示例主要点:
1.键鼠的输入
可以直接调用Input类,和在托管代码中调用是一样的
//inputState是一个组件,来保存键鼠的数据
inputState.Horizontal = Input.GetAxis("Horizontal");
inputState.Vertical = Input.GetAxisRaw("Vertical");
inputState.MouseX = Input.GetAxisRaw("Mouse X");
inputState.MouseY = Input.GetAxisRaw("Mouse Y");
inputState.Space = Input.GetKeyDown(KeyCode.Space);
通过查看源码知道,Input类调用的是InputUnsafeUtility类,也就是键鼠的输入是一个非托管代码的封装,所以在ecs中可以直接调用,并且在函数中可以加上BurstCompile这个标签,下面是Input类的源码
public static float GetAxis(string axisName)
{
return InputUnsafeUtility.GetAxis(axisName);
}
public static float GetAxisRaw(string axisName)
{
return InputUnsafeUtility.GetAxisRaw(axisName);
}
2.相机的控制
因为相机是托管对象,需要像之前给托管对象赋值一样,函数不能打这个BurstCompile标签,主要的逻辑是获取实体,然后通过人物的位置和键鼠的数组,计算相机的位置,代码中采用了一种新的查询方式,使用ComponentLookup组件获取实体的位置组件
//访问了托管代码,不能添加爆发编译标签
public void OnUpdate(ref SystemState state)
{
//判断相机是否已经初始化,防止生命周期的问题
if (Camera.main != null)
{
//获取所有LocalTransform组件,然后通过实体id找到对应实体的这个组件
var transformLookup = SystemAPI.GetComponentLookup<LocalTransform>(true);
//获取人物挂载Controller组件的实体,场景中只有一个
var controllerEntity = SystemAPI.GetSingletonEntity<Controller>();
//获取Controller组件,场景中只有一个
var controller = SystemAPI.GetSingleton<Controller>();
//然后通过实体id找到对应实体的这个组件
var controllerTransform = transformLookup[controllerEntity];
//找到相机的托管对象
var cameraTransform = Camera.main.transform;
//位置赋值
cameraTransform.position = controllerTransform.Position;
//计算旋转
cameraTransform.rotation = math.mul(controllerTransform.Rotation,
quaternion.RotateX(controller.CameraPitch));
}
}
上面的这个查询controllerTransform组件的逻辑,有点像3DMax中的选取一个边,然后点击循环状态,所有同类型的边都找到了,然后输入id,然会需要的组件,个人理解
3.控制System执行的顺序
通过使用 [UpdateAfter(typeof(ControllerSystem))],标识该system的update 在ControllerSystem执行之后执行,也就是人物移动之后,在设置相机的状态
[UpdateAfter(typeof(ControllerSystem))]
public partial struct CameraSystem : ISystem
标签: UpdateAfter,UpdateBefore全部继承自ISystemOrderAttribute,系统排序属性