在游戲開發中,游戲角色占了很大的篇幅,可以說游戲中所有的內容都是由主角所帶動。這里就介紹一下角色類的設計和持久化。
一、角色類應用場景和設計思想
游戲中的角色類型不一而足,有不同的技能,有不同的屬性等等。有些一個玩家只有一個角色,有些一個玩家可以有多個角色。這里就目前項目來描述一下角色類的構造,思路都是類似的。
早期我寫角色類都是直接一個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); } }
搞完了英雄類和屬性類的持久化,角色類的持久化也就大同小異了,不過角色也就是玩家一個游戲只有一個,也就不用枚舉了。
四、總結
考慮到英雄類和屬性類的字段動態增長,可能每次游戲開辟的內存不同,那么此時反序列化的出來的數據覆蓋會不會有錯呢?可以考慮一下。