從零開始做一個SLG遊戲(八):配置表載入元件
對於配置表,我準備使用一個GameConfig元件來存放所有的配置:
- <blockquote>public class GameConfig : Component
這樣,在載入GameConfig元件的時候,就會呼叫對應的Awake事件,所以可以寫一個Awake事件來載入所有的配置元件,而這些配置元件將都放在GameConfig的configEntity元件上。
- [EventSystem(typeof(GameConfig))]
- public class AwakeSystem : IAwakeSystem, IAwake
- {
- public void Awake(Component component)
- {
- if (component is GameConfig game)
- {
- game.configEntity = (Entity)Game.ObjectPool.Get<Entity>();
- }
- }
- }
在載入GameConfig這個元件時,就會執行這一事件。
接下來就是具體配置表的載入了,這時候需要定義一種新的事件型別,這種事件型別不似awake事件那樣具有通用性,通過類名來儲存,而是通過事件名來儲存,所以需要新建一個事件型別:
- [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
- public class EventSystemAttribute : Attribute
- {
- ……
- public string eventType;
- ……
- public EventSystemAttribute(string type)
- {
- eventType = type;
- }
- }
在原來的EventSystemAttribute類中,加入一個新的引數string型別的eventType。
- public interface IEventSystem
- {
- }
- public interface IEvent
- {
- void Handle(Component component);
- }
設計一個對應該函式的介面。
- public class EventSystem
- {
- ……
- private readonly ListDictionary<string, IEventSystem> eventSystems = new ListDictionary<string, IEventSystem>();
- ……
- public void InitSystems()
- {
- foreach (Type type in Assembly.GetTypes())
- {
- object[] objects = Attribute.GetCustomAttributes(type);
- if (objects.Length == 0)
- {
- continue;
- }
- foreach (object obj in objects)
- {
- if (obj is EventSystemAttribute e)
- {
- object sys = Activator.CreateInstance(type);
- if (sys is IAwakeSystem awake)
- {
- awakeSystems.Add(e.ClassType, awake);
- }
- if (sys is IEventSystem evt)
- {
- eventSystems.Add(e.eventType, evt);
- }
- }
- }
- }
- }
- ……
- }
而後將介面載入到EventSystem類中。
- public class EventSystem
- {
- ……
- public void ExecuteEvent(Component component,string eventType)
- {
- List<IEventSystem> systems = eventSystems.Get(eventType);
- if (systems == null)
- {
- return;
- }
- foreach (IEventSystem ievent in systems)
- {
- try
- {
- if (ievent is IEvent evt)
- {
- evt?.Handle(component);
- }
- }
- catch(Exception e)
- {
- Debug.Log(e.ToString());
- }
- }
- }
- }
然後再通過這個函式來呼叫它。
接下來就是在GameConfig的Awake函式裡呼叫這個函式:
- [EventSystem(typeof(GameConfig))]
- public class GameConfigAwake : IAwakeSystem, IAwake
- {
- public void Awake(Component component)
- {
- if (component is GameConfig game)
- {
- game.configEntity = (Entity)Game.ObjectPool.Get<Entity>();
- Game.EventSystem.ExecuteEvent(game, EventType.InitConfigEvent);
- }
- }
- }
然而,用string作為型別是很容易出錯的,因為很容易打錯字。所以可以用一個部分類來作為可擴充套件的型別表:
- static partial class EventType
- {
- public const string InitConfigEvent = "InitGameConfigEvent";
- }
這樣就可以在多個地方同時編輯EventType類了,比如:
檔案一:
- static partial class EventType
- {
- public const string InitConfigEvent = "InitGameConfigEvent";
- }
檔案二:
- static partial class EventType
- {
- public const string AnotherEvent = "AnotherEvent";
- }
這樣,以後新增新的事件的時候,就不用再開啟某個固定的EventType類檔案去改,只需在一個檔案裡就可以做到在EventType類中新增新的變數名。記得讓字串的內容和型別名寫成一樣,這樣可以避免事件名有重複。
好了,準備了這麼多,可以開始做正事了,載入配置表,首先是載入科技花費的表:
這張表需要載入的其實只是下面這幾個:
儲存的結構很簡單:
- public class TechnologyCost : Component
- {
- public Dictionary<int, int> cost;
- public int GetCost(int level)
- {
- return cost[level];
- }
- }
接下來就是寫一個事件,載入這個元件到GameConfig的configEntity實體上
- [EventSystem(EventType.InitConfigEvent)]
- public class LoadTechnologyCost : IEventSystem, IEvent
- {
- public void Handle(Component component)
- {
- if (component is GameConfig game)
- {
- game.configEntity.AddComponent<TechnologyCost>();
- }
- }
- }
EventSystem(EventType.InitConfigEvent)意味著這個事件將載入到EventSystem.eventSystems中。並在GameConfigAwake這一事件中呼叫。
接下來是具體的載入,我將載入的方法放在了TechnologyCost元件的Awake方法中:
- [EventSystem(typeof(TechnologyCost))]
- public class AwakeTechnologyCost : IAwakeSystem, IAwake
- {
- public void Awake(Component component)
- {
- if (component is TechnologyCost techCost)
- {
- techCost.cost = new Dictionary<int, int>();
- List<string[]> costFile = CSVUtil.Process("CSV/technologyCost");
- int key;
- int value;
- for (int i = 0; i < costFile.Count; i++)
- {
- if (i == 0)
- continue;
- if (costFile[i] != null)
- {
- try
- {
- key = Convert.ToInt32(costFile[i][0]);
- value = Convert.ToInt32(costFile[i][1]);
- if (!techCost.cost.ContainsKey(key))
- {
- techCost.cost.Add(key, value);
- }
- }
- catch (Exception e)
- {
- Debug.Log(e.ToString());
- }
- }
- }
- foreach (KeyValuePair<int, int> valuePair in techCost.cost)
- {
- Debug.LogFormat("level:{0} cost:{1}", valuePair.Key, valuePair.Value);
- }
- }
- }
- }
最後幾行,會把讀取後的內容列印出來用於測試,將來會去掉。
載入的程式碼原理和上面的一樣,我就直接放出來了。
- <blockquote>using System;
這樣,以後每要載入一個新的配置表,都只需要在一個檔案裡改就行了,不用同時修改多個檔案,這也是前面做了一大堆準備工作的目的所在。
相關閱讀:
從零開始做一個SLG遊戲(一):六邊形網格
從零開始做一個SLG遊戲(二):用mesh實現簡單的地形
從零開始做一個SLG遊戲(三):用unity繪製圖形
從零開始做一個SLG遊戲(四):UI系統之主介面搭建
從零開始做一個SLG遊戲(五):UI系統之彈窗功能
從零開始做一個SLG遊戲(六):UI系統擴充套件
從零開始做一個SLG遊戲(七):遊戲系統以及配置表
作者:觀復
專欄地址:https://zhuanlan.zhihu.com/p/70715555
相關文章
- 從零開始做一個SLG遊戲(七):遊戲系統以及配置表遊戲
- 從零開始做一個SLG遊戲(一):六邊形網格遊戲
- 從零開始做一個SLG遊戲(六):UI系統擴充套件遊戲UI套件
- 從零開始做一個SLG遊戲(三):用unity繪製圖形遊戲Unity
- 從零開始做一個SLG遊戲(四):UI系統之主介面搭建遊戲UI
- 從零開始做一個SLG遊戲(五):UI系統之彈窗功能遊戲UI
- 從零開始做一個SLG遊戲(二):用mesh實現簡單的地形遊戲
- 從零開始打造一個iOS圖片載入框架(一)iOS框架
- 從零開始:用REACT寫一個格鬥遊戲(一)React遊戲
- 從零開始實現放置遊戲(一)遊戲
- 從零開始打造一個iOS圖片載入框架(三)iOS框架
- 從零開始打造一個iOS圖片載入框架(四)iOS框架
- 從零開始打造一個iOS圖片載入框架(二)iOS框架
- phaser3入門教程-從零開始開發一個打磚塊遊戲遊戲
- 從零開始:用REACT寫一個格鬥遊戲(二)React遊戲
- 從零點五開始用Unity做半個2D戰棋小遊戲(一)Unity遊戲
- 從零開始實現放置遊戲(六):Excel批量匯入遊戲Excel
- 從零開始寫一個ExporterExport
- 從零開始開發一個 WebpackWeb
- 從零開始徒手擼一個vue的toast彈窗元件VueAST元件
- [ 從零開始配置一個 Windows 前端開發環境 ] - 一:WT + WSLWindows前端開發環境
- [ 從零開始配置一個 Windows 前端開發環境 ] - 二:vscodeWindows前端開發環境VSCode
- 從零開始搭建一個 Webpack 開發環境配置(附 Demo)Web開發環境
- 從零開始--webpack 4 配置Web
- 從零開始實現一個RPC框架(零)RPC框架
- 從零開始實現放置遊戲(一):整體框架搭建遊戲框架
- 【從零開始擼一個App】PKCEAPP
- 【從零開始擼一個App】KotlinAPPKotlin
- 從零開始仿寫一個抖音App——開始APP
- 從零開始完成一個Android JNI開發Android
- 從零開始寫一個node爬蟲(一)爬蟲
- 從零開始實現一個RPC框架(一)RPC框架
- VsCode從零開始配置一個屬於自己的Vue開發環境VSCodeVue開發環境
- 從零開始搭建一個 hexo 部落格。Hexo
- 從零開始搭建一個mock服務Mock
- 從零開始搭建一個vue專案Vue
- 從零開始設計一個部落格
- 從零開始實現一個簡易的Java MVC框架(八)–製作StarterJavaMVC框架