原标题:游戏开发框架设计规则!
目的
- 新增新功能时更加快速便捷,不会导致其他模块的改变,上下文清晰,更不容易出逻辑缺陷
- 方便调试时理清逻辑关系,快速定位问题
- DOTS、OOP、组件式开发的优缺点
- 设定条条框框的规则,能尽量private就尽量private,强迫程序员设计出更好的代码
- 优点
- 简单易用
- 内部不透明,无需了解内部实现直接用(多用于工具类)
- 缺点
- 引用混乱
- 代码依赖性和耦连
- 违反匿名者原则(越少人知道越好)
- 不用它,可以强迫设计出更好的代码
- 强调 系统间 的交互
- 系统之间不要直接交流,而是通过中间件交流,例如事件管理器,观察者模式
- 尽量不用单例模式,全局变量容易交叉使用,造成理解混乱和系统之间的耦连
- 分离判端逻辑和执行逻辑
- 游玩过程每获得100金币则获得一个成就,并且播放成就音效
现在看起来复杂,执行效率看起来很低,但是方便以后维护的代码:
publicclassGameEvent{//全局变量事件publicconstintON_COIN_OVER_100 = 1; }
publicclassGameCoreSystem{privateintm_Coin;
privatevoidUpdate( ) {//...//每获得100金币触发成就事件if(m_Coin++ > 100) {m_Coin = 0; EventManager.instance.Invoke(GameEvent.ON_COIN_OVER_100);}}}
publicclassAchievementManager{publicAchievementManager( ) {//注册"获得成就"的事件EventManager.instance.RegEvent(GameEvent.ON_COIN_OVER_100).trigger += OnAchieved;}
privatevoidOnAchieved( objectsender, objectreciever, object[] args ) {//获得成就后的逻辑varachievementUid = ( int)args[ 0]; if(achievementUid == GameEvent.ON_COIN_OVER_100) {//...}}
~AchievementManager{//随着成就系统内存释放,去掉注册事件EventManager.instance.RegEvent(GameEvent.ON_COIN_OVER_100).trigger -= OnAchieved;}}
publicclassGameAudioSystem: AudioManager{protectedoverridevoidOnInit( ) {//在音频系统注册"获得成就"的事件EventManager.instance.RegEvent(GameEvent.ON_COIN_OVER_100).trigger += OnTrigger;}
privatevoidOnTrigger( objectsender, objectreciever, object[] args ) {//实现逻辑PlayOneShot( "sfx_button_enter"); }
privatevoidOnDestroy( ) {//随着音频系统内存释放,去掉注册事件EventManager.instance.RegEvent(GameEvent.ON_COIN_OVER_100).trigger -= OnTrigger;}}
高内聚: internal和Assembly Definition 综述
- 强调 系统内 逻辑
- 程序集去代表一个模块的功能,上级只引用该程序集中仅有的一个对外的管理该程序集的类
- 强迫程序员设计出更好的代码,高内聚更体现代码的复用性
- 编译根据程序集来进行,节约时间
- 脑图
- 程序集和目录结构
- 设计原则
- 一个程序集所有类可以对外public,有一个管理的类,名称为$"{程序集名称}System",有一个单例静态引用为internal,方便其他子系统访问
- 除了NoteSystem,所有类的对外接口限定词为internal,包括构造函数,保证了接口的封闭性与安全性
- 一个母系统配合几个子系统完成这个系统模块的功能,从而提供对外统一在大系统的接口,保证代码设计的高内聚
internalNote( int_tick, byte_noteDataUid ) {tick = _tick;noteDataUid = _noteDataUid;}}
privateNativeArray<Note> m_Notes;
privatereadonlyNoteDataSystem m_NoteDataSystem;
privatereadonlyNoteTickSystem m_NoteTickSystem;
internalstaticNoteSystem instance;
publicNoteSystem( ) {instance = this; m_NoteDataSystem = newNoteDataSystem; m_NoteTickSystem = newNoteTickSystem; }...
NoteDataSystem
privateList< string> GetStrings( intnumber, List< string> list ) {...}
internalNoteData( byte_uid, byte_type, uint_score, uint_hp, uint_mp, uint_damage, byte_audio, byte_effect, int_bmss, int_renderer ) {...}
internalvoidSetNoteData( stringbms, stringscene ) {...} }
privateNativeArray<NoteData> m_NoteDatas; ...
internalNoteDataSystem( ) {...}
internalNoteData GetNoteData( stringbms, stringscene ) {...}
internalNoteData GetNoteData( byteuid ) {...}
~NoteDataSystem {...}}
NoteTickSystem
internalNoteTick( byte_uid, byte_offset, bool_isLeft ) {uid = _uid;offset = _offset;isLeft = _isLeft;}}
privateDictionary< int, NativeArray<NoteTick>> m_NoteTicks;
internalNoteTickSystem( ) {}
internalvoidSetup( NativeArray<NoteSystem.Note> notes) {Debug.Log( "NoteTickSystem Setup!"); }
internalNativeArray<NoteTick> GetNoteTicks( inttick ) {returnm_NoteTicks[tick]; }...
- GameCoreSystem也同理
publicGameCoreSystem( ) {m_NoteSystem = newNoteSystem; }...
PeroTools2
- 部分Mnanager将不再支持外部的单例模式,游戏过程用到的Manager并且和特定属性有关的去单例,如AudioManager、UIManager、ServerManager、SceneManager,要承接上下文的则不去单例,如ResourcesManager、ConfigManager、CoroutineManager。
internal staticT instance {get{if(s_Instance == null) {s_Instance = newT; Singleton.Init(s_Instance);}returns_Instance; }}
publicvoidReset{Singleton.Destroy(s_Instance);s_Instance = default; }}
publicclassSingleton<T> : SingletonInternal<T> where T : new{publicnewstaticT instance => SingletonInternal<T>.instance; }
- 通用代码的叫Manager, 特殊代码的叫System
- 无法单例的Manager通过继承来完成功能
privatevoidOnTrigger( objectsender, objectreciever, object[] args ) {PlayOneShot( "sfx_button_enter"); }
privatevoidOnDestroy( ) {EventManager.instance.RegEvent(GameEvent.ON_COIN_OVER_100).trigger -= OnTrigger;}}
其他 Unity如何创建程序集
- 引用上你需要用到的其他程序集
- 不同平台程序集的开启和关闭
- 反注入依赖
来源:Muse Dash主程,peropero技术渣渣担当游戏网
责任编辑: