Unity中GameObject API解析
本文節選自
洪流學堂
公眾號專欄《鄭洪智的Unity2018課》,未經允許不可轉載。
洪流學堂
公眾號回覆
專欄
,檢視更多專欄文章。
洪流學堂,讓你快人幾步。你好,我是鄭洪智。
GameObject我們已經很瞭解了,它本身沒有功能,它是元件的容器,很多時候我們需要在指令碼中操作GameObject。今天我們就來看看如何實現這些需求。
GameObejct相關的文件位於:
https://
docs。unity3d。com/Script
Reference/GameObject。html
這一篇我們會採用問題+答案的形式,告訴你如何解決遊戲中常見的需求。
如何在指令碼中獲取自身所在的GameObject?
我們知道指令碼必須掛在一個GameObject上面才能執行,那麼如何知道當前指令碼所掛載的GameObject是哪一個呢?
這就需要用到
gameObject
屬性了。
gameObject
屬性可以在所有繼承MonoBehaviour的類中獲取到,因為指令碼必須要掛在到一個物體上才能執行,這個gameObject就是指令碼掛到的物體。
using
UnityEngine
;
public
class
Test
:
MonoBehaviour
{
void
Start
()
{
Debug
。
Log
(
gameObject
。
name
,
gameObject
);
}
}
上面的程式碼就會打印出指令碼所掛物體的名字。
注意這裡Debug。Log傳入了兩個引數,這是為什麼呢?
遇到這種問題,我們首先查一下Unity的文件。
為什麼要查
Unity
的文件呢?
從圖中可以看到,將游標移到Debug上面時,顯示Debug類是屬於UnityEngine這個名稱空間的,也就是Unity提供的API。
Debug。Log有兩種形式:
public
static
void
Log
(
object
message
);
public
static
void
Log
(
object
message
,
Object
context
);
第二種形式中可以傳入一個Object型別的引數,傳入這個引數時,在Console中顯示的log會與指令碼所在的物體關聯。點選Console中這條資訊時,會在Hierarchy中高亮這一個物體。
Log關聯GameObject。gif
如何透過物體名字查詢物體?
GameObject類中有一個靜態(static)方法Find,用於透過名字查詢場景中的物體。
什麼是
靜態方法
?
靜態方法是標記為static的方法。靜態方法獨立於例項物件存在。即使沒有類的例項,仍然可以透過類名。靜態方法呼叫。
靜態方法中不能訪問例項成員,可以訪問其他靜態成員
。
靜態方法在定義時需要在返回值型別前面加上static修飾符,比如:
static
void
Walk
(){
Debug
。
Log
(
“Walking”
);
}
訪問時,可以直接透過
類名。方法名
呼叫。比如查詢物體的方法就是
GameObject。Find(“cat”)
。
查詢的名稱字串中可以包含“/”,比如
GameObject。Find(“animals/cat”)
就只會查到父物體名字為animals的cat物體。如果“/”字元在字串中最開始的位置,那麼會在根節點開始找,比如
GameObject。Find(“/animals/cat”)
就只會查到根節點為animals物體的子物體cat。
查詢過後,一定要判斷一下是否為空,因為Find有可能找不到你想找的物體。
特別注意1
這個方法的效率比較低,不要在Update中呼叫此方法,否則可能會造成遊戲卡頓。一般的做法是,在Awake或Start方法中透過Find找到,然後儲存到成員變數中。
比如:
using
UnityEngine
;
public
class
Test
:
MonoBehaviour
{
private
GameObject
cat
;
void
Start
()
{
cat
=
GameObject
。
Find
(
“cat”
);
if
(
cat
!=
null
)
Debug
。
Log
(
“找到了cat物體”
,
cat
);
}
}
特別注意2
這個方法無法找到active為false的物體。
那麼如何查詢active為false的物體呢?
1、不要使用Find,直接在程式碼中透過public的變數關聯物體。
2、不要設定物體的active為false,先在遊戲最開始時透過程式碼找到物體,然後透過程式碼設為false
3、透過transform。Find,我們明天會講到。
如何修改物體的active狀態?
修改物體的active狀態是一個快速隱藏/顯示物體的方法。物體的active是false時,物體上
所有的元件都不會執行
,相當於將物體隱藏了。
gameObject。SetActive
(
false
)
;
特別注意
這個方法只會改變物體自身的active屬性。如果該物體有子物體,那麼子物體也會被隱藏,但是active屬性不會變。如果該物體的父物體的active是false,即使將該物體的active設定為true,該物體也不會顯示出來。
物體的active可以透過兩個屬性來判斷:
activeInHierarchy
物體是否在Hierarchy中是啟用狀態。這個屬性為true時,該物體及其所有父物體的active都為true。
activeSelf
物體自身的active屬性是否為true,即使該物體的父物體的active可能為false。
如何透過tag查詢物體?
除了透過物體的name查詢物體,透過物體的tag也可以查詢。Tag即在Inspector上設定的一個標籤,如下圖所示:
一個物體只能有一個Tag,但是一個Tag可以被多個物體使用。
透過tag查詢有兩個方法:
public
static
GameObject
FindWithTag
(
string
tag
);
返回
第一個
查詢到的標籤為tag的active為true的物體,如果沒有找到則返回null。
tag必須在TagManager中設定過,否則會丟擲異常。異常內容是:
UnityException: Tag: cat is not defined。
含義是:
標籤:cat 沒有定義
。
public
static
GameObject
[]
FindGameObjectsWithTag
(
string
tag
);
由於一個Tag可以被多個物體使用,所以這個方法可以找到所有使用該標籤的active為true的物體,並返回對應的陣列。如果沒有找到,會返回一個空陣列(長度為0的陣列)。
tag必須在TagManager中設定過,否則會丟擲異常。異常內容是:
UnityException: Tag: xxx is not defined。
含義是:
標籤:xxx 沒有定義
。
如何用程式碼建立空物體?
有時候為了組織Hierarchy的結構,需要動態建立空物體作為資料夾使用。
建立空物體可以使用如下程式碼:
GameObject
go
=
new
GameObject
();
go
。
name
=
“EmptyGameObject”
;
GameObject
dog
=
new
GameObject
(
“Puppy”
);
new的時候可以傳入一個字串作為GameObject的名字。也可以不傳,預設名字是
New Game Object
。也可以建立後再修改空物體的名字。
如何用程式碼建立內建幾何體?
透過程式碼也很容易建立Unity中的幾種預設幾何體。
public
static
GameObject
CreatePrimitive
(
PrimitiveType
type
);
其中PrimitiveType是一個列舉(enum)型別,包括的型別有:Sphere、Capsule、Cylinder、Cube、Plane、Quad。
具體的用法如下:
GameObject cube = GameObject。CreatePrimitive(PrimitiveType。Cube);
上面的程式碼可以建立一個Cube,和透過選單欄
GameObject
>
3D Object
>
Cube
創建出來的Cube一致。
什麼是
列舉
?
列舉是一組命名整型常量。列舉型別是使用 enum 關鍵字宣告的。
C# 列舉是值型別。換句話說,列舉包含自己的值,且不能繼承或傳遞繼承。
宣告列舉的一般語法:
enum
<
enum_name
>
{
enumeration
list
};
其中,
enum_name 指定列舉的型別名稱。
enumeration list 是一個用逗號分隔的識別符號列表。
列舉列表中的每個符號代表一個整數值,一個比它前面的符號大的整數值。預設情況下,第一個列舉符號的值是 0。例如:
enum
Days
{
Sun
,
Mon
,
tue
,
Wed
,
thu
,
Fri
,
Sat
};
使用時,可以使用
Days。Sun
來表示星期日。
總結
本文講解了和GameObject類相關的常見問題及API的用法。
但是由於GameObject類中還有一些不常用API,建議自行查閱GameObject文件獲得更全面的瞭解:
https://
docs。unity3d。com/Script
Reference/GameObject。html
今日思考題
在Unity中透過程式碼嘗試下講到的和沒講到的API~
歡迎在留言區分享你的收穫,和大家一起討論。
別忘了分享給你學Unity的朋友,也許能夠幫到他。
洪流學堂
公眾號回覆
專欄
,檢視更多專欄文章。