自定义语法的实现主要通过以下模块协作完成,涉及从文本输入到脚本编译和执行的完整流程。以下是核心逻辑的总结:
1. 文本处理与分词(Tokenizer.cs)
- 功能:将输入的脚本文本分解为
Token
,识别关键字、方法、参数、块等。 - 实现:
- 通过
Tokenizer
类处理逐行文本,识别Cycle
(如 Now、Once、Loop)、Method
、Statement
、Comment
等 token 类型。 - 使用正则表达式(
KeywordRegex
)在分词前替换全局关键字(如中文“若”替换为“if”),支持中文编程和简易语法。 - 支持中文标点转换为英文标点(如“:”转为“:”),统一格式。
- 处理块结构(
{
和}
),支持嵌套块(如方法定义或条件语句)。 - 跳过引号内的内容,避免误替换字符串中的关键字。
- 通过
- 关键点:
- 全局替换表(
ScriptSyntax.GlobalVariables
)简化了语法扩展,允许中文编程和自定义简写。
- 全局替换表(
2. 语法解析(CommonParser.cs 和 UnifiedCompiler.cs)
- 功能:将 token 解析为
Command
和ScriptStatement
,构建ScriptStructure
。 - 实现:
CommonParser.ParseTokens
:遍历 token,识别周期类型(Now、Once、Loop、Import、Value、Method),解析方法调用和参数。- 支持嵌套命令(
NestedCommands
)和显式目标对象(target
参数)。 UnifiedCompiler
:负责具体语句的识别,转换为Command
对象,处理方法调用、赋值、移动等。- 参数以字符串形式存储,延迟类型解析到运行时,增加灵活性。
ScriptStructure
存储解析结果,包含各类命令(Now、Once、Loop)、导入语句、变量声明、方法定义和剩余语句。
- 关键点:
- 解析支持简易语法(如
move up 1
转为Move
命令)。 - 保留未识别的语句(
RemainingStatements
),允许混合原生 C# 代码。 - 方法定义(
MethodDefinition
)支持自定义方法,解析方法签名和体内的语句。
- 解析支持简易语法(如
3. 代码生成(CodeGenerator.cs)
- 功能:将
ScriptStructure
转换为可执行的 C# 脚本,分为MainScript
(Once 和 Loop)和NowScript
(Now)。 - 实现:
GenerateMainScript
:- 生成
Start
方法(Once 命令)和Update
方法(Loop 命令)。 - 包含导入语句(
using
)、变量声明(ValueStatements
)和自定义方法。 - 支持协程(
IEnumerator
)和普通方法调用,自动选择StartCoroutine
或直接调用。
- 生成
GenerateNowScript
:- 生成一次性执行的脚本,包含
ExecuteCommands
协程,依次执行 Now 命令。 - 在执行完后销毁自身(
Destroy(this)
)。
- 生成一次性执行的脚本,包含
SerializeCommand
:将Command
序列化为方法调用,处理参数类型(如Vector3
、字符串等)和默认值。ConvertValueToCSharp
:将字符串参数转换为 C# 表达式(如(1,2,3)
转为new Vector3(1,2,3)
)。
- 关键点:
- 区分协程和普通方法调用,避免 Loop 中重复启动协程。
- 使用
RawParameters
保留原始参数格式,确保自定义方法调用正确。 - 生成的脚本以唯一命名(
Guid
)避免冲突。
4. 脚本编译与附加(ScriptCompiler.cs)
- 功能:将生成的 C# 代码编译为程序集并附加到
GameObject
。 - 实现:
- 使用
Microsoft.CodeAnalysis
编译 C# 代码,引用 Unity 和系统程序集(cachedReferences
)。 - 异步编译(
Task.Run
和协程),避免阻塞主线程。 - 检查脚本内容是否变化,避免重复编译(
lastCompiledScript
)。 - 移除旧脚本组件(
GeneratedScript
或TempNowScript
),附加新编译的组件。 - 缓存编译结果(
compiledScripts
),支持后续访问。 ParseScript
:整合 token 解析,处理 Method 块,生成完整ScriptStructure
。
- 使用
- 关键点:
- 编译优化显著(异步+缓存),无卡顿(2025/4/14 记录)。
- 支持直接编译 C# 脚本(
CompileCSharpScript
),跳过原生解析。 - 方法定义解析(
ParseMethodDefinition
)使用正则匹配签名,确保格式正确。
5. 运行时支持(ScriptFunctions.cs)
- 功能:提供自定义方法库,供生成的脚本调用。
- 实现:
- 包含移动(
Move
、MoveCoroutine
)、旋转(Rotate
)、缩放(Scale
)、物理(Force
、AddCollider
)、事件(OnCollision
、OnKeyPress
)等方法。 - 支持协程和普通版本,适应不同周期(Now 使用协程,Loop 使用普通)。
print
方法支持彩色输出(ScriptOutputDisplay
),解析颜色字符串(如"red"
或(1,0,0)
)。- 事件处理通过辅助类(
CollisionHandler
、KeyPressHandler
等)实现动态注册。
- 包含移动(
- 关键点:
- 方法抽象化,减少脚本复杂度(如
Move
封装平滑移动逻辑)。 - 物理和事件方法扩展了交互能力(如碰撞检测、鼠标点击)。
- 方法抽象化,减少脚本复杂度(如
6. 用户交互(ObjectSelectionManager.cs 和 ScriptOutputDisplay.cs)
- 功能:提供脚本编辑和输出界面,支持运行时交互。
- 实现:
ObjectSelectionManager
:- 允许选择场景对象(
HandleSelection
),高亮显示(highlightMaterial
)。 - 显示 UI 面板(
ShowUI
),编辑脚本(TMP_InputField
)。 - 保存脚本到
ES3
,支持持久化(SaveInput
)。 - 触发编译(
ProcessScriptAndSave
),附加到选中对象。
- 允许选择场景对象(
ScriptOutputDisplay
:- 显示脚本输出(
AddOutput
),支持颜色和重复计数。 - 自动清空输出(
ClearOutput
),确保界面干净。
- 显示脚本输出(
7. 语法定义(ScriptSyntax.cs)
- 功能:定义自定义语法的关键字、方法名、方向映射和替换规则。
- 实现:
Keywords
和MethodNames
:定义保留字和可调用方法。DirectionMap
:映射方向(如up
到Vector3.up
)。GlobalVariables
:定义替换规则(如引入
转为Import
,红
转为"red"
)。CycleTypes
:支持 Now、Once、Loop、Import、Value、Method 周期。
此方悬停