代码地址
https://github.com/Unity-Technologies/EntityComponentSystemSamples/tree/master/UnityPhysicsSamples/Assets/Demos/6.%20Use%20Cases/CharacterController
系统构成
输入系统
需要在ProjectSettings.asset中加入UNITY_INPUT_SYSTEM_EXISTS宏定义
scriptingDefineSymbols:
1: UNITY_POST_PROCESSING_STACK_V2;UNITY_INPUT_SYSTEM_EXISTS
输入的配置在Common/InputActions
DemoInputGatheringSystem 负责收入的接收,并写入CharacterControllerInput
角色控制系统
角色控制主要围绕CharacterControllerInternalData组件进行计算,Update收集并组成CharacterControllerJob,由这个Job完成运算工作
角色移动控制
- 落地检查CheckSupport:
- 碰撞检查,通过向下偏移ContactTolerance的射线检查是否有碰撞
- 如果无碰撞,设置状态为在空中,返回
- 根据碰撞点创建接触面信息列表constraints
- 由SimplexSolver.Solve求出支撑面,和速度
- 如果速度和初始速度没明显变化,一般为支撑面的坡度太大(近乎垂直,见代码Solve1D,速度会减去支撑面法向乘以速度),状态设置为在空中
- 如果速度很小,则状态设置为被支撑
- 否则跟最大滑坡角度比较,决定是被支撑还是在滑坡
- HandleUserInput输入处理
- 根据输入确定移动方向和是否跳跃
- 旋转角色,见"角色旋转控制",同时要维持之前的速度方向(Velocity.Angular = -userRotationSpeed * up)
- 求出linearVelocity
- 如果不是在空中,用 CalculateMovement, 根据角色方向和所在平面重新计算速度
- CollideAndIntegrate 碰撞处理并算出最终位置
角色旋转控制
Mouse Delta 被归一化了
Delta Mouse说明:https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/manual/Mouse.html
应该是屏幕像素差
计算如下:
bool haveInput = (math.abs(horizontal) > float.Epsilon);
if (haveInput)
{
var userRotationSpeed = horizontal * ccComponentData.RotationSpeed;
ccInternalData.Velocity.Angular = -userRotationSpeed * up;
ccInternalData.CurrentRotationAngle += userRotationSpeed * DeltaTime;
}
手的旋转控制
原有角度乘以绕x轴旋转的矩阵
float a = -input.Looking.y;
gunRotation.Value = math.mul(gunRotation.Value, quaternion.Euler(math.radians(a), 0, 0));
Unity.Mathematics缺少将四元素转欧拉的函数,这个在Unity.Physics.Math中有说明
// Note: taken from Unity.Animation/Core/MathExtensions.cs, which will be moved to Unity.Mathematics at some point
// after that, this should be removed and the Mathematics version should be used
#region toEuler