对《[Unity官方实例教程 秘密行动] Unity官方教程《秘密行动》(十二) 角色移动》的一些笔记和个人补充,解决角色在地形上移动时穿透问题。
这里素材全是网上找的。
教程看这里:
[Unity官方实例教程 秘密行动] Unity官方教程《秘密行动》(九) 角色初始设定
一、模型设置:
1.首先设置模型的动作无限循环。
不设置的话就会出现类似跑步只跑了第一步有动作后面无动作直接滑过去的样子。
1.1.点选模型的动作文件。
1.2.在“Inspector”面板点击“Animations”。
1.3.勾上“Loop Time”。
2.设置模型的比例。
可以把模型调整到合适的大小。
1.1.点选模型的动作文件。
1.2.在“Inspector”面板点击“Model”。
1.3.调整“Scale Factor”里的数值。
2.角色(Rigidbody)的移动。
在视屏里的例子中,玩家的移动的模型里自带了位移的。
如果自己手里的模型只是原地动作的话,可以加入以下代码,实现前进并平滑转弯的效果。
2.1.在 PlayerMovement 类里,增加角色移动速度字段。
/// <summary> /// 角色移动速度。 /// </summary> public float _speedMove = 15f;
2.2.主要使用 rigidbody.MovePosition() 方法进行移动,具体查文档。
/// <summary> /// 角色移动。 /// </summary> /// <param name="horizontal">横向。</param> /// <param name="vertical">纵向。</param> private void Moving(float horizontal, float vertical) { //移动的目标位置。 var targetPosition = new Vector3(horizontal * this._speedMove, 0f, vertical * this._speedMove); //更新刚体位置为目标位置。 rigidbody.MovePosition(rigidbody.position + targetPosition * Time.deltaTime); }
2.3.将 Moving() 方法在 MovementManagement 的最后面调用。
/// <summary> /// 让角色移动,并且要让它动作平滑,有良好的手感。 /// </summary> /// <param name="horizontal">横向。</param> /// <param name="vertical">纵向。</param> private void MovementManagement(float horizontal, float vertical) { //判断玩家是否在横向或者纵向移动。 if (Math.Abs(horizontal) > 0f || Math.Abs(vertical) > 0f) { //角色转向。 Rotating(horizontal, vertical); //角色速度。 this._animator.SetFloat(this._hash._speedFloat, 1f, this._speedDampTime, Time.deltaTime); //角色移动。 Moving(horizontal, vertical); } else { //如果没有获取到用户输入时,将速度设置成 0。 this._animator.SetFloat(this._hash._speedFloat, 0f); } }
现在,角色已经可以在 Unity3d 里自制的地形里移动了,但是有个问题,角色碰到斜坡等地方的时候,会直接穿过去。
3.角色(Character Controller)的移动。
Unity3d 里有专门针对角色移动的控制器CharacterController。
3.1.删除 Rigidbody 与 Collider 组件。
3.2.增加CharacterController。
通过修改 Center 的值来调整自带的碰撞器的位置。
修改 Radius 与 Height 来调整碰撞器的大小。
如下图:
3.3.代码调整。
3.3.1.Moving() 方法修改成如下
使用 CharacterController 的SimpleMove方法进行移动,参数则表示相对原坐标的偏移量。
/// <summary> /// 角色移动。 /// </summary> /// <param name="horizontal">横向。</param> /// <param name="vertical">纵向。</param> private void Moving(float horizontal, float vertical) { var controller = GetComponent<CharacterController>(); //设置移动向量。 var moveDirection = new Vector3(horizontal, 0, vertical); /* * 参数:移动的偏移。 * 例:假如角色向前 5 步,向右 3 步。 * 则:相对原坐标的偏移量是:Z 轴是 5, X 轴是 3 。 */ controller.SimpleMove(moveDirection * this._speedMove); }
3.3.2.由于没有了Rigidbody,所以转向方法void Rotating(float horizontal, float vertical)也需要做调整。
rigidbody.rigidbody.rotation 修改成 transform.rotation。
var newRotation = Quaternion.Lerp(rigidbody.rotation, targetRotaion, this._turnSmoothing * Time.deltaTime);
rigidbody.MoveRotation(newRotation);
修改成
transform.rotation = newRotation;
完整Rotating()方法如下:
/// <summary> /// 角色转向。 /// </summary> /// <param name="horizontal">横向。</param> /// <param name="vertical">纵向。</param> private void Rotating(float horizontal, float vertical) { //目标方向。 var targetDirection = new Vector3(horizontal, 0f, vertical); /* * 创建目标旋转值 并假设Y轴正方向为"上"方向。 * 函数参数解释: LookRotation(目标方向为"前方向", 定义声明"上方向") */ var targetRotaion = Quaternion.LookRotation(targetDirection, Vector3.up); /* * 创建新旋转值 并根据转向速度平滑转至目标旋转值。 * 函数参数解释: Lerp(角色刚体当前旋转值, 目标旋转值, 根据旋转速度平滑转向) */ var newRotation = Quaternion.Lerp(transform.rotation, targetRotaion, this._turnSmoothing * Time.deltaTime); //更新游戏对象旋转角度为新旋转角度。 transform.rotation = newRotation; }