一、需求:
需要做基于BIM的大场景展示,先不提功能,模型展示就是个问题。基本核心的优化是LOD,把Revit通过3dmax转换,处理,分解成一个个模型单元,再在Unity中进行场景重建。这个已经完成了。在Unity中再结合LOD,能够一定程度上优化性能,提高帧率,但是不够。现在是1000w个点,从15FPS提高到25FPS,这时因为用了LOD,内存中有2000w个点了。
在路上开车开车就想起了ECS,是否能够用这种宣传上适合大规模重复类似行为的场景的技术来动态控制模型的LOD呢,而且我还需要从内存中动态加载卸载模型的功能。
第一次知道ECS是半年前了,虽然公司的Unity也升级到2019.3了,但是一直没有时间好好学习一下ECS。其实应该说是找不到必要性吧,最近学了Maxscript和Revit二次开发,说明时间不是问题,优先级才是原因。有必要,任何技术都会马上去学习的。另外UE5宣传片看到了,似乎能完全解决大量模型加载的问题,下次去学一下吧。
二、学习与练习
现在学习东西都是在B站上了,https://www.bilibili.com/video/BV1W54y197sb?from=search&seid=16767424865285994023,
把视频的内容整理一下,同时把碰到的问题记录一下。
1.安装需要的包
这里就碰到一个问题,Burst安装后,会出现问题:
The type or namespace name 'CompilerServices' does not exist in the namespace
总共有好几条,google了一下,参考:https://forum.unity.com/threads/missing-references-in-the-collections-package.847027/,将Burst升级到最新版本1.3.0,默认安装的是verified-1.2.3版本
-------------------------------------------------------------------------------------------------------
官方例子:https://github.com/Unity-Technologies/EntityComponentSystemSamples
安装一个就行,已经安装了,就没操作过了。
2.ComponentSystem / JobComponentSystem / SystemBase
最上面的视频中的代码是用ComponentSystem
public class LevelUpSystem : ComponentSystem
{
protected override void OnUpdate()
{
Entities.ForEach((ref LevelComponent levelComponent) =>
{
levelComponent.Level += 1f * Time.DeltaTime;
});
}
}
public struct LevelComponent : IComponentData
{
public float Level;
}
另一个教程里面的是JobComponentSystem
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Entities;
using Unity.Jobs;
using Unity.Transforms;
using System;
//public class VelocityScript : MonoBehaviour,IConvertGameObjectToEntity
//{
// public float Value;
// public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
// {
// dstManager.AddComponent(entity);
// dstManager.SetComponentData(entity,new Velocity(){ Value=Value});
// }
//}
[GenerateAuthoringComponent]
struct Velocity:IComponentData
{
public float Value;
}
class ApplyVelocitySystem : JobComponentSystem
{
//struct ApplyVelocityJob : IJobForEach
//{
// public float deltaTime;
// public void Execute(ref Translation translation, ref Velocity velocity)
// {
// translation.Value += velocity.Value * deltaTime;
// }
//}
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
//var job = new ApplyVelocityJob();
//job.deltaTime = Time.DeltaTime;
//return job.Schedule(this, inputDeps);
float deltaTime = Time.DeltaTime;
return Entities.ForEach((ref Translation translation, in Velocity velocity) =>
{
translation.Value += velocity.Value * deltaTime;
}).Schedule(inputDeps);
}
}
这个视频是官方(中国)讲解2019.3的,应该是比较新的。
然后查询了一下二则的区别,unity论坛中提到SystemBase(https://forum.unity.com/threads/jobcomponentsystem-vs-componentsystem-for-singlethread.850381/#post-5610469)。
测试了一下,2w个Capsule物体移动, 感觉ComponentSystem最慢了 15-20FPS,JobComponentSystem和SystemBase都是25-35。
有人专门也问了一下用哪里(https://forum.unity.com/threads/is-there-any-difference-between-systembase-jobcomponentsystem-and-componentsystem-anymore.892978/#post-5868991),楼主很较真,有点争执,就是不求甚解听官方的就行和一定要知道为什么的人之间的争执。反正,结论就是用 SystemBase,另外两个迟早会被删除掉。
现在的Unity.Entities(preview.6-0.10.0)的文档中就是这么说的(https://docs.unity3d.com/Packages/com.unity.entities@0.10/manual/ecs_systems.html?_ga=2.71828115.1406000335.1590492138-1802642859.1577498182)。
SystemBase的话,还有的问题,用Run()还是Schedule(),还是ScheduleParallel()?
3.Samples
有个博客写的不错,https://blog.csdn.net/qq_30137245/article/details/99071697,就按照这个顺序学习,磨刀不误砍柴工,前期学的越充分,动起手来越顺手。
三、问题