離散仿真引擎基礎
- 簡介
- 簡答題
- 編程實踐,小游戲
- 思考題(選做)
簡介
學習3D游戲編程與設計的第二講《離散仿真引擎基礎》,下載試用了軟體Unity3D,完成制作小游戲井字棋,
本博客分為三部分:
- 簡答題
- 編程實踐:小游戲《井字棋》
- 思考題
簡答題
1. 解釋游戲物件(GameObjects) 和 資源(Assets)的區別與聯系,
- 游戲物件表示某些資源的具體實體化,出現在游戲的場景中,游戲物件一般有敵人,場景,攝像機等非物體虛擬父類,子類一般為游戲內的物體 ;
- 資源表示硬碟中的檔案,存盤在Unity工程的Assets檔案中,資源可以被多個物件使用,也可以作為模板實體化成游戲內的物體,一般劃分為材質,物件,場景,預設,聲音,腳本,貼圖等子檔案夾中,
-
區別:游戲物件是具有一定屬性與功能的類的物體化,對應為Unity中具有對應職能與屬性的組件,例如游戲中常見的玩家、怪物等;資源是預先準備好的模型、圖片、音樂等,可以直接并重復使用
-
聯系:資源可以添加到游戲物件作為其一部分,而游戲物件可以保存作為一種資源以便捷地重復使用
2. 下載幾個游戲案例,分別總結資源、物件組織的結構(指資源的目錄組織結構與游戲物件樹的層次結構)
從資源網站下載游戲憤怒的小鳥、賽車游戲、2048游戲、像素鳥游戲等資源后,進行總結后,這里以憤怒的小鳥為例,
游戲資源的目錄組織結構一般包含:Animation、Matreias、Prefab、Scene、Scripts、Sprites,

游戲物件樹的層次結構一般包含:Camera、Background、Light和一些自定義物件等,

3. 撰寫一個代碼,使用 debug 陳述句來驗證 MonoBehaviour 基本行為或事件觸發的條件
- 基本行為包括 Awake() Start() Update() FixedUpdate() LateUpdate()
- 常用事件包括 OnGUI() OnDisable() OnEnable()
撰寫如下代碼并添加到Main Camere:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class test : MonoBehaviour
{
void Start()
{
Debug.Log("Start");
}
void Update()
{
Debug.Log("Update");
}
void Awake()
{
Debug.Log("Awake");
}
void FixedUpdate()
{
Debug.Log("FixedUpdate");
}
void LateUpdate()
{
Debug.Log("LateUpdate");
}
void OnGUI()
{
Debug.Log("OnGUI");
}
void OnDisable()
{
Debug.Log("OnDisable");
}
void OnEnable()
{
Debug.Log("OnEnable");
}
}
運行結果如下:

- Awake() :當一個腳本實體被載入時被呼叫;
- Start() : 在所有update()函式被呼叫之前呼叫;
- Update():當行為啟用時其Update()在每一幀被呼叫;
- FixedUpdate():當行為啟動時其Update()在每一時間片被呼叫;
- LateUpdate():當行為啟用時,在所有Update()執行完后執行;
- Onable() :當物件變為可用或激活狀態時此函式被呼叫,OnEnable不能用于協同程式(物體啟動時被呼叫);
- Ondisable() :當物件變為不可用或非激活狀態時此函式被呼叫,當物體被銷毀時他被呼叫,并且可用于任意清理代碼 ,當腳本編譯完成之后重新加載時,該函式被呼叫,OnEnable()在腳本被載入后被呼叫,(物體被禁用時呼叫) ;
- OnGUI() :繪制GUI時觸發,一般在這個函式里繪制GUI選單(GUI顯示函式只能在OnGUI中被呼叫),
4. 查找腳本手冊,了解 GameObject,Transform,Component 物件
- 分別翻譯官方對三個物件的描述(Description)
GameObeject:Base class for all entities in Unity Scenes.
翻譯:Unity場景中所有物體的基類,
Transform:Position, rotation and scale of an object.Every object in a Scene has a Transform. It’s used to store and manipulate the position, rotation and scale of the object. Every Transform can have a parent, which allows you to apply position, rotation and scale hierarchically.
翻譯:物件的位置旋轉和比例,場景中每個物件都有一個變換,他用于操作物件的位置,縮放和旋轉,每個轉換都可以擁有一個父類,允許分層應用位置,
Component:Base class for everything attached to GameObjects.
翻譯:所有附加到GameObject的東西的基類,
描述下圖中 table 物件(物體)的屬性、table 的 Transform 的屬性、 table 的部件
- 本題目要求是把可視化圖形編程界面與 Unity API 對應起來,當你在 Inspector 面板上每一個內容,應該知道對應API,
- 例如:table 的物件是 GameObject,第一個選擇框是 activeSelf 屬性,

