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。
轉載于:https://www.cnblogs.com/xifarm/p/csharp_learnunity3d_component.html
總結
以上是生活随笔為你收集整理的C#程序员整理的Unity 3D笔记(十三):Unity 3D基于组件的思想的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 超详细的QSS样式表入门Demo
- 下一篇: 为VS2005添加X64编译平台