【Unity基礎知識】基礎遊戲單位GameObject中常用的屬性和API

2022-07-20 15:00:32

一、GameObject中的成員變數

主要思想:得到該指令碼依附的GameObject的相關資訊
現有:

Lesson4的程式碼:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Lesson4 : MonoBehaviour
{
    void Start()
    {
        //1.得到名字
        print(this.gameObject.name);

        //2.更改名字
        this.gameObject.name = "Lesson4的新名字";
        print(this.gameObject.name);

        //3.得到是否啟用
        print(this.gameObject.activeSelf);

        //4.得到是否開啟了靜態
        print(this.gameObject.isStatic);

        //5.得到層級(Layer)
        print(this.gameObject.layer);

        //6.得到標籤(Tag)
        print(this.gameObject.tag);

        //7.得到transform
        //this.transform這種方法是Mono提供的
        //this.gameObject.transform是GameObject提供的
        //這兩種寫法得到的資訊是完全一樣的
        print(this.gameObject.transform.position);
    }
}

執行:

二、GameObject中的靜態方法

2-1.建立Unity自帶的幾何體

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson4 : MonoBehaviour
{
    void Start()
    {
        GameObject.CreatePrimitive(PrimitiveType.Cube);

        //補充:
        //這個靜態方法是有GameObject型別返回值的,
        //可以用一個GameObject變數去接收它,然後再做後續的邏輯處理
        GameObject obj =  GameObject.CreatePrimitive(PrimitiveType.Sphere);
        //比如改個名字
        obj.name = "我用程式碼建立的幾何體";
        //還能得到這個幾何身上掛載的指令碼
        //obj.GetComponent...
    }
}

執行:

2-2.查詢物件相關

無法找到失活的物件

現有:
Lesson4的程式碼:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Lesson4 : MonoBehaviour
{
    void Start()
    {
        //1.查詢單個物件
        //兩種方法的共同點:
        //  -無法找到失活的物件
        //  -如果場景中有多個滿足查詢條件的物件,我們無法確定找的是哪一個
        //  1-1.通過物件名查詢
        //      這個查詢效率比較低 因為它會在場景中所有物件中進行查詢
        //      找到了 就返回對應物件,沒找到 返回null
        GameObject obj2 = GameObject.Find("Wall");
        //      保險起見,使用前先判斷是否找到
        if (obj2 != null)
        {
            print("根據名字找的物件:" + obj2.name);
        }
        else
        {
            print("沒找到Wall物件");
        }

        //  1-2.通過Tag查詢
        GameObject obj3 = GameObject.FindWithTag("Player");
        //      或寫成(這兩種寫法是一模一樣的)
        //obj3 = GameObject.FindGameObjectWithTag("Player");
        //      保險起見,使用前先判斷是否找到
        if (obj3 != null)
        {
            print("根據Tag找的物件:" + obj3.name);
        }
        else
        {
            print("沒找到Tag為Player的物件");
        }

        //學到現在,目前有兩種得到單個物件的方式:
        //  -先暴露出去,然後從外部面板拖進去 進行關聯
        //  -通過API去查詢

        //2.查詢多個物件
        //  只能通過Tag去查詢多個物件
        //  將返回一個GameObject陣列
        GameObject[] objs = GameObject.FindGameObjectsWithTag("Player");
        print("Tag為Player的物件個數:" + objs.Length);

        //補充:還有幾個用的很少的查詢方法,都是GameObject的父類別Object提供的方法
        //引出的額外知識點:Unity裡的Object 不是指C#裡的萬物之父object
        //Unity裡的Object是Unity自己寫的,它也屬於萬物之父object
        //Unity的Object的名稱空間在UnityEngine中;C#的object的名稱空間在System中
        //此方法可找到場景中掛載了某一個指令碼的物件(誰掛了這個指令碼 就找誰)
        //此方法效率更加底下,因為它不僅要去遍歷物件,還要去遍歷指令碼
        Lesson4 l4 = GameObject.FindObjectOfType<Lesson4>();
    }
}

執行:

2-3.範例化(克隆)、刪除物件的方法

被克隆的物件:①可以是場景上的物件、②可以是一個預製體
現有:

Lesson4的程式碼:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Lesson4 : MonoBehaviour
{
    //準備用來被克隆的物件
    public GameObject obj;
    //準備用來被刪除的物件
    public GameObject obj2;

    void Start()
    {
        //範例化(克隆)物件
        //作用:根據一個GameObject物件建立出一個和它一模一樣的GameObject物件
        //將會返回一個被克隆的物件,使用GameObject型別的變數接收
        GameObject insObj = GameObject.Instantiate(obj);
        //接收之後,就可以隨意操縱insObj了

        //補充:如果繼承了MonoBehaviour 可以不用寫前面的GameObject
        //因為這個方法是Unity的Object基礎類別提供的,所以可以直接用
        //Instantiate(obj);

        //刪除物件
        //1.下一幀就刪除
        GameObject.Destroy(obj2);

        //2.延遲一段時間後 再刪除
        //引數1 要刪除的物件
        //引數2 幾秒後刪除
        GameObject.Destroy(obj2, 3);

        //3.Destroy不僅可以刪除物件,還可以刪除指令碼
        GameObject.Destroy(this); //把自己這個指令碼刪除

        //注意:這個Destroy不會馬上刪除物件,只是給這個物件加了一個移除標識
        //     一般情況下,會在下一幀 把物件刪除,這麼做是為了減少卡頓
        //如果有特殊需求 需要馬上刪除物件(一般很少用)
        //GameObject.DestroyImmediate(obj2);

        //補充:如果繼承了MonoBehaviour 可以不用寫前面的GameObject
        //因為這個方法是Unity的Object基礎類別提供的,所以可以直接用
        //Destroy(obj2);
    }
}

