一.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,暫時沒有資源,沒有做
寫了半天必須配張圖啊