关卡编辑工具讨论
一个关卡编辑工具框架的相关讨论:尚未完成
国庆妄图拐骗找工作的朋友入伙帮我把很久之前构思的究↗极↘关卡编辑器做出来,目前看来他兴致缺缺,留档先
考虑可设计一个所见即所得的关卡工具,通过Odin Inspector框架实现
关卡工具如以下要素组成:
-
Prefab关卡模块:以 Prefab 的形式呈现,所见即所得
-
如一个路人的模块,可被拖拽至场景中,inspector 面板显示相关配置信息,并可视化相关表现
-
其所需组件有:
-
Transform:用于标识和持久化位置信息,是被收集的核心操作:
-
Indexer:用于标识该信息点位所在的关卡,以及自动分配 ID 实现索引
- (被实例化时,会自动调用 OnEnable 函数,可以通过这个连接编辑器)
- 当编辑器当前已打开关卡文件时,为组件分配 ID,并获取当前 prefab 的信息类型,并将 inspector 上的组件信息储存至关卡编辑器中。
-
InfoComponent:关卡信息组件,用于快捷编辑组件信息
-
当相关组件信息被更改时(如 transform 组件),将自身改变更新至关卡编辑器:
-
考虑通过
Update
监听、CustomEditor
重载、OnValidate
事件等形式实现 -
所有信息组件默认:
void OnValidate() { var Indexer = GetComponent<LevelEditorIndexer>() Indexer.Refresh() }
-
-
-
Render:渲染器,用于将组件信息可视化
-
-
-
InfoComponent信息组件:
-
关卡信息组件用于储存每个关卡对象运作所需的信息:
-
(从这个角度来说,Transform 也是一种特殊的关卡信息组件
-
我们会以 Entity-Component System 的形式对该组件的组合进行组织
- (对这种关卡编辑器的想发最早是从 Unity Dots 框架的设计中来的)
- 基于这种关卡编辑模式,能有效将美术资源与关卡信息绑定
-
LevelEditorIndexer 是独立的关卡信息组件,用于管理细化的关卡信息
- 以 Unity ECS 为例,Indexer 定义了其下管理组件的 ArcheType 原型
-
-
关卡信息组件通常是具体的Component,仅包含数据,即对ArcheType下模块信息的显示
-
可能有两个方向:
- 对于ArcheType下每个信息Component,均创建InfoComponent
- 对ArcheType内的所有信息进行序列化展示
- (我不好评估哪种更合适
-
-
ArcheType原型
-
是关卡编辑器中储存的核心数据,整合多个Component
-
比方说对于一个球,可能包含如下信息Component:
- Transform
- Radius
- Color ...
-
-
大致以如下形式构建:
public class ArcheType { private ArcheTypeConfig _config; private Dictionary<ModuleType, IInfoModule> _modules = new Dictionary<ModuleType, IInfoModule>(); public ArcheType(ArcheTypeConfig config) { _config = config; } public void AddModule(ModuleType moduleType, IInfoModule module) { if (_config.AllowedModules.Contains(moduleType)) { _modules[moduleType] = module; } else { throw new InvalidOperationException($"Invalid module type for {_config.ArcheTypeName}: {moduleType}"); } } // ... 其他方法 ... } // 由配置表导出多种ArcheTypeConfig配置文件 public class ArcheTypeConfig { public string ArcheTypeName { get; set; } public List<ModuleType> AllowedModules { get; set; } = new List<ModuleType>(); }
-
在ArcheType上依据选定原型添加对于Modules储存数据,并满足渲染和储存需要
-
-
Render绘制组件:
-
绘制组件和Indexer联动,基于ArcheType自动加载渲染模块,用于在场景中可视化相关关卡模块(避免了直接使用MeshRender不方便编辑
using System; using UnityEngine; public class ArcheTypeRendererFactory { // 传入ArcheType的类型和GameObject,返回相关的渲染器。 // 如果没有找到对应的渲染器,返回默认的渲染器。 public static MonoBehaviour CreateRendererForArcheType(ArcheType archeType, GameObject gameObject) { string archeTypeName = archeType.GetType().Name; string rendererTypeName = archeTypeName + "Renderer"; // 使用类型名称动态查找Renderer类型 Type rendererType = Type.GetType(rendererTypeName); if (rendererType != null) { // 找到了对应的Renderer类型 return (MonoBehaviour)gameObject.AddComponent(rendererType); } else { // 没有找则添加默认的Renderer return gameObject.AddComponent<DefaultArcheTypeRenderer>(); } } }
-
比方说如果是对路人的渲染器,可能直接在逻辑里写了路人的渲染样式,随机挑选路人实例化。
-
此外,还会按需绘制部分基础信息,如点位名称ID等到地图中
-
关卡编辑器编辑时对模块的隐藏也是通过关闭绘制渲染。
-
-
关卡编辑器(TBD):用于收集全部组件的信息,并完成序列化
-
用于过滤和筛选模组,并赋予相关ID
- (比方说对一类ArcheType可能直接赋予特定ID段
-
通过数据库管理和过滤(提前准备后续项目
-
整合显示ArcheType上的GUI信息
-
相关批处理功能接口
-
批量创建等快捷方式
-
!define RECT class
RECT LevelEditor {
+Refresh()
+GetIndex()
+Init()
-database: Database
}
RECT Database {
+Store(archeType: ArcheType)
+Retrieve(id: ID): ArcheType
}
RECT Prefab {
}
RECT ArcheType {
-_config: ArcheTypeConfig
-_modules: Dictionary<ModuleType, IInfoModule>
+AddModule(moduleType: ModuleType, module: IInfoModule)
}
RECT ArcheTypeConfig {
-ArcheTypeName: string
-AllowedModules: List<ModuleType>
}
RECT Indexer {
+OnEnable()
+Refresh()
+levelId: ID
+PointId: ID
}
RECT InfoComponent {
}
RECT Render {
}
ArcheTypeConfig "1" -- "1" ArcheType : contains
ArcheType "1" o-- "*" Indexer : managed by
ArcheType "1" o-- "*" InfoComponent : contains
ArcheType "1" o-- "*" Render : uses
LevelEditor o-- "*" Indexer : uses
LevelEditor o-- "*" InfoComponent : uses
LevelEditor o-- "*" Render : uses
LevelEditor -- Database : uses
Prefab o-- Indexer : contains
Prefab o-- InfoComponent : contains
Prefab o-- Render : contains
@enduml
Comments NOTHING