记录一下从官方第三人称模板简化出来的角色移动控制。
实现效果
最终实现的效果是,当按下w时,角色向当前相机方向移动;按ad时,向当前相机方向左右转;按s时向相机移动。
角色控制演示
环境
unity2021.3.5f1c1版本普通3d工程
插件使用到了cinemachine2.8.6,视频中的相机移动为cinemachine的自由视角相机,但不重要
进入正题
一个简单的场景
角色上挂载了Animator(用于控制移动动画),Character Controller(unity自带的角色控制器),Player Controller(自己写的控制脚本)
角色的动画状态机,当speed大于0.3时从站立状态转移到移动状态,移动状态由一个混合了走路和奔跑的混合树完成。在脚本中通过对speed赋值来控制角色移动。
然后是代码部分
public Camera playerFollowCamera;
public Animator animator;
[Tooltip("How fast the character turns to face movement direction")]
[Range(0.0f, 0.3f)]
public float RotationSmoothTime = 0.12f;
声明公开变量
private float _rotationVelocity;
private float _targetRotation = 0.0f;
private CharacterController _controller;
private int _aniId_speed;
private int _aniId_hurt;
private int _aniId_atk;
private int _aniId_beHit;
私有变量,包括了角色控制器、运动参数和状态机参数的id
// Start is called before the first frame update
void Start()
{
InitComponents();
InitAnimator();
}
// Update is called once per frame
void Update()
{
PlayerMove();
}
在start中获取角色控制器,并计算出状态机参数的哈希值,在update中调用移动函数
private void InitComponents()
{
_controller = GetComponent<CharacterController>();
}
private void InitAnimator()
{
_aniId_speed = Animator.StringToHash("speed");
_aniId_atk = Animator.StringToHash("atk");
_aniId_hurt = Animator.StringToHash("hurt");
_aniId_beHit = Animator.StringToHash("be hit");
}
角色移动函数
private void PlayerMove()
{
var ad = Input.GetAxis("Horizontal");
var ws = Input.GetAxis("Vertical");
if (ad == 0 && ws == 0) return;
Vector3 inputDirection = new Vector3(ad, 0.0f, ws).normalized;
_targetRotation = Mathf.Atan2(inputDirection.x, inputDirection.z) * Mathf.Rad2Deg + playerFollowCamera.transform.eulerAngles.y;
float rotation = Mathf.SmoothDampAngle(transform.eulerAngles.y, _targetRotation, ref _rotationVelocity, RotationSmoothTime);
transform.rotation = Quaternion.Euler(0.0f, rotation, 0.0f);
Vector3 targetDirection = Quaternion.Euler(0.0f, _targetRotation, 0.0f) * Vector3.forward;
// move the player
_controller.Move(targetDirection.normalized * Time.deltaTime);
animator.SetFloat(_aniId_speed, new Vector3(ad, 0, ws).magnitude);
}
获取两个轴的输入,当玩家有输入时,进行旋转和移动。不进行是否有输入的判断的话,会出现相机移动角色自动跟随转变方向的效果。
然后计算出要转动的角度。使用了平滑过度,可以根据需要调整RotationSmoothTime和_rotationVelocity
再计算出欧拉角与forward做乘算,就得到了带有合适转动的位移向量。
因为角色应用了根运动,跑动的位移由动画控制,所以直接调用控制器的move即可,不需要在这里指定移动速度。
最后设置动画状态机的参数,让角色播放移动动画。