2016年8月22日 星期一

[Unity] 在不按下Play運行專案的狀態下,用Editor執行程式



如要在場景中利用程式產生一片一片的磁磚時,抑或隨機密集生成物件、隨機的洞穴地形等,

總是需要將參數設定好,然後再按下Ctrl+P執行,查看最終效果,再做微調,

但不斷重複地執行是累人的。

不過,我們可以透過擴充Editor父類別自訂,讓程式直接執行並由Editor控制參數。



首先引用UnityEditor命名空間:
 
using UnityEditor;
並撰寫類別格式如下:
 
[CustomEditor (typeof(MapGenerator))]
public class MapEditor : Editor 
{

}
在其裡面繼承Editor中的OnInspectorGUI()方法,讓被繼承的方法執行後,宣告想要執行的其他自訂程式:
 
public override void OnInspectorGUI()
{
 base.OnInspectorGUI();

 MySelfScript theScript = target as MySelfScript;

 theScript.MyMethod();
}
以上。若想要在場景中刪除物件,建議使用DestroyImmediate代替Destroy。 參考自:https://www.youtube.com/playlist?list=PLFt_AvWsXl0ctd4dgE1F8g3uec4zKNRV0 ep8

2016年8月9日 星期二

[Unity] 如果Transform.Translate歪掉了,座標系統錯了...



一般而言,遊戲專案中要製作一把槍,通常會在槍口處建立一個Empty子物件,取得該物件的Transform,

然後在該處Instantiate子彈預製物件,再利用transform.translate等方法予以子彈位移。

Unity的物件以Z軸為正前方,亦為向量transform.Forward之指向。

然而有天我利用transform.translate使子彈位移時,子彈卻沒有往Z軸方向前進。

寫法亦十分單純:

void Update () 
{
 transform.Translate (transform.forward * Time.deltaTime * speed);
}


我仍不清楚是何處設置錯誤,不過我嘗試Translate方法的第二個引數,也就是座標系統

void Update () 
{
 transform.Translate (transform.forward * Time.deltaTime * speed, Space.World);
}



子彈此時卻順利地往Z軸前進了。

[Unity] 第三人稱俯瞰射擊:讓角色正面朝向游標位置

上圖擷取自Unity官方教學專案Survival Shooter



一、
簡略寫法:
在Update方法中建立一無垠的、虛擬的、y軸向上的平面,並使用Plane類別下的Raycast方法獲得滑鼠在該平面上的交點:

Ray ray = viewCamera.ScreenPointToRay(Input.mousePosition); //須先宣告一Camera物件
float rayDistance;
Plane groundPlane = new Plane(Vector3.up, Vector3.zero);

if(groundPlane.Raycast(ray, out rayDistance))
 {
  Vector3 point = ray.GetPoint(rayDistance);

  Vector3 lockTransformRotation = new Vector3(point.x, transform.position.y, point.z);
  transform.LookAt(lockTransformRotation);
 }


二、
進一步之寫法:
主要於FixedUpdate方法中撰寫,使用Physics.Raycast於Camera射出射線,檢查射線與場景上實體平面的焦點,將角度儲存為Quaternion,套用於Rigidbody組件上:

首先宣告變數並於Awake中取得Mask:
 
int floorMask;         
float camRayLength = 100f; //射線長度
void Awake ()
        {
            floorMask = LayerMask.GetMask ("Floor"); 
        }


記得在場景上的平面設置為Floor Layer,以在程式中利用該Layer之LayerMask(遮罩)。

void FixedUpdate()
{
  Ray ray = viewCamera.ScreenPointToRay(Input.mousePosition); //須先宣告一Camera物件
  RaycastHit floorHit;

  if(Physics.Raycast (ray, out floorHit, camRayLength, floorMask))
            {
                Vector3 playerOrientationToMouse = floorHit.point - transform.position;
                playerOrientationToMouse .y = 0f;

                Quaternion newRotatation = Quaternion.LookRotation (playerOrientationToMouse ); 
                myRigidbody.MoveRotation (newRotatation);
            }
}



以上參考自官方Survival Shooter 學習專案,有錯敬請不吝指正。

2016年8月8日 星期一

[Unity] 關於令角色移動的幾種寫法



以下以3D專案為例:

一、
建立Rigidbody Component組件,
於建立一C#程式,於Update方法中使用Input.GetAxis方法,並建立一Vector3區域變數:

    
    void Update() {
    Vector3 moveInput = new Vector3(Input.GetAxis("Horizontal"),0f,Input.GetAxisRaw("Vertical"));
    Vector3 moveVelocity = moveInput.normalized * moveSpeed;
    }

Vector3.normalized簡而言之便是將一Vector3向量歸於1,以便另立變數予以加乘。
接著在FixedUpdate方法中使用Rigidbody.MovePosition:

 
   public void FixedUpdate()
   {
  myRigidbody.MovePosition(transform.position + velocity * Time.fixedDeltaTime);
   }


二、
建立Rigidbody Component組件,
並在FixedUpdate方法中使用Rigidbody.AddForce方法:


  void FixedUpdate() 
    {
        rb.AddForce(transform.forward * thrust);
    }


三、
在Update方法中使用Transform.translate方法:

 
   void Update() {
        transform.Translate(Vector3.forward * Time.deltaTime);
        transform.Translate(Vector3.up * Time.deltaTime, Space.World);
    }


以上有錯敬請不吝指正。