Unity3D 游戲開發構架篇 ——角色類的設計與持久化


在游戲開發中,游戲角色占了很大的篇幅,可以說游戲中所有的內容都是由主角所帶動。這里就介紹一下角色類的設計和持久化。

一、角色類應用場景和設計思想

  游戲中的角色類型不一而足,有不同的技能,有不同的屬性等等。有些一個玩家只有一個角色,有些一個玩家可以有多個角色。這里就目前項目來描述一下角色類的構造,思路都是類似的。

  早期我寫角色類都是直接一個Class,然后想到什么屬性就往里面添加,如果游戲過程中需要對屬性的修改,邏輯判斷也寫在這個類中,這樣必然導致類的龐大和臃腫,最后你自己也忘記了自己寫在什么地方了。

  后期的邏輯如果修改了,姑且不論屬性之間的互相連帶和邏輯連帶,你的查找就是一件麻煩事。

  這里我們討論一下一個玩家賬號多個角色的構造。

  定為一個角色類,包括玩家的疲勞,金幣,元寶等等。角色類包括多個英雄對象。

  一個英雄類,包括英雄的屬性,等級等等,英雄對象包括多個屬性對象。

  一個屬性類,包括屬性的值,下一級屬性的值等等。

  對這些類的修改,類的內部只提供接口,邏輯的判斷存在於外部的部件中,而不是自己類的內部實現。這樣代碼就簡潔明了不少,同樣邏輯修改也只需要查找對應的部件即可。

 

  當然還有更復雜的,如下圖所示:

  一個基礎屬性類衍生出來了Attribute,Virtal,SKill等等。

 

二、持久化的應用場景和設計思想

  角色化類創建后,這個類不論游戲的關閉和開啟都要和上一次的一樣。可以采用持久化的方案。C#中一般采取序列化到本地二進制文件或者XML文件等流序列化。

  當然你也可以采用Unity3D的ScriptableObject方案。

  http://blog.csdn.net/jjiss318/article/details/7195052

三、核心代碼

  BaseState.CS

  基礎屬性類,可以枚舉中動態添加

    [Serializable]
    public class BaseState
    {
        public int _baseValue;
        public int _grown;
        public int _max_baseValue;
		public Attribute _name;

		


        public BaseState(int _baseValue, int _grown, Attribute _name, int _max_baseValue)
        {
            this._baseValue = _baseValue;
            this._grown = _grown;
            this._name = _name;
            this._max_baseValue = _max_baseValue;
        }
        //調整接口如下
		…………………………
    }
	public enum Attribute
    {
        Might,
        Constitution
    }

  BaseCharacter.CS

  基礎英雄類,可以枚舉中動態添加

  

    [Serializable]
    public class BaseCharacter
    {
        public Character _name;
        public Currency_Kind mycurrency;
        public int price;
        public bool _isLocked;
        public int _level;
        public int _max_level;
        public BaseState[] attribute_list;

        public BaseCharacter ( Character _name,Currency_Kind _kind, int price,int _max_level)
        {
            this._name = _name;
            this.mycurrency = _kind;
            this.price = price;
            _isLocked = true;
            _level=0;
            this._max_level = _max_level;
            this.attribute_list= new BaseState[Enum.GetValues(typeof(Attribute)).Length];
            AddAllAttriute(this._name,this.attribute_list);
        }
        private void AddAllAttriute(Character _name, BaseState[] attribute_list)
        {
            AttributeDateBase.GetBaseArrayByName(_name,attribute_list);
        }

        
    }
    public enum Character {
        Moking,
        Super_Pig
    }

  序列化方法,這里就采用本地二進制方法

//持久化英雄數組
        public static void Load()
        {
            Globals.Character = new BaseCharacter[Enum.GetValues(typeof(Character)).Length];
            Debug.Log("load");

            //second load
            if (File.Exists(fileName))
            {
                try
                {
                    using (FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
                    {

                        BinaryFormatter b = new BinaryFormatter();
                        //這里貌似最好一個個序列化
                        //BaseCharacter[] gp = (BaseCharacter[])b.Deserialize(fileStream);
                        for (int i = 0; i <  Globals.Character.Length; i++)
                        {
                            Globals.Character[i] = (BaseCharacter)b.Deserialize(fileStream);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Utils.WriteLog("Globals.Save occurs an error:" + ex);
                }
            }
            else {
                HeroDateBase.GetBaseArray(Globals.Character);
            }

        }
        public static void Save()
        {
            if (Globals.Character == null && Globals.Character.Length <=0)
            {
                return;
            }
            try
            {
                using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write))
                {
                    BinaryFormatter b = new BinaryFormatter();
                    //也要一個個反序列化
                    for (int i = 0; i < Globals.Character.Length; i++)
                    {
                        b.Serialize(fs, Globals.Character[i]);    
                    }
                    
                    Debug.Log("Serialize Save");
                }
            }
            catch (Exception ex)
            {
                Utils.WriteLog("Globals.Save occurs an error:" + ex);
            }

        }

  搞完了英雄類和屬性類的持久化,角色類的持久化也就大同小異了,不過角色也就是玩家一個游戲只有一個,也就不用枚舉了。

四、總結

  考慮到英雄類和屬性類的字段動態增長,可能每次游戲開辟的內存不同,那么此時反序列化的出來的數據覆蓋會不會有錯呢?可以考慮一下。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM