C#程式員整理的Unity 3D筆記(十三):Unity 3D基於組件的思想,

來源:互聯網
上載者:User

C#程式員整理的Unity 3D筆記(十三):Unity 3D基於組件的思想,

如果你接觸過《設計模式》、軟體架構的編程思想,就會知道優秀的設計準則:“組合優於繼承的”。

這句話很簡短,但開始學習OOP的時候,真切的是—-不太好理解(以我個人當初學習為例)。

 

OOP的繼承思想

在設計主角(Player)的時候,為了能夠複用A、B、C的功能,我開始把A、B、C按照繼承來寫,多了一些Virutal\Override\Protected等修飾符,功能沒有任何問題,就是有些彆扭。如Start、Update方法,只能在A中採用模板方法處理,萬一B、C、Player中直接用了Start、Update方法,會導致奇奇怪怪的問題;同時在繼承的基類中,無形之間多了一些包袱,對於Player不得不使用A、B、C的函數、變數(非private的)。

整個關係變為了:

  • Player is a A
  • Player is a B
  • Player is a C

心理上疙疙瘩瘩的,總覺得有點彆扭。

 

OOP的組合思想

以前使用組合思想較多的是構建樹、樹葉模型,例如電信中的網元模型。這種思想,屬於Unity 3D的核心思想–組件。在Player、A、B、C中可自由使用Start、Update函數(請不考慮執行順序,指令碼組件的先後順序外部可調整,但是意義不大),最重要的是,關係理順了—主角變成更積極、主動。

  • Player have a A
  • Player have a B
  • Player have a C
    在Unity 3D中,可複用的幾乎全部為封裝為了組件,eg: transform、rigibody、render、camera、***.cs指令碼;為了配合方便的使用非內建的組件,可使用gameObject.AddComponent<T>()、gameObject.GetComponent<T>()來添加、獲得組件(一般是自訂的指令碼)。

 

這裡我舉一個實際的例子,在《Unity 3D手機遊戲開發》第二版的“太空射擊遊戲”中,有一個需求,需要給遊戲中可複用的GameObject添加自動銷毀的功能(通過時間計時器,或者觸發器添加),代碼很簡單,不到100行,要添加的GameObject有5、6個,雖然工作量不大,但總不能每個都拷貝一遍代碼吧。

開始我是按照OOP繼承做的,

 

看了幾天,很不爽,後來重構為如:

這樣使得自動銷毀組件的功能發揮的更加靈活、機動,即不必拘泥於靜態繼承思想來實現。

從這個重構過程中,我學到Unity 3D組件思想的閃閃發光……

附錄:完整的自動銷毀組件代碼:

public class AutoDestoryComponent : MonoBehaviour 
{ 
    #region ICanCache 
    public ParticleSystem[] m_pss = null; 
    public int m_life = 1; //3條命 
    public float m_AutoDeadTime = 3;//3s自動銷毀

    private int m_life_Base = 3; //3條命【恢複用】 
    private float m_AutoDeadTime_Base = 3;//3s自動銷毀【恢複用】【-1:表示不自動銷毀,如Enemy】

    void Update() 
    { 
        //需要自動銷毀 
        if (m_AutoDeadTime_Base >= 0) 
        { 
            m_AutoDeadTime -= Time.deltaTime;

            if (m_AutoDeadTime <= 0) 
            { 
                InnerDead(); 
                return; 
            } 
        }

        if (m_life <= 0) 
        { 
            InnerDead(); 
        } 
    }

    /// <summary> 
    /// 設定自動銷毀資料 
    /// </summary> 
    /// <param name="life_base">預設生命值</param> 
    /// <param name="autoDeadTime_base">-1不自動銷毀;其他資料代表銷毀時間(單位s)</param> 
    public void SetBasePara(int life_base = 1, float autoDeadTime_base = -1) 
    { 
        m_AutoDeadTime = m_AutoDeadTime_Base = autoDeadTime_base; 
        m_life = m_life_Base = life_base; 
    }

    //是否啟用 
    public bool IsUse { get; set; } 
    //死後位置 
    public Vector3 DeathPosition 
    { 
        get 
        { 
            return new Vector3(2000, 2000, 2000); 
        } 
    }

    //複活 
    public void Init(Vector3 position, Quaternion rotation) 
    { 
        transform.gameObject.SetActive(true); 
        transform.position = position; 
        transform.rotation = rotation; 
        IsUse = true; 
        foreach (ParticleSystem item in m_pss) 
        { 
            item.Play(true); 
        }

        //有些繞 
        m_life = m_life_Base; 
        m_AutoDeadTime = m_AutoDeadTime_Base; 
    }

    private void InnerDead() 
    { 
        IsUse = false; 
        transform.position = DeathPosition; 
        foreach (ParticleSystem item in m_pss) 
        { 
            item.Stop(true); 
        }

        this.gameObject.SetActive(false); 
    } 
    #endregion 
}

 

 

包括系統內建的Audio、Transform、Camera、Image、Button等等。GameObject是一個容器,沒有Image的GameObject,只要建立一個空的GameObject,添加Image Component極為Image GameObject對象的。

也即是在Unity3D中,很少用GameObject.ID的概念,而是用GameObject.Tag、GameObject.name來區分不同的GameObject,且Tag、name不唯一。

 

結論:在Unity3D中,萬事萬物都是Component。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.