Unity Entities|0.2.0-preview.18
JobComponentSystem支持俩种类型的lambda表达式:
1. JobComponentSystem.Entities.ForEach(lambda)依赖于Entities,返回Entities集合通过lambda进行选择筛选
2.JobComponentSystem.Job.WithCode(lambda) 依赖于IJob且执行一次
然后呢俩种定义方式都可以通过
Schedule()或者Run()方式进行运行。区别就是Run()是立即执行。
这里官方还介绍了来个关键之使用 ref 和 in。ref可以用来写更改数据,in用来只读数据的。
Entities.ForEach example:
class ApplyVelocitySystem : JobComponentSystem
{
protected override JobHandle OnUpdate(JobHandle inputDependencies)
{
var jobHandle = Entities
.ForEach((ref Translation translation,
in Velocity velocity) =>
{
translation.Value += velocity.Value;
})
.Schedule(inputDependencies);
return jobHandle;
}
}
Job.WithCode example:
public class RandomSumJob : JobComponentSystem
{
private uint seed = 1;
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
Random randomGen = new Random(seed++);
NativeArray<float> randomNumbers
= new NativeArray<float>(500, Allocator.TempJob);
JobHandle generateNumbers = Job.WithCode(() =>
{
for (int i = 0; i < randomNumbers.Length; i++)
{
randomNumbers[i] = randomGen.NextFloat();
}
}).Schedule(inputDeps);
NativeArray<float> result
= new NativeArray<float>(1, Allocator.TempJob);
JobHandle sumNumbers = Job.WithCode(() =>
{
for (int i = 0; i < randomNumbers.Length; i++)
{
result[0] += randomNumbers[i];
}
}).Schedule(generateNumbers);
sumNumbers.Complete();
UnityEngine.Debug.Log("The sum of "
+ randomNumbers.Length + " numbers is " + result[0]);
randomNumbers.Dispose();
result.Dispose();
return sumNumbers;
}
}
关于Entities.ForEach的一些查询实体的方法:
这主要用于获取到执行Entities
WithAll<T>:查找含有T类型的
component
WithAny<T,U>:同时查询多个不同类型的
component,也可以只查询一个,作用等同于WithAll<T>
WithNone<T>
:查询不包含有此类型组件
WithChangeFilter<T>
:理解的意思感觉就是在块中☞之前修改过的数据的component
WithSharedComponentFilter
:顾名思义就是选择是shared component的
WithStoreEntityQueryInField
:存储查询到的Entities可以进行一些查询操作
这里官方也有一个很重要的Tips:
WithNone<T>
使用不注意可能会和WithAll<T>以及WithAny<T,U>引起冲突。这里注意一下好了。
使用举例:
return Entities.WithAll<LocalToWorld>()
.WithAny<Rotation, Translation, Scale>()
.WithNone<LocalToParent>()
.ForEach((ref Destination outputData,
in Source inputData) =>
{
/* do some work */
})
.Schedule(inputDeps);
EntityQuery 使用举例:
private EntityQuery query;
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
int dataCount = query.CalculateEntityCount();
NativeArray<float> dataSquared
= new NativeArray<float>(dataCount, Allocator.Temp);
JobHandle GetSquaredValues = Entities
.WithStoreEntityQueryInField(ref query)
.ForEach((int entityInQueryIndex, in Data data) =>
{
dataSquared[entityInQueryIndex] = data.Value * data.Value;
})
.Schedule(inputDeps);
return Job
.WithCode(() =>
{
//Use dataSquared array...
var v = dataSquared[dataSquared.Length -1];
})
.WithDeallocateOnJobCompletion(dataSquared)
.Schedule(GetSquaredValues);
}
Shared component 使用示例:
public class ColorCycleJob : JobComponentSystem
{
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
List<Cohort> cohorts = new List<Cohort>();
EntityManager.GetAllUniqueSharedComponentData<Cohort>(cohorts);
NativeList<JobHandle> dependencies
= new NativeList<JobHandle>();
foreach (Cohort cohort in cohorts)
{
DisplayColor newColor = ColorTable.GetNextColor(cohort.Value);
JobHandle thisJobHandle
= Entities.WithSharedComponentFilter(cohort)
.ForEach((ref DisplayColor color) => { color = newColor; })
.Schedule(inputDeps);
dependencies.Add(thisJobHandle);
}
return JobHandle.CombineDependencies(dependencies);
}
}
捕获之后参数方法:
这主要用于获取到Entities执行完lambda之后进行的一些参数设置
WithReadOnly(myvar):改变获取到的数据访问限制给成只读
WithDeallocateOnJobCompletion(myvar):完成操作之后释放本容器
WithNativeDisableParallelForRestriction(myvar):官方说法挺晦涩,感觉说人话就是可以允许多个线程访问本组数据,但是可能会额外消耗一点性能
WithNativeDisableContainerSafetyRestriction(myvar):这个官方大体的意思感觉就是关闭多线程访问保护你们尽管来,不要命的一种操作
WithNativeDisableUnsafePtrRestrictionAttribute(myvar):理解起来太头疼了(官方直译:
允许您使用本机容器提供的不安全指针。不正确的指针使用可能导致应用程序中出现细微的错误、不稳定和崩溃)
Job options介绍:
JobHandle Schedule(JobHandle):
Entities.ForEach 中:可以并行执行在线程上执行lambda函数
Job.WithCode 中:执行一个单独的实例在后台线程中
void Run():
Entities.ForEach 中:执行一次lambda操作,不接受参数,也不返回参数
Job.WithCode 中:执行一次
WithBurst(FloatMode, FloatPrecision, bool):设置Brust编译器信息:
floatMode :浮点数优化模式,快速模式速度快但是也可能产生不必要的错误
floatPrecision :设置浮点数学精度
synchronousCompilation:立即编译该函数,而不是调度该函数以供以后编译。
WithoutBurst():禁止使用Brust编译器
WithStructuralChanges()
:在主线程上执行lambda函数并禁用Burst,以便可以对函数中的实体数据进行结构更改。为了获得更好的性能,可以使用一个并发的EntityCommandBuffer
WithName(string):
将指定的字符串指定为生成的作业类的名称。指定名称是可选的,但可以帮助在调试和分析时识别函数。