在测试ECS时发现网上的文档和教程,包括个人的和官方的都无法正常使用。原因在于,只写了代码的文档没有明确指出所使用的ECS版本,由于当前ECS还是预览功能,升级速度很快,版本差异大,所以很多都已经不适用了。官方的demo集合可以使用,但是必须升级到2019.1以后的版本。
个人测试项目采用Unity 2019.3.0a8
ECS版本如图:
如果有编译错误,需要检查下面的依赖包是否也和我的一样。
另外在创建完创建一堆cube的demo之后,发现cube没有显示,
没有Render组件。查阅文档之后发现render相关的组件还需要额外下载包如图:
测试结果:
传统Mono方式,创建4900个Cube并做单一运动。如下图:
ECS模式,创建40000个Cube并做单一运动。如下图:
ECS+JobSystem,创建62500个Cube并做单一运动。如下图:
ECS+JobSystem+BurstCompile,创建72900个Cube并做单一运动。如下图:
以下内容摘自官方文档
作业系统是通过创建多个作业来实现程序的"多线程"。
常说的多线程是指利用CPU的能力在多个核心上同时执行多个线程,都是并行执行的。
当线程数多于CPU核心的时候,会出现抢夺资源的情况,时从而导致频繁的上下文切换。
上下文切换是这样一个过程:通过执行保存线程的部分状态,然后处理另一个线程,然后重构第一个线程,然后继续处理它。这样其实是很消耗资源的。
而作业系统是在每个CPU逻辑核心上都创建一个工作线程,用来避免上下文切换(反正我没看懂)。当多个作业之间有依赖关系时,作业系统可以通过调整依赖项来保证被依赖的作业先完成。
作业系统是如果做到线程安全的:
多线程代码会导致竞态条件(作业系统),简单地说就是一个线程的输出依赖于另一个线程,就会产生竞态条件。而且这种问题出现时很难修复,因为它取决于运行时间,并不是每次都能遇到,而且调试会导致程序暂停,那么时间也就变了,无法复现问题。
作业系统的解决方法是,向每个作业发送所需数据的副本而不是发送主线程中对数据的引用。
An example of multiple jobs and dependencies
Job code:
// Job adding two floating point values together
public struct MyJob : IJob
{
public float a;
public float b;
public NativeArray<float> result;
public void Execute()
{
result[0] = a + b;
}
}
// Job adding one to a value
public struct AddOneJob : IJob
{
public NativeArray<float> result;
public void Execute()
{
result[0] = result[0] + 1;
}
}
Main thread code:
// Create a native array of a single float to store the result in. This example waits for the job to complete
NativeArray<float> result = new NativeArray<float>(1, Allocator.TempJob);
// Setup the data for job #1
MyJob jobData = new MyJob();
jobData.a = 10;
jobData.b = 10;
jobData.result = result;
// Schedule job #1
JobHandle firstHandle = jobData.Schedule();
// Setup the data for job #2
AddOneJob incJobData = new AddOneJob();
incJobData.result = result;
// Schedule job #2
JobHandle secondHandle = incJobData.Schedule(firstHandle);
// Wait for job #2 to complete
secondHandle.Complete();
// All copies of the NativeArray point to the same memory, you can access the result in "your" copy of the NativeArray
float aPlusB = result[0];
// Free the memory allocated by the result array
result.Dispose();