2-1 Using Gizmos To Visualise Code
本章使用Unity提供的Gizmos工具來視覺化Code,比方說我們要製作一個點擊敵人後,人物會移動敵人前幾公尺的距離,好讓玩家可以放出範圍技之類的功能。撰寫這項功能時,我們可以用Gizmos工具輔助我們從視覺化看出效果如何,如下圖這樣。
我們使用兩個變數walkMoveStopRadius、attackMoveStopRadius,分別控制人物移動的停止點與點擊敵人的停止點,如上圖標示人物在敵人(紅色球球)前一段距離停下來,紅色虛線框繪製出停止的範圍,可以想像成發動範圍技的適合範圍。
以下完整程式碼跟註解。
我們使用兩個變數walkMoveStopRadius、attackMoveStopRadius,分別控制人物移動的停止點與點擊敵人的停止點,如上圖標示人物在敵人(紅色球球)前一段距離停下來,紅色虛線框繪製出停止的範圍,可以想像成發動範圍技的適合範圍。
以下完整程式碼跟註解。
using System; using UnityEngine; using UnityStandardAssets.Characters.ThirdPerson; [RequireComponent(typeof (ThirdPersonCharacter))] public class PlayerMovement : MonoBehaviour { [SerializeField] float walkMoveStopRadius = 0.2f; [SerializeField] float attackMoveStopRadius = 5f; ThirdPersonCharacter theThirdPersonCharacter; // A reference to the ThirdPersonCharacter on the object CameraRaycaster cameraRaycaster; Vector3 currentDestination, clickPoint; bool isInDircetMode = false; private void Start() { cameraRaycaster = Camera.main.GetComponent(); theThirdPersonCharacter = GetComponent (); currentDestination = transform.position; } // Fixed update is called in sync with physics private void FixedUpdate() { if(Input.GetKeyDown(KeyCode.G)){ //切換GamePad Mode isInDircetMode = !isInDircetMode; //解決Gamepad模式切換時,人物角色會自動回到上一個滑鼠點擊位置的Bug currentDestination = transform.position; } if (isInDircetMode) { ProcessDirectMovement (); } else { ProcessMouseMovement (); } } private void ProcessDirectMovement(){ // read inputs float h = Input.GetAxis("Horizontal"); float v = Input.GetAxis("Vertical"); // calculate camera relative direction to move: Vector3 cameraForward = Vector3.Scale(Camera.main.transform.forward, new Vector3(1, 0, 1)).normalized; Vector3 movement = v*cameraForward + h*Camera.main.transform.right; theThirdPersonCharacter.Move(movement, false, false); } private void ProcessMouseMovement(){ if (Input.GetMouseButton(0)) { //print("Cursor raycast hit" + cameraRaycaster.currentLayerHit); clickPoint = cameraRaycaster.hit.point; switch (cameraRaycaster.currentLayerHit) { case Layer.Walkable: //取得滑鼠點擊到的物件的位置 currentDestination = ShortDestination (clickPoint, walkMoveStopRadius); break; case Layer.Enemy: currentDestination = ShortDestination (clickPoint, attackMoveStopRadius); print ("Not moving to enemy."); break; default: print ("Unexpected layer found."); break; } } WalkToDestination (); } private void WalkToDestination(){ //將點擊到的物件位置減去自己的位置,取得相減後的向量 Vector3 playerToClickPoint = currentDestination - transform.position; //計算該向量的距離,若距離太短,就不要移動了(可避免人物角色原地移動) if (playerToClickPoint.magnitude >= 0) { //TODO 設為0導致原本角色原地移動的Bug又出現了 //告知ThirdPersonCharacter物件依向量移動,後面兩個false分別為蹲下和跳躍 theThirdPersonCharacter.Move(playerToClickPoint, false, false); } else { theThirdPersonCharacter.Move(Vector3.zero, false, false); } } Vector3 ShortDestination(Vector3 destination, float shortening){ //將滑鼠點擊的位置減去自己所在的位置後,normalized取得單位向量,保持向量方向不變長度為1後 //再乘以shortening亦即要縮短幾倍的乘量,故reductionVector會變為移動至該位置方向且縮短指定倍率的Vector Vector3 reductionVector = (destination - transform.position).normalized * shortening; //將滑鼠點擊位置減去reductionVector,就會得到一個縮短距離後的Vector return destination - reductionVector; } void OnDrawGizmos(){ //繪製移動路徑 Gizmos.color = Color.black; Gizmos.DrawLine (transform.position, clickPoint); Gizmos.DrawSphere (currentDestination, 0.15f); Gizmos.DrawSphere (clickPoint, 0.1f); //繪製攻擊範圍 Gizmos.color = new Color(255f, 0f, 0f, 0.5f); Gizmos.DrawWireSphere (transform.position, attackMoveStopRadius); } }
留言
張貼留言