1.簡答題
(1)解釋遊戲對象(GameObjects) 和 資源(Assets)的差別與聯系。
遊戲對象是在遊戲中真實存在一個物體,是可以進行選中操作的對象,而資源則是對遊戲對象的一個修飾,比如一個正方體是遊戲對象,但是其表面的圖案等具體資訊是資源來設定的。
(2)下載下傳幾個遊戲案例,分别總結資源、對象組織的結構(指資源的目錄組織結構與遊戲對象樹的層次結構)
在unity中的遊戲其資源的目錄結構一般有腳本和各種材質包,對不同的對象使用的類型相似的放在一起,比如顔色放一起,材質放一起等等。
對于對象組織的目錄結構一般為從屬結構,對某一些對象的控制,對資源環境的控制等等。
(3)編寫一個代碼,使用 debug 語句來驗證 MonoBehaviour 基本行為或事件觸發的條件
基本行為包括 Awake() Start() Update() FixedUpdate() LateUpdate()
常用事件包括 OnGUI() OnDisable() OnEnable()
首先使用C#語言編寫腳本檔案
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
Debug.Log("start\n");
}
// Update is called once per frame
void Update()
{
Debug.Log("update\n");
}
private void Awake()
{
Debug.Log("awake\n");
}
private void FixedUpdate()
{
Debug.Log("fixedupdate\n");
}
private void LateUpdate()
{
Debug.Log("lateupdate\n");
}
private void OnGUI()
{
Debug.Log("ongui\n");
}
private void OnDisable()
{
Debug.Log("ondisable\n");
}
private void OnEnable()
{
Debug.Log("onenable\n");
}
}
是以其是否執行隻需要觀察是否有相應輸出即可。
程式運作結果如下:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHLwUzValnVtpVbsdkW250MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLxYTM1QjN0QTM3ATOwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
可以看到在程式最開始運作時會調用Awake函數,然後調用Onenable,接着執行Start函數,然後FixedUpdate,這些執行完之後才開始Update函數。
是以總結一下,同時查閱相關資料:
Awake函數:當腳本被載入時調用。
Start函數:第一次進入遊戲時調用。
FixedUpdate函數:遊戲循環時調用。
Update函數:當start函數執行完後進入遊戲循環調用。
LastUpdate函數:當所有Update函數調用完之後調用。
OnGUI函數:遊戲循環在渲染過程中,場景渲染之後調用。
OnDdiable函數:當某物體被禁用時調用。
OnEnable函數:當取消禁用時調用。
(4)查找腳本手冊,了解 GameObject,Transform,Component 對象。
a.分别翻譯官方對三個對象的描述(Description)
GameObject:是unity編輯中最重要的概念,在遊戲中的每一個對象都是GameObject,從對象到道具到燈光,相機等。但是它本身不能做任何事情,在它成為一個角色之前需要給他一個特征、環境或者特殊的影響。
Transform:被用來儲存一個遊戲對象的位置、旋轉角度、大小。每個GameObject都會有一個Transform元件依附。
Component:元件是遊戲中對象和行為的螺母和螺栓,它們是每個遊戲對象的功能部件。
b.描述下圖中 table 對象(實體)的屬性、table 的 Transform 的屬性、 table 的部件
本題目要求是把可視化圖形程式設計界面與 Unity API 對應起來,當你在 Inspector 面闆上每一個内容,應該知道對應 API。
例如:table 的對象是 GameObject,第一個選擇框是 activeSelf 屬性。
第二個選擇框是Transform,第三個選擇框是MeshFilter,第四個是BoxCollider,第五個是MeshRenderer。
c.用 UML 圖描述三者的關系(請使用 UMLet 14.1.1 stand-alone版本出圖。
(5)整理相關學習資料,編寫簡單代碼驗證以下技術的實作:
a.查找對象:
Debug.Log("start\n");
GameObject cube;
cube = GameObject.Find("cube");
if(cube!=null)
{
Debug.Log("find\n");
}
else
{
Debug.Log("did not find\n");
}
運作結果如下
b.添加子對象
void Start()
{
Debug.Log("start\n");
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.name = "cube1";
cube.transform.position = new Vector3(0, Random.Range(0, 5), 0);
cube.transform.parent = this.transform;
}
運作結果如下:
c.周遊對象樹
void Start()
{
Debug.Log("start\n");
foreach (Transform child in transform)
{
Debug.Log(child.name);
}
}
目錄結構如下:
運作結果如下:
d.清除所有子對象
void Start()
{
Debug.Log("start\n");
foreach (Transform child in transform)
{
Destroy(child.gameObject);
}
}
目錄結構如下:
運作結果如下:
(6)資源預設(Prefabs)與 對象克隆 (clone)
a.預設(Prefabs)有什麼好處?
其為一種可重複使用的遊戲對象,可以了解為一個配置好了的對象,可以很友善的加入到一個遊戲中去,節省工作。而且在遊戲中使用同一個預設都是它的一個克隆,當它本身改變時,其所有克隆出來的都會被改變。
b.預設與對象克隆 (clone or copy or Instantiate of Unity Object) 關系?
預設與克隆都可以對同一個對象複制出大量相同的對象,但是預設出來的克隆對象與其本體有關,當預設對象改變時,其所有克隆對象都會改變,但是如果通過克隆方式建立對象,那麼建立出來的對象就與被克隆的對象沒有了關系,可以随意更改。
c.制作 table 預制,寫一段代碼将 table 預制資源執行個體化成遊戲對象
這裡首先需要在Assets檔案夾下建立一個Resources檔案夾
然後再把cube對象拖進去。
void Start()
{
Debug.Log("start\n");
GameObject cube1 = Instantiate(Resources.Load("cube") as GameObject);
cube1.transform.parent = this.transform;
}
對象目錄如下:
運作之後結果如下:
程式設計實踐,小遊戲
遊戲内容: 井字棋 或 貸款電腦 或 簡單電腦 等等
技術限制: 僅允許使用 IMGUI 建構 UI
作業目的:
了解 OnGUI() 事件,提升 debug 能力
提升閱讀 API 文檔能力
下面是編寫的井字棋遊戲。
實作思路是主要在OnGUI函數中對整個遊戲過程的控制,每次點選時都會判斷目前該誰下了,目前位置是否可以下,是否有人獲勝,獲勝或者平局應該彈出什麼,還有就是重新開始遊戲。對于算法邏輯來說并不複雜,主要是對于一些函數的調用,實作代碼如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
private int[,] map = new int[3, 3];//建立棋盤
private int turn = 0;
private int num = 0;
private int size = 50;
// Start is called before the first frame update
void Start()
{
num = 0;//下棋數
turn = 1 - turn;//輪流下第一個
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
map[i,j] = 0;
}
}
}
// Update is called once per frame
void Update()
{
//Debug.Log("update\n");
}
private int getwin()
{
for(int i=0;i<3;i++)
{
if (map[i, 0] == map[i, 1] && map[i, 1] == map[i, 2]) return map[i, 1];
if (map[0, i] == map[1, i] && map[1, i] == map[2, i]) return map[1, i];
}
if (map[1, 1] == map[0, 0] && map[1, 1] == map[2, 2]) return map[1, 1];
if (map[1, 1] == map[0, 2] && map[1, 1] == map[2, 0]) return map[1, 1];
if (num == 9) return 3;
return 0;
}
private void OnGUI()
{
GUI.skin.button.fontSize = 20;
GUI.skin.label.fontSize = 20;
if (GUI.Button(new Rect(300, 250, 150, 50), "Reset"))
{
num = 0;
turn = 1 - turn;//輪流下第一個
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
map[i, j] = 0;
}
}
}
int win = getwin();
if(win==1) GUI.Label(new Rect(350, 50, 100, 50), "O wins");
else if(win==2) GUI.Label(new Rect(350, 50, 100, 50), "X wins");
else if(win==3) GUI.Label(new Rect(350, 50, 100, 50), "Draw");
for (int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
if(map[i,j]==1)
{
GUI.Button(new Rect(i * size + 300, j * size + 100, size, size), "O");
}
else if(map[i,j]==2)
{
GUI.Button(new Rect(i * size + 300, j * size + 100, size, size), "X");
}
else if(GUI.Button(new Rect(i * size + 300, j * size + 100, size, size), ""))
{
if (win == 0)
{
if (turn == 0)
{
map[i, j] = 1;
}
else map[i, j] = 2;
turn = 1 - turn;
num++;
}
}
}
}
}
}
運作界面如下:
到這裡就基本完成了要求。
視訊檔案如下井字棋