【Unity3D遊戲開發學習筆記】(六)上帝之手—GameObject的操作
在Unity中,所有實體都屬於遊戲物件(GameObject),比如外部匯入到場景中的模型,Unity自帶的立方體等等,而要將這些GameOject進行管理,互動等操作,則需要用到指令碼來實現,上一節我們已經學習瞭如何建立一個指令碼並繫結到一個物體上,現在我們將進一步學習如何通過指令碼對GameObject進行控制。
一、建立GameObject
在Unity裡面,建立遊戲物件有兩種方式:
- 第二種,則是通過指令碼進行建立和刪除,這種方式會相對靈活,接下來要講的也正是這一種方式。
首先,我們新建一個指令碼,暫時命名為:GameObjectControl好了,然後開啟指令碼,並進行以下編輯:
using UnityEngine;
using System.Collections;
public class CreateObjects : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
void OnGUI()
{
if(GUILayout.Button("建立Cube",GUILayout.Height(50 )))
{
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.AddComponent<Rigidbody>();
cube.GetComponent<Rigidbody>().useGravity = false;
cube.GetComponent<Renderer>().material.color = Color.red;
cube.name = "Cube";
cube.transform.position = new Vector3(0.0f, 5.0f, 0.0f);
}
if (GUILayout.Button("建立Sphere", GUILayout.Height(50)))
{
GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
sphere.AddComponent<Rigidbody>();
sphere.GetComponent<Rigidbody>().useGravity = false;
sphere.GetComponent<Renderer>().material.color = Color.green;
sphere.name = "Sphere";
sphere.transform.position = new Vector3(5.0f, 5.0f, 0.0f);
}
}
}
然後儲存指令碼,並繫結到Camera上,執行,我們就會發現在介面上多了兩個按鈕,然後分別點選之後,場景當中就會出現一個立方體和一個球體。
我們簡要介紹一下幾個主要用到的函式:
- GameObject.CreatePrimitive()建立一個GameObject物件並指定一個Unity自帶的模型(如果想要生成別的物體可以使用GameObject.Instantiate(),這個我們後面說到)
- AddComponent< T>() 和 GetComponent< T>() 新增和獲取GameObject的元件
- transform.position 設定物體在世界座標系下的位置,如果是想要相對父節點的位置,則使用transform.localPosition
二、獲取GameObject
通過指令碼獲取GameObject有兩種方式:
- 通過宣告一個Public變數,然後在Inspector檢視進行賦值
- 通過GameObject的屬性物件名稱來獲取
public GameObject obj;//通過Inspector直接賦值
// Use this for initialization
void Start()
{
if (obj == null)
obj = GameObject.Find("Cube");//根據名稱直接在整個場景當中搜尋該物體
}
三、新增元件和修改元件
新建的GameObject一般情況下都是沒有任何功能屬性的,我們需要給它賦予各種遊戲元件它才能有自己相應的遊戲功能。比如我們拿剛剛那個例子來說:
cube.AddComponent<Rigidbody>();
cube.GetComponent<Rigidbody>().useGravity = false;
cube.GetComponent<Renderer>().material.color = Color.red;
我們這裡給cube這個物體添加了一個叫Rigidbody的元件,這是一個剛體元件,有了這個元件,這個物體就受到物理引擎的作用,然後我們修改這個元件的useGravity屬性,使它不受重力的作用,並把它材質屬性中的顏色改成了紅色。大家可以試一下改變它的重力屬性,設為true,然後執行的時候我們就能看到立方體往下掉。總的來說,我們給遊戲新增元件通過AddComponent< T>()的方法,獲取元件則是通過GetComponent方法,然後如果是需要銷燬元件,則使用Destroy(),該方法需要提供引數,如果引數是GameObject,就會將這個Object都銷燬了。
四、傳送廣播和訊息
在遊戲當中,廣播和訊息是遊戲物件之間通訊的一個快捷方式,就像廣播那樣,由傳送方進行訊息的傳送,而Receiver遊戲物件裡的Monobehavior指令碼都能收到。它主要是通過GameObject.SendMessage(string methonName, object value = null, SendMessageOptions options = SendMessageOptionsRequireReceiver)函式傳送的。下面我們來看個例子。
我們新建一個指令碼叫Receiver:
using UnityEngine;
using System.Collections;
public class Receiver : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
void ShowNumber(int num)
{
Debug.Log("我是: "+ this.transform.name + " 我收到的數字是 : " + num);
}
}
然後我們將原來的GameObjectControl.cs檔案改一下:
using UnityEngine;
using System.Collections;
public class CreateObjects : MonoBehaviour {
private GameObject[] receiver = new GameObject[2];
// Use this for initialization
void Start()
{
}
// Update is called once per frame
void Update () {
}
void OnGUI()
{
if(GUILayout.Button("建立Cube",GUILayout.Height(50)))
{
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
receiver[0] = cube;
cube.AddComponent<Receiver>();
cube.AddComponent<Rigidbody>();
cube.GetComponent<Rigidbody>().useGravity = false;
cube.GetComponent<Renderer>().material.color = Color.red;
cube.name = "Cube";
cube.transform.position = new Vector3(0.0f, 5.0f, 0.0f);
}
if (GUILayout.Button("建立Sphere", GUILayout.Height(50)))
{
GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
receiver[1] = sphere;
sphere.AddComponent<Rigidbody>();
sphere.AddComponent<Receiver>();
sphere.GetComponent<Rigidbody>().useGravity = false;
sphere.GetComponent<Renderer>().material.color = Color.green;
sphere.name = "Sphere";
sphere.transform.position = new Vector3(5.0f, 5.0f, 0.0f);
}
if (GUILayout.Button("傳送訊息", GUILayout.Height(50)))
{
receiver[0].SendMessage("ShowNumber", 999, SendMessageOptions.RequireReceiver);
receiver[1].SendMessage("ShowNumber", 222, SendMessageOptions.RequireReceiver);
}
}
}
在分別建立了立方體和球體之後,點擊發送訊息,我們可以看到以下結果:
Message相關有3條指令:
SendMessage (“函式名”,引數,SendMessageOptions) //GameObject自身的Script
BroadcastMessage (“函式名”,引數,SendMessageOptions) //自身和子Object的Script
SendMessageUpwards (“函式名”,引數,SendMessageOptions) //自身和父Object的Script
關於第三個引數使用:
SendMessageOptions.RequireReceiver //如果沒有找到相應函式,會報錯(預設是這個狀態)
SendMessageOptions.DontRequireReceiver //即使沒有找到相應函式,也不會報錯,自動忽略
五、克隆遊戲物件
克隆遊戲物件跟建立遊戲物件不一樣,建立遊戲物件,得出來的GameObject我們需要對他進行載入元件才能有自己的功能,而克隆遊戲物件則可以克隆一個完全具有一定功能的遊戲物件(包括其所有的元件)。通過克隆物件,我們可以節省很多的時間,比如子彈的發射,完全可以採用克隆的手段生成大量的子彈而不用我們自己手動新建並且新增屬性。同樣還是GameObjectControl這個例子,我們改動一下:
在OnGUI上新增一個函式
if (GUILayout.Button("CloneCube", GUILayout.Height(50)))
{
GameObject obj = Instantiate(receiver[0]);
obj.GetComponent<Rigidbody>().useGravity = true;
obj.transform.position = new Vector3(0, 0, 0);
}
在分別點選建立立方體和球體之後,點選CloneCube的按鍵,我們可以看到每點一次就會生成一個紅色的Cube出來並且往下落(因為我們設定了它的重力屬性)
然後我們可以發現在Hierarchy介面上出現了很多的Cube(Clone)的Object。
六、移動、縮放,旋轉
移動物體
要使遊戲物件在原來的基礎上繼續移動,在程式碼中可以通過transform.Translate(Vector3 offset)實現,引數是移動的數值.
縮放物體
使用transform.localScale = new Vector3(x,y,z);
分別代表的是x軸方向上縮放x,y軸方向上縮放y,z軸方向上縮放z
整體縮放可以通過將localScale乘一個係數實現。
旋轉物體
遊戲物件的旋轉方式有兩種:
- 圍繞自身旋轉
- 圍繞某一個點或者是某向量旋轉
transform.Rotate()函式是自身的旋轉,Unity裡面提供了很多的實現方式
transform.RotateAround()則是圍繞某個點旋轉
這節就先到這O(∩_∩)O,下一節會介紹一些常用的工具類~