Unity
如果你曾使用 Unity 制作过游戏,那么在开始使用 All Out 时,你需要了解一些关键差异!
如果你来自 Unity,你会对以下内容感到熟悉: 实体 + 组件,一个 层级,一个 检查器,以及可复用的 预制体。最大的思维转变是,All Out 游戏是 多人优先:游戏状态会为你同步,而且默认情况下,你编写的大多数逻辑都像是由服务器权威控制的一样。
总结:与 Unity 相比有什么不同
多人联机是默认方式:游戏状态会自动从服务器复制到客户端。通常你 不需要 编写 RPC、SyncVars 或 Netcode 生成逻辑。
要有意识地决定代码在哪里运行:
使用会影响状态的游戏输入/UI,在 服务器 + 本地客户端 (见 is_local_or_server() 模式下(参见 CSL 编写指南)。
避免全局单例状态:多个玩家会连接到同一个会话。优先将状态存储在玩家身上或世界组件中。
移动端优先:除非你的游戏明确面向 PC,否则避免只依赖键盘的假设。
概念映射(Unity → All Out)
项目布局:“脚本”和“资源”存放的位置
脚本:你的游戏代码位于 .csl 文件中。新项目会以一个 main.csl 开始,它会导入引擎并定义生命周期入口点。参见 CSL 入门.
资源:游戏资源位于项目的 /res 目录下,并通过路径引用 不带 这个 /res 前缀(例如: "ui/button.png")。参见 资源与素材.
在 Unity 中,每个 C# 脚本都会被编译,并且可以使用各自的 using 指令。在 All Out 中,请将导入集中管理:
如果你添加了一个文件夹(比如 ui/),请导入该文件夹 一次 在 main.csl
示例:
生命周期:MonoBehaviour → CSL
在 Unity 中,你通常会附加一个 MonoBehaviour 到一个 GameObject 上,并实现:
在 CSL 中,你通常会使用:
中的全局过程 main.csl (用于游戏级设置)
示例组件:
有关生命周期模型的更多背景,请参见 游戏/帧生命周期.
预制体:Unity Prefabs → All Out Prefabs
All Out 预制体是在编辑器中创建的,并且可以在运行时复用或生成。
“序列化字段”(在检查器中暴露的变量)
Unity 使用 [SerializeField] 以及公共字段在检查器中暴露值。在 CSL 中,使用 @ao_serialize 将字段暴露给编辑器。
然后将你的组件添加到一个实体上,在 检查器 中按实体调整数值。
生成和查询:Instantiate/Find → Scene API
Unity 模式:
new GameObject() / Instantiate()
FindObjectOfType<T>(), GetComponentsInChildren<T>()
All Out 模式:
碰撞与触发器:默认“没有回调”
如果你习惯于 OnTriggerEnter / OnCollisionEnter,请注意,CSL 不依赖碰撞回调来编写游戏玩法脚本。一种常见模式是查询附近的组件并检查距离。
多人联机思维:输入、UI,以及“代码在哪里运行”
在 Unity 中,你通常可以假设“我的客户端拥有我的角色”。在 All Out 中,请采用服务器权威的思维方式:
影响游戏状态的输入/UI:在能够影响权威状态的地方运行(通常是服务器 + 本地客户端)
参见 CSL 编写指南中使用以下内容的示例 is_local_or_server() 与 is_local().
Unity 到 All Out 的常见陷阱
单例管理器:优先使用每玩家或每实体状态,而不是全局 GameManager 风格的单例。
导入习惯:从 main.csl 导入引擎和文件夹(不要把导入分散到许多文件中)。
假设是单人游戏:始终思考“如果有 10 个玩家连接会发生什么?”
硬编码桌面端输入:除非是有意为之,否则避免要求键盘/鼠标。