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);
}
}

留言
張貼留言