3D遊戲編程與設計–第二次做業
簡答題
-
解釋 遊戲對象(GameObjects) 和 資源(Assets)的區別與聯繫。html
解答:git
- 遊戲對象(GameObjects),遊戲程序空間中的事物,多是 Empty(空,最有用的事物)、2D、3D、光線、攝像機等
- 遊戲資源(Assets),構造遊戲對象、裝飾遊戲對象、配置遊戲的物體和數據。即序列化的或存儲格式的遊戲對象或數據
遊戲對象指的是建立出來的對象,以及初始化時的燈光和相機。而遊戲資源能夠是建立的遊戲對象,也能夠是從外部導入的圖像。github
兩者也是有聯繫的,咱們將遊戲對象拖入進遊戲資源中,便成爲了一個遊戲資源;當咱們將遊戲資源實例化以後便成爲了遊戲對象算法
-
下載幾個遊戲案例,分別總結資源、對象組織的結構(指資源的目錄組織結構與遊戲對象樹的層次結構)編程
解答:c#
在 unity hub 中的學習目錄中有不少遊戲樣例進行學習和下載,我選擇了其中的兩款進行分析。設計模式
-
經過 unity 打開後能夠查看到它的 Assets 目錄以下所示:數組
由圖中能夠看到Assets目錄的結構,是採用的屬性結構,父文件夾包含多個子文件夾,且相同或者相似的文件保存在同一個文件夾中,每一個子文件夾,也有若干個子文件。能夠根據這樣的層次結構獲得結論,資源文件夾將屬性類似的資源放在同一個文件夾中。框架
找到該項目的場景BlankScene打開後,能夠看到對象的層次結構,不難看出有多個對象有本身的子對象,這些子對象又具備本身的子對象。父對象由他們的子對象組成起來。全部對象以樹形形式組織起來。ide
-
又下載了幾個遊戲案例,發現其對象的層次結構與Assets的層次結構與上面的案例相似,這裏就不展開說明了,直接將他們的結構截圖放在下面:
- 遊戲介紹:
- Assets的結構以下所示:
- 對象的層次結構以下所示:
-
-
編寫一個代碼,使用 debug 語句來驗證 MonoBehaviour 基本行爲或事件觸發的條件
- 基本行爲包括 Awake() Start() Update() FixedUpdate() LateUpdate()
- 經常使用事件包括 OnGUI() OnDisable() OnEnable()
解答:
首先添加一個C#代碼的資源,驗證的代碼內容以下所示:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Test : MonoBehaviour { // Start is called before the first frame update void Start() { Debug.Log("Start"); } // Update is called once per frame void Update() { Debug.Log("Update"); } void FixedUpdate() { Debug.Log("FixedUpdate"); } void LateUpdate() { Debug.Log("LateUpdate"); } void Awake() { Debug.Log("Awake"); } void OnGUI() { Debug.Log("OnGUI"); } void OnDisable() { Debug.Log("OnDisable"); } void OnEnable() { Debug.Log("OnEnable"); } }
而後打開保存,在unity中點擊play進行運行,獲得的結果以下圖所示:
下面是對行爲或事件的解釋:
- Start(): 在Update函數調用以前調用一遍
- Awake(): 用於腳本被實例裝載時調用
- Update(): 每一幀都會調用一次
- FixedUpdate(): 每一個固定時間片調用一次
- LateUpdate(): 在Update函數調用後被調用
- OnGUI(): 繪製GUI時會被調用
- OnDisable(): 對象變爲不可用時函數被調用
- OnEnable(): 對象變爲可用狀態時函數被調用
-
查找腳本手冊,瞭解 GameObject,Transform,Component 對象
- 分別翻譯官方對三個對象的描述(Description)
- 描述下圖中 table 對象(實體)的屬性、table 的 Transform 的屬性、 table 的部件
- 本題目要求是把可視化圖形編程界面與 Unity API 對應起來,當你在 Inspector 面板上每個內容,應該知道對應 API。
- 例如:table 的對象是 GameObject,第一個選擇框是 activeSelf 屬性。
- 用 UML 圖描述 三者的關係(請使用 UMLet 14.1.1 stand-alone版本出圖)
解答:
-
GameObject:Base class for all entities in Unity Scenes.(是全部在Unity場景中的實體的基類)
Transform:Position, rotation and scale of an object.(物體的位置、旋轉、和大小)
Component:Base class for everything attached to GameObjects.(是全部附加到遊戲物體上的基類)
table對象的屬性:activeSelf屬性,有物體的名字,和Static屬性,下面是Tap,Layer,Prefab,Transform等屬性
Transform的屬性:Position表明物體在XYZ軸上的位置,Rotation表明物體在XYZ方向旋轉的角度,Scale表示物體在XYZ方向上的大小
table的部件:Transform,Mesh Filter,Box Colider,Mesh Renderer
三者的關係是,GameObject和component是一對多的關係,也就是一個GameObject能夠有多個component;GameObject和Transform是一對一的關係,也就是說一個GameObject對應於一個Transform;component是Transform的父類,Transform只是component的一種
-
資源預設(Prefabs)與 對象克隆 (clone)
- 預設(Prefabs)有什麼好處?
- 預設與對象克隆 (clone or copy or Instantiate of Unity Object) 關係?
- 製做 table 預製,寫一段代碼將 table 預製資源實例化成遊戲對象
解答:
-
預設能夠快速實例化不少相同的對象,能夠減小工做量,而且對於預設的修改至關因而對全部由預設建立出來的對象的修改,這樣不須要一一修改,也是減小了工做量
-
用預設建立一個對象,至關因而從預設克隆出來的一個對象,對預設的所有修改,由它建立出來的全部對象都會進行修改。可是若是是克隆對象的話,因爲克隆對象是相對獨立的,彼此之間沒有聯繫,也不會互相影響,因此對一個克隆對象進行改變並不會形成別的克隆對象的改變
-
首先作好Table對象,作好的成果以下所示:
作好以後將Table拖入到Assets中成爲一個預製資源
成爲預製資源後將原先作好的遊戲對象刪除掉,使得場景中只有燈光和相機兩個對象,而後建立一個C#資源進行編寫代碼:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class NewBehaviourScript : MonoBehaviour { // Start is called before the first frame update public GameObject table; void Start() { Instantiate(table); } // Update is called once per frame void Update() { } }
將寫好的C#代碼加入到新建立的對象的部件中,而後點擊 play 開始運行,結果以下所示:
能夠看到成功將資源實例化成對象
編程實踐,小遊戲
-
遊戲內容: 井字棋 或 貸款計算器 或 簡單計算器 等等
-
技術限制: 僅容許使用 IMGUI 構建 UI
-
做業目的:
- 瞭解 OnGUI() 事件,提高 debug 能力
- 提高閱讀 API 文檔能力
我學習並製做了井字棋這個項目,實驗的過程截屏以下所示:
-
遊戲過程:分爲兩個玩家進行遊戲,第一個玩家是’X’,第二個玩家是’O’,若是某個玩家的棋子3個連成一條線那麼就會顯示該玩家獲勝,若是最終棋盤填滿也沒有玩家獲勝,則會顯示「Play even(平局)」。在遊戲進行途中,或者遊戲結束後均可以進行重置,只需點擊左邊的reset按鈕便可,棋盤會從新清零,開始新的遊戲
-
遊戲框架:該遊戲主要由9個按鈕組成的棋盤,一個插入的背景圖片,按鈕組成的重置鍵,標籤組成的遊戲名稱,以及最後遊戲結束顯示的結束語組成
-
代碼說明:首先設置兩個全局變量,int類型的board數組表明 3 * 3 的棋盤,若是數值爲0表明該位置爲空,若是數值爲1表明玩家1在此下了棋,若爲2表明玩家2在此下了棋,和int類型step變量,用於記錄當前的棋盤有多少位置被下過了
而後是start()函數,包括了init()函數用來初始化棋盤,也就是清零board數組,而且將step設置爲0
接下來是isWin(),函數用來判斷是否有人獲勝,而且返回獲勝的人,若是沒有人獲勝則返回0
接下來就是OnGUI()函數,用來調用上面的初始化或者判斷是否有人獲勝,而且進行每一步下棋的操做,而且顯示遊戲的名稱和背景,具體代碼以下所示:
-
實驗總結:經過本次實驗學會了OnGUI函數的完成,而且學會了按鈕,標籤的定義過程,也更加熟悉了在遊戲運行時,各個函數的運行順序和運行次數。也發現了unity作遊戲的方便之處。
-
完整實驗代碼:傳送門
思考題【選作】
-
微軟 XNA 引擎的 Game 對象屏蔽了遊戲循環的細節,並使用一組虛方法讓繼承者完成它們,咱們稱這種設計爲「模板方法模式」。
- 爲何是「模板方法」模式而不是「策略模式」呢?
解答:
模板方法模式:定義一個操做中算法的骨架,而將一些步驟延遲到子類中,模板方法使得子類能夠不改變一個算法的結構便可重定義該算法的某些特定步驟。是一種行爲模式。
策略模式:定義一系列算法,將每個算法封裝起來,並讓它們能夠相互替換。策略模式讓算法獨立於使用它的客戶而變化。是一種對象行爲模式。
策略模式的缺點:
-
策略類數量有可能會不少。
-
全部的策略類都須要對外暴露。
模板方法模式和策略模式均可以用來分離高層的算法和底層的具體實現細節。都容許高層的算法獨立於它的具體實現細節重用。此外,策略模式也容許具體實現細節獨立於高層的算法重用,不過要以一些額外的複雜性、內存以及運行時間做爲代價。
-
將遊戲對象組成樹型結構,每一個節點都是遊戲對象(或數)。
- 嘗試解釋組合模式(Composite Pattern / 一種設計模式)。
- 使用 BroadcastMessage() 方法,向子對象發送消息。你能寫出 BroadcastMessage() 的僞代碼嗎?
解答:
-
組合模式(Composite Pattern),又叫部分總體模式,是用於把一組類似的對象看成一個單一的對象。組合模式依據樹形結構來組合對象,用來表示部分以及總體層次。這種類型的設計模式屬於結構型模式,它建立了對象組的樹形結構。這種模式建立了一個包含本身對象組的類。該類提供了修改相同對象組的方式。
-
// father void Start () { this.BroadcastMessage("Mes"); } // son void Mes(){ Debug.Log ("Son"); }
-
一個遊戲對象用許多部件描述不一樣方面的特徵。咱們設計坦克(Tank)遊戲對象不是繼承於GameObject對象,而是 GameObject 添加一組行爲部件(Component)。
- 這是什麼設計模式?
- 爲何不用繼承設計特殊的遊戲對象?
解答:
- 組合模式
- 直接添加不見,能夠方便的調整對象的屬性,不然可能會形成浪費現象