下一步:

執行:

2-4.GameObject物件過場景不移除

Unity中可以建立多個遊戲場景,難免會場景之間來回切換
Unity的機制是,一旦切換到另一個場景,此場景裡的物件會被全部移除
如果有的物件不想在切換場景的時候被移除

現有:

Lesson4的程式碼:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Lesson4 : MonoBehaviour
{
    void Start()
    {
        //誰不想切換場景時被移除,就傳入誰
        //一般都是傳依附的GameObject物件
        //下面這句程式碼的意思就是 本指令碼依附的物件切換場景不被移除
        GameObject.DontDestroyOnLoad(this.gameObject);

        //補充:如果繼承了MonoBehaviour 可以不用寫前面的GameObject
        //因為這個方法是Unity的Object基礎類別提供的,所以可以直接用
        DontDestroyOnLoad(this.gameObject);
    }
}

執行並切換場景:
此時Lesson4就不會被自動移除了

三、GameObject中的成員方法

3-1.建立空GameObject物件相關

現有:

Lesson4的程式碼:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Lesson4 : MonoBehaviour
{
    void Start()
    {
        //new一個GameObject就是在建立一個空物體
        GameObject obj = new GameObject();
        //還建立的同時直接命名
        GameObject obj2 = new GameObject("建立的同時直接命名");
        //建立的同時直接命名並掛載指令碼(想掛幾個都行)
        GameObject obj3 = new GameObject("建立的同時直接加指令碼", typeof(Lesson3),  typeof(Lesson2));
    }
}

執行:

3-2.為現有GameObject物件新增指令碼

之前說過繼承了Mono的指令碼 是不能夠new的
如果我們想動態地給現有物件新增指令碼的話,就需要使用GameObject提供的方法

現有:

Lesson3的程式碼:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson4 : MonoBehaviour
{
    //想要新增指令碼的GameObject物件
    public GameObject obj;

    void Start()
    {
        //為obj新增指令碼 誰想加指令碼就用誰 .AddComponent
        //這種方法用的少,因為返回值還要as
        Lesson3 les3 = obj.AddComponent(typeof(Lesson3)) as Lesson3;
        //一般使用泛型
        Lesson2 les2 = obj.AddComponent<Lesson2>();
        //通過返回值 得到新增的指令碼的資訊,來做後續的邏輯處理

        //補充:關係得到指令碼,GameObject裡得到指令碼的方法 和Mono裡得到指令碼的方法一模一樣,用誰的都可以
        //都是.GetComponent系列
    }
}

下一步:

執行:

3-3.標籤比較

現有:

Lesson4的程式碼:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Lesson4 : MonoBehaviour
{
    void Start()
    {
        //方法一:
        //判斷這個物件的標籤是否是 Player
        //返回值是bool
        if (this.gameObject.CompareTag("Player");
        {
            print("沒錯,物件的標籤是Player");
        }
        //這兩種↑↓方法是一模一樣的
        //方法二:
        if (this.gameObject.tag == "Player")
        {
            print("沒錯,物件的標籤是Player");
        }
    }
}

執行:

3-4.設定啟用失活

現有:

Lesson4的程式碼:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Lesson4 : MonoBehaviour
{
    //想要啟用的物件
    public GameObject Jihuo;
    //想要失活的物件
    public GameObject shiHuo;
    void Start()
    {
        //啟用
        Jihuo.SetActive(true);
        //失活
        shiHuo.SetActive(false);
    }
}

下一步:

執行:

3-5.次要的成員方法(瞭解即可,不建議使用)

通過廣播或傳送訊息,讓自己或別人 執行某些行為方法
現有:

Lesson4的程式碼:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Lesson4 : MonoBehaviour
{
    void Start()
    {
        //通知自己 執行某行為
        //它會在自己身上掛載的所有指令碼中 去找TestFun函數,並執行所有名為TestFun的函數
        this.gameObject.SendMessage("TestFun");
        //有引數的 直接傳即可
        this.gameObject.SendMessage("TestFun2", 99);

        //再補充兩個,不舉例子了
        //1.廣播行為 讓自己和自己的子物件去執行
        //this.gameObject.BroadcastMessage("函數名");
        //2.向父物件和自己傳送訊息 並執行
        //this.gameObject.SendMessageUpwards("函數名")
    }
    
    void TestFun()
    {
        print("Lesson4的TestFun被執行了");
    }
    void TestFun2(int i)
    {
        print("Lesson4的TestFun2被執行了" + i);
    }
}

Lesson4_1的程式碼:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Lesson4_1 : MonoBehaviour
{
    void TestFun()
    {
        print("Lesson4_1的TestFun被執行了");
    }
    void TestFun2(int i)
    {
        print("Lesson4_1的TestFun2被執行了" + i);
    }
}

執行: