-
准备工作
-
改变实体的Transform
-
新建一个System,尝试控制实体的位置偏移,控制Translation组件,这个是Unity自身Transform下的默认组件
改变实体位置
public class TestConterollerComponten : ComponentSystem {
protected override void OnUpdate()
{
Entities.ForEach((ref Translation translation) =>
{
translation.Value = new Unity.Mathematics.float3(1, 1, 1);
});
}
}
改变实体角度
把一个GameObject转成Entity后,Translation组件它默认是拥有的,但是RotationEulerXYZ 角度组件需要我们手动添加
上一章我们讲过,要用代理类,添加我们写的数据组件,RotationEulerXYZ 也是一样的
代理类
public class TestTransformCorrelation : MonoBehaviour, IConvertGameObjectToEntity
{
public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
{
dstManager.AddComponentData(entity, new RotationEulerXYZ());
}
}
修改实体的角度
public class TestConterollerComponten : ComponentSystem {
protected override void OnUpdate()
{
Entities.ForEach((ref RotationEulerXYZ RotationEulerXYZ) =>
{
RotationEulerXYZ.Value = new Unity.Mathematics.float3(0,45,0);
});
}
}
使用ECS预制件生成1w个方块
- 首先新建一个Cube ,并把它设置成预制件
- 新建一个控制脚本Manager,这一部分跟着写就可以了,后面会对EntityManager的API做更多的介绍
public GameObject cube;
public float interval, sum;
void Start () {
// 把普通预制件转成ECS预制件
GameObjectConversionSettings tempSetting = GameObjectConversionSettings.FromWorld(World.DefaultGameObjectInjectionWorld,null);
Entity tempEntityPrefab = GameObjectConversionUtility.ConvertGameObjectHierarchy(cube, tempSetting);
// 获得EntityManager
EntityManager entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
Translation tempTranslation = new Translation();
tempTranslation.Value.x = -1;
for (int i = 0; i < sum; i++)
{
for (int j = 0; j < sum; j++)
{
// 生成实体
Entity entityCube = entityManager.Instantiate(tempEntityPrefab);
tempTranslation.Value.x += interval;
// 使用EntityManager,修改实体的位置
entityManager.SetComponentData(entityCube, tempTranslation);
}
tempTranslation.Value.x =-1;
tempTranslation.Value.y += interval;
}
}
- 把预制件拖进脚本里
- 间隔interval设置成2,sum设置100,这样就把1w个方块平铺排开了
使用普通方式生成1W个方块
public GameObject cubePrefab;
public float interval, sum;
void Start()
{
Vector3 tempVector3 = new Vector3(-interval,0,0);
for (int i = 0; i < sum; i++)
{
for (int j = 0; j < sum; j++)
{
//GameObject entityCube = GameObject.CreatePrimitive(PrimitiveType.Cube);
GameObject entityCube = GameObject.Instantiate(cubePrefab);
tempVector3.x += interval;
entityCube.transform.position = tempVector3;
}
tempVector3.x = -1;
tempVector3.y += interval;
}
}
运行后性能对比
同样是生成一万个方块,让相机渲染到所有方块
普通方式fps只有70
ECS生成fps翻了一倍
通过JobSystem和Burst编译器进一步优化性能
我们新建一个JobSystem,我们在通过Entities把所有的方块的Burst打开
运行后fps应该会再提升一点
public class ECSJobComponentSystem : JobComponentSystem
{
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
JobHandle tempJobHandle = Entities.ForEach((ref Translation translation ) =>{})
//打开Burst
.WithBurst()
.Schedule(inputDeps);
return tempJobHandle;
}
}
使用批处理处理GpuInstancing优化性能
CPU----数据---->GPU----渲染---->屏幕
游戏内对象越多,需要提交的数据就越多,批处理就是打包多个数据成一个数据提交,降低数据提交次数
批处理有静态\动态\GpuInstancing三种
- 还是在ECS的基础上 1w个cube渲染,需要我们新建一个材质球,给材质球打开批处理
FPS到了360多,又涨了一倍多,整体性能翻倍
- 那么如果只是用批处理,不用ECS,性能会有这么大的提升么?
开了批处理,性能肯定是有所提升的,我用普通的生成方式,生成1w个方块,也同时给这些方块的材质球打开了批处理,fps从70提升到了80左右
所以主要还是ESC对性能的帮助,才能让Unity运行速度更起飞