一.CharacterController组件驱动
这是常用的角色控制方式,但是最大的缺点就是无法被力所驱动,因此,很难做出冲撞的抵触效果
另外这里要说明:
第一种:characterController.SimpleMove(Speed);
第二种:characterController.Move(Speed*deltaTime);
发生的问题:第一种和第二种垂直移动效果不同。
解决:官方文档:第一种始终使用的是系统的默认垂直加速度,而第二种要自己实现。
using System.Collections; using System.Collections.Generic; using UnityEngine; /// <summary> /// 角色控制器控制角色物理效果 /// </summary> public class PlayerControllerTest00 : MonoBehaviour { public float speed = 6.0F; public float jumpSpeed = 8.0F; public float gravity = 20.0F; private Vector3 moveDirection = Vector3.zero; void Update() { CharacterController controller = GetComponent<CharacterController>(); if (controller.isGrounded) { moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")); moveDirection = transform.TransformDirection(moveDirection); moveDirection *= speed; if (Input.GetKeyDown(KeyCode.Space)) moveDirection.y = jumpSpeed; } moveDirection.y -= gravity * Time.deltaTime; controller.Move(moveDirection * Time.deltaTime); } }
这里借用了某位老兄的代码:https://www.cnblogs.com/ChenZiRong1999/p/13395132.html
这里产生了一个疑问,如果有知道的网友,给我留个评论:
遇到一个玄学Bug,用角色控制器做了一个角色控制组件,采用两种方式:
第一种:角色外层根用空物体然后挂上组件,动画模型物体作为子物体。
第二种:动画模型物体直接为根物体,并且模型没有位移动画。
移动代码charactorController.SimpleMove(verticalSpeed+horizonSpeed);
发生的问题:第一种比第二种飘,也就是从一个物体边缘走出去落下的过程中第一种很飘,貌似垂直速度不符合效果。
二.刚体驱动
这里使用胶囊碰撞体加刚体组件的方式来实现,从而可以实现冲撞效果,缺点是需要大量的时间来调整,而且代码干涉物理效果,并且物理更新与渲染更新并不同步,因此角色的移动会相对看起来比较抖动,当然无论代码是放在FixedUpdate()还是Update()都和很难完全消除抖动,更多的是从相机动手,让相机的跟随抵消不同步抖动带来的视觉干扰。
在刚体下有几种移动方式,具体如代码中所示。
using System.Collections; using System.Collections.Generic; using UnityEngine; /// <summary> /// 刚体角色控制器控制角色 /// </summary> public class PlayerControllerTest01 : MonoBehaviour { Rigidbody rigid; public float moveSpeed; private Vector3 moveDirection = Vector3.zero;//角色的方向 float moveScale = 0; private void Awake() { rigid = GetComponent<Rigidbody>(); } private void Update() { //跳跃:为刚体施加一个向上的力:该力是由向上的跳跃速度和在刚体原速度方向上的一个速度合成的 //VelocityChange是一个瞬时速度 if (Input.GetKeyDown(KeyCode.Space)) { rigid.AddForce(transform.up * 20 /*+ rigid.velocity.normalized * directionalJumpFactor*/, ForceMode.VelocityChange); } moveScale = 0; if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.S)) { moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")); moveScale = 1; } //旋转,使用刚体的旋转 Quaternion rot = Quaternion.Euler(0, Vector3.SignedAngle(Vector3.forward, moveDirection, Vector3.up), 0);//目标旋转 Quaternion currentRot = Quaternion.RotateTowards(rigid.rotation, rot, Time.deltaTime * 600);//中间插值旋转 rigid.MoveRotation(currentRot); //水平移动 Vector3 v = Vector3.Project(rigid.velocity, transform.forward); float s = moveSpeed == 0 ? 0 : 1 - v.magnitude / moveSpeed; //rigid.AddForce(transform.forward * moveScale * s, ForceMode.VelocityChange);//第一种:力驱动,好处:比较真实具体移动交给物理系统;缺点:不好控制,容易滑动 //rigid.velocity = transform.forward * 10 * moveScale + Vector3.up * rigid.velocity.y;//第二种:速度设置,好处:直接设置速度;缺点:直接干涉物理速度,抖动失真 //if (moveScale == 1) rigid.MovePosition((rigid.position + transform.forward * moveSpeed * Time.deltaTime));//第三种:直接物理位置,好处:直接移动,缺点:目前描述不出来 } private void FixedUpdate() { if (moveScale == 1) rigid.MovePosition((rigid.position + transform.forward * moveSpeed * Time.fixedDeltaTime)); } }
同样,参考某位老兄的代码:https://blog.csdn.net/qq_38327432/article/details/91561247
二.动画驱动
顾名思义,这里代码只是改变动画状态机的状态参数,移动动画自身带有位移,这样的好处就是动画效果和位移等效果完美契合,整个的动画都交由动画师来完成,缺点是整个过程的动画参数量大,至于动画遇到的问题,做的少,暂时不知道。代码demo,暂时没有资源,没有做
写了半天必须配张图啊