table:第一個選擇框時便簽Tag:當前選擇的是未加標簽;第二個選擇框是層,當前是默認屬性;第三個屬性是預設,
table的Transform:有三個屬性:Position、Rotation、Scale,分別表示位置,旋轉,比例
table的部件:Transform、Cube、Mesh Renderer、Box Colloder等,
用 UML 圖描述 三者的關系(請使用 UMLet 14.1.1 stand-alone版本出圖)

5. 資源預設(Prefabs)與 物件克隆 (clone)
- 預設(Prefabs)有什么好處?
使游戲物件可重復使用,這個游戲物件已經配置完成,可以直接加入到游戲中去,提高了作業效率,
- 預設與物件克隆 (clone or copy or Instantiate of Unity
Object) 關系?
預設與克隆都可以由一個物件生成大量相同的物件,但是預設出的物件在本體改變時回隨著本體進行改變,而克隆出的物件之間沒有聯系,可以隨意更改,
- 制作 table 預制,寫一段代碼將 table 預制資源實體化成游戲物件
參考課件,制作table后將其拖入Assets,自動形成table預制,

將 table 預制資源實體化成游戲物件,代碼如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class createTable : MonoBehaviour
{
public GameObject table;
// Start is called before the first frame update
void Start()
{
GameObject temp = (GameObject)Instantiate(table, transform.position, transform.rotation);
temp.name = "instance";
}
void Update()
{
}
}
將createTable添加到Main Camera,并把之前做好的table預制拖入選擇框,

點擊運行,效果如下圖:

編程實踐,小游戲
井字棋——專案地址
- 游戲內容: 井字棋 或 貸款計算器 或 簡單計算器 等等
- 技術限制: 僅允許使用 IMGUI 構建 UI
- 作業目的:
- 了解 OnGUI() 事件,提升 debug 能力
- 提升閱讀 API 檔案能力
實作功能:
- 共O、X兩種棋子,點擊Start游戲開始;
- O棋先手,點擊方塊O、X棋子交替落棋;
- 兩種贏法:橫著三格連成,豎著三格連成;
- 三種結局:O棋贏、X棋贏、平局,
主要代碼如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
private int[,] chessBoard = new int[3, 3];
private int turn = 1;//決定誰落子
void Start()
{
Reset();//初始化界面
}
int checkWin()//判斷勝負
{
for(int i = 1; i < 3; i++)
{
if (chessBoard[i, 0] == chessBoard[i, 1] && chessBoard[i, 0] == chessBoard[i, 2] && chessBoard[i, 0] != 0)
return chessBoard[i, 0];
}//豎著贏
for (int i = 0; i < 3; i++)
{
if (chessBoard[0, i] == chessBoard[1, i] && chessBoard[0, i] == chessBoard[2, i] && chessBoard[0, i] != 0)
return chessBoard[0, i];
}//橫著贏
if (chessBoard[0, 0] == chessBoard[1, 1] && chessBoard[0, 0] == chessBoard[2, 2] && chessBoard[0, 0] != 0)
return chessBoard[0, 0];//斜著贏
int count = 0;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (chessBoard[i, j] != 0)
{
count++;
}
}
}
if (count == 9)//被填滿仍無人勝利,平局
return 0;
return 3;
}
void OnGUI()
{
if (GUI.Button(new Rect(300, 50, 150, 50), "Start Game"))
{
Reset();//點擊Start Game按鈕重置游戲
}
GUISkin skin = GUI.skin;
skin.button.normal.textColor = Color.green;
skin.button.hover.textColor = Color.blue;//設定按鈕樣式
int State = checkWin();//判斷當前狀態2:x贏1:O贏0:平局
if (State == 2)
{
skin.button.normal.textColor = Color.red;
GUI.Label(new Rect(300, 105, 50, 50), "X Win!");
}
else if (State == 1)
{
skin.button.normal.textColor = Color.red;
GUI.Label(new Rect(300, 105, 50, 50), "O Win");
}
else if (State == 0)
{
skin.button.normal.textColor = Color.red;
GUI.Label(new Rect(300, 105, 50, 50), "Tied");
}
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (chessBoard[i, j] == 1)
{
GUI.Button(new Rect(300 + 50 * i, 130 + j * 50, 50, 50), "O");
}
else if (chessBoard[i, j] == 2)
{
GUI.Button(new Rect(300 + 50 * i, 130 + j * 50, 50, 50), "X");
}
if (GUI.Button(new Rect(300 + 50 * i, 130 + j * 50, 50, 50), ""))
{//按鈕沒被點擊時,被點擊后改變棋盤狀態,然后根據棋盤狀態改變按鈕顯示
if (State == 3)
{
if (turn == 1)
chessBoard[i, j] = 1;
else if (turn == -1)
chessBoard[i, j] = 2;
turn = -turn;
}
}
}
}
}
void Reset()
{//重置棋盤
turn = 1;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
chessBoard[i, j] = 0;
}
}
}
void Update()
{
}
}
撰寫上述代碼檔案至預制腳本,拖入Main Camere中,點擊運行即可開始游戲,實作效果如下:
- 開始游戲

- O棋橫著贏

- X棋橫著贏

- O棋豎著贏

- X棋豎著贏

- 平局

思考題(選做)
- 微軟 XNA 引擎的 Game 物件屏蔽了游戲回圈的細節,并使用一組虛方法讓繼承者完成它們,我們稱這種設計為“模板方法模式”,
- 為什么是“模板方法”模式而不是“策略模式”呢?
模板方法模式:定義一個演算法的骨架,將骨架中的特定步驟延遲到子類中,模板方法模式使得子類可以不改變演算法的結構即可重新定義該演算法的某些特定步驟,
策略模式:屬于物件的行為模式,其用意是針對一組演算法,將每一個演算法封裝到具有共同介面的獨立的類中,從而使得它們可以相互替換,
模板方法可以通過不同的實作來達到不同的效果,而策略模式以不同的實作方法來達到相同的效果,
- 將游戲物件組成樹型結構,每個節點都是游戲物件(或數),
- 嘗試解釋組合模式(Composite Pattern / 一種設計模式),
- 使用 BroadcastMessage() 方法,向子物件發送訊息,你能寫出 BroadcastMessage() 的偽代碼嗎?
組合模式(Composite Pattern),又叫部分整體模式,是用于把一組相似的物件當作一個單一的物件,組合模式依據樹形結構來組合物件,用來表示部分以及整體層次,這種型別的設計模式屬于結構型模式,它創建了物件組的樹形結構,
foreach childObject
sendMessage();
- 一個游戲物件用許多部件描述不同方面的特征,我們設計坦克(Tank)游戲物件不是繼承于GameObject物件,而是 GameObject 添加一組行為部件(Component),
- 這是什么設計模式?
Decorator模式
- 為什么不用繼承設計特殊的游戲物件?
因為需要對物件動態的添加功能,采用繼承需要修改的代碼過多,采用Decorate模式,可以在不修改原來代碼的情況下增加新的功能核模塊,且繼承容易導致類與類之間結構混亂,
參考資料:
模板方法模式和策略模式
組合模式
裝飾器模式
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/121556.html
標籤:其他
