天天看點

3D遊戲程式設計作業(一)

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");
    }
}

           

是以其是否執行隻需要觀察是否有相應輸出即可。

程式運作結果如下:

3D遊戲程式設計作業(一)

可以看到在程式最開始運作時會調用Awake函數,然後調用Onenable,接着執行Start函數,然後FixedUpdate,這些執行完之後才開始Update函數。

3D遊戲程式設計作業(一)

是以總結一下,同時查閱相關資料:

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版本出圖。

3D遊戲程式設計作業(一)

(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");
        }
           
3D遊戲程式設計作業(一)

運作結果如下

3D遊戲程式設計作業(一)

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;
    }
           

運作結果如下:

3D遊戲程式設計作業(一)

c.周遊對象樹

void Start()
    {
        Debug.Log("start\n");
        foreach (Transform child in transform)
        {
            Debug.Log(child.name);
        }
    }
           

目錄結構如下:

3D遊戲程式設計作業(一)

運作結果如下:

3D遊戲程式設計作業(一)

d.清除所有子對象

void Start()
    {
        Debug.Log("start\n");
        foreach (Transform child in transform)
        {
            Destroy(child.gameObject);
        }
    }
           

目錄結構如下:

3D遊戲程式設計作業(一)

運作結果如下:

3D遊戲程式設計作業(一)

(6)資源預設(Prefabs)與 對象克隆 (clone)

a.預設(Prefabs)有什麼好處?

其為一種可重複使用的遊戲對象,可以了解為一個配置好了的對象,可以很友善的加入到一個遊戲中去,節省工作。而且在遊戲中使用同一個預設都是它的一個克隆,當它本身改變時,其所有克隆出來的都會被改變。

b.預設與對象克隆 (clone or copy or Instantiate of Unity Object) 關系?

預設與克隆都可以對同一個對象複制出大量相同的對象,但是預設出來的克隆對象與其本體有關,當預設對象改變時,其所有克隆對象都會改變,但是如果通過克隆方式建立對象,那麼建立出來的對象就與被克隆的對象沒有了關系,可以随意更改。

c.制作 table 預制,寫一段代碼将 table 預制資源執行個體化成遊戲對象

這裡首先需要在Assets檔案夾下建立一個Resources檔案夾

3D遊戲程式設計作業(一)

然後再把cube對象拖進去。

void Start()
    {
        Debug.Log("start\n");
        GameObject cube1 = Instantiate(Resources.Load("cube") as GameObject);
        cube1.transform.parent = this.transform;
    }
           

對象目錄如下:

3D遊戲程式設計作業(一)

運作之後結果如下:

3D遊戲程式設計作業(一)

程式設計實踐,小遊戲

遊戲内容: 井字棋 或 貸款電腦 或 簡單電腦 等等

技術限制: 僅允許使用 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++;
                    }
                }
            }
        }
    }

}

           

運作界面如下:

3D遊戲程式設計作業(一)
3D遊戲程式設計作業(一)

到這裡就基本完成了要求。

視訊檔案如下井字棋

繼續閱讀