Unity 3D類結構簡介


  趁着周末,再來一發。對於Unity3D,我也是剛開始學習,希望能夠與大家多多交流。好了,廢話不多說,下面繼續。

  本篇文章使用C#進行舉例和說明。關於Unity 3D編輯器中的各種窗口,網上有很多資料了,這里不做介紹,默認大家都知道各個窗口的作用了,並會在Unity 3D編輯器中執行基本的操作。

  上一篇講的是Unity 3D的基礎知識,這篇講一下我剛開始學習編寫腳本時遇到的一些困惑,主要是Unity 3D自身繼承結構方面的問題。

  腳本作為Unity 3D中的一個組件,是經常會使用到的。一個對象可以添加腳本組件,添加方式有兩種:一種是直接拖到對象上,另一種是在對象的Inspector窗口中點擊最下面的Add Component,然后選擇需要的腳本就可以添加成功。第二種方式如下圖所示:

  我們在編寫腳本時,經常需要用到對各種場景對象(GameObject)的訪問,在剛開始的使用時,對於對象的訪問方法一直都比較模糊。很多教程上都是這么寫的:定義一個類型為Transform的變量,然后將該變量與一個游戲對象關聯,然后使用。

  關聯變量與游戲對象主要有兩種方式。

  方式一:當腳本添加到一個游戲對象上時,在該游戲對象的Inspector窗口可以看到該腳本里面定義的public變量(見下圖紅框中內容)。那么將需要關聯游戲對象的Transform變量的訪問屬性指定為public,然后將游戲對象從Hierarchy直接拖到這個變量上面就可以了。游戲音樂等其他資源也都可以通過這種方式關聯,不過游戲音樂一般會放在Project窗口中,將其從Project窗口直接拖動到AudioClip類型變量上即可,當然這個變量也得是public,否則只能通過代碼的方式獲取。

  方式二:在代碼中使用類似GameObject.Find函數,與Find相關的有許多函數,例如FindGameObjectsWithTag()之類的,這些函數大家都可以去網上查詢,Unity 3D官方文檔里也有。各種Find函數都可以用來獲取游戲對象。

  剛開始學習時,我的疑惑是:明明是游戲對象時GameObject類型,而Transform只是一個組件,為什么很多地方使用Transform去代表這個對象,然后通過Transform對象對其進行一些操作?

  為了解決我這個疑問,我去查了Unity 3D類結構圖。它的設計剛開始看起來還有點繞,看明白的才知道是怎么回事。下面就講一下我對這部分的理解。

  在Unity 3D中,不管是游戲對象(GameObject)類還是Component(組件)類,都繼承於Object類。這里要明確:雖然游戲對象中包含了各種組件,但是它們從繼承結構上來說是平級的。

其中GameObject對象中包含了例如:audio, collider, rigidbody等組件變量,這些變量所關聯的組件都是依附於該GameObject對象上的,同時也可以使用GetComponent獲取依附於該對象上的組件(這兩種方式都可以獲取該對象上的組件),即下面兩種方式效果是一樣的(C#):

1 GameObject obj; 2 Rigidbody rigid = obj.GetComponent<rigidbody>(); 3 Rigidbody rigid = obj.rigidbody;

  第一種組件獲取方式比較方便,而第二種組件獲取方式則比較通用。例如要獲取一個腳本組件,GameObject默認是沒有該變量的,那么此時只能通過第二種方式獲取。例如腳本類名是Gun,那么在該腳本依附的GameObject上獲取方式就是:  Gun gun = obj.GetComponent<Gun>(); 如果該GameObject沒有該組件,則返回null。

  在Component類中,也包含了例如:audio, collider, rigidbody等組件變量,這些變量表示該Component所依附的對象上的audio組件、collider組件、rigidbody組件等。audio、collider、rigidbody等這些變量的類型分別是Audio類、Collider類和Rigidbody類,這些具體的組件類又都是繼承於Component類的。即Component類中包含了繼承於它的具體組件的對象,這些對象關聯到了該組件依附於GameObject上的組件。而且,Component類中也有一個GetComponent方法,這個函數與GameObject中的功能是一樣的,能夠通過該函數獲取該組件依附於的GameObject上的其他組件。

  舉個例子,有一個GameObject obj,其中包含了兩個組件:Transform和Rigidbody。

1 public GameObject obj; // 可以通過“關聯變量與游戲對象的方式一”與對象進行關聯,將其關聯到一個包含Transform組件和Rigidbody組件的對象上
2 Transform m_trans1 = obj.transform; 3 Transform m_trans2 = obj.getComponent<Transform>(); 4 Rigidbody m_rigid1 = obj.rigidbody; 5 Rigidbody m_rigid2 = obj.getComponent<rigidbody>();

  那么m_trans1、m_trans2、m_trans1.transform、m_rigid1.transform和m_rigid1.getComponent<Transform>()等都指向同一個東西,就是obj的Transform組件。同理m_rigid1、m_rigid2、m_trans1.rigidbody和m_rigid1.rigidbody等也是都代表了obj的Rigidbody組件,這幾種訪問方式都是可以的。

  這也就解釋了我的疑惑,由於每個GameObject都必須有Transform組件,通過Transform組件,我們可以訪問到該GameObject的其他組件,因此可以用Transform去代表這個GameObject。如果我們用Rigidbody去代表該GameObject就不好了,因為不是每個GameObject都有Rigidbody組件。Unity 3D提供的這組結構,使得組件的訪問方法不止一種,這也是給初學者最大困惑的地方,不過我現在還不知道這幾種訪問方法在性能上是不是有區別(哪位小伙伴知道的話可以分享分享),但是不考慮性能的話,這幾種訪問方法都是可以的。

  看了上述那么復雜的結構,是不是感覺比較詭異?尤其是上面代碼中提到的m_trans1和m_trans1.transform都指向同一個東西,剛開始學的時候看着還是很暈的。同時,在這里要感謝一下這位仁兄,看了他這篇文章《Unity 3D編程概覽》,使我對於Unity 3D的類結構有了更清晰的認識。

  上面就是我對Unity 3D類結構的學習心得,由於剛開始學習,理解還不夠深,如果文中存在不對的地方歡迎指正。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM