公司动态
Unity Package本地链接:ET框架插件开发效率提升实战指南
1. 项目概述为什么ET框架插件开发绕不开本地链接如果你正在用ET框架做项目尤其是涉及到需要复用的模块或者想开发一个独立的插件包那你一定遇到过这个场景你辛辛苦苦写了一个通用模块比如一个网络协议处理器或者一个UI组件想把它抽成Package给项目里的其他模块用。按照常规思路你得先打包成.unitypackage或者发布到内部的npm仓库然后在主项目里更新依赖。但每次改一行代码都要重复“修改 - 打包 - 发布 - 导入”这个循环调试效率低到让人抓狂。这就是“Unity Package本地链接”技术要解决的核心痛点。它允许你将一个本地的文件夹直接以Package的形式链接到你的Unity项目中。你对本地Package代码的任何修改Unity编辑器都能近乎实时地感知并重新编译就像这些代码原本就写在项目的Assets目录下一样。对于ET框架这种强调热更新、模块化架构的项目来说掌握这项技巧不是“锦上添花”而是“雪中送炭”。它能让你在开发ET插件时获得与开发项目内脚本几乎无异的流畅体验同时保持代码的模块化和可复用性。简单来说这个技巧能让你实现“编码即调试”修改本地Package的代码Unity立刻重新编译无需手动导入。保持项目结构清晰核心业务逻辑、通用模块、编辑器工具都能以Package形式管理主项目Assets目录不再臃肿。无缝对接ET的模块化设计ET框架本身大量使用Package来组织代码如Core、Model、Hotfix等开发自己的插件时沿用这套范式理解和集成成本最低。接下来我会以一个实际的ET插件开发过程为例拆解从零配置本地链接到高级调试的完整流程并分享我踩过的坑和总结出的最佳实践。2. 核心原理与前置知识Package、AsmDef与ET的模块化哲学在动手之前我们需要统一几个关键概念这能帮你理解后续所有操作的“为什么”。2.1 Unity Package的本质不仅仅是文件夹很多人以为Unity Package就是一个压缩包。在本地链接的语境下它更准确的定义是一个符合特定结构的文件夹并且包含一个名为package.json的清单文件。这个文件定义了包的名称、版本、依赖关系等元数据。当Unity通过file:协议链接这个文件夹时它会将这个文件夹视为一个特殊的、只读的Packages目录下的子模块。ET框架对Package有更严格的命名规范通常采用cn.etetet.作为前缀例如cn.etetet.network。这不仅是命名空间也对应了其在npm仓库如GitHub Packages上的发布地址确保了唯一性。2.2 程序集定义文件AsmDef代码隔离的基石AsmDefAssembly Definition File是Unity实现代码模块化编译的核心。每个AsmDef文件会告诉Unity“我这里的.cs文件请打包成一个独立的DLL程序集”。ET框架重度依赖AsmDef来实现服务端/客户端代码分离、热更新层与AOT层隔离。在你的ET插件Package里你会看到多个AsmDef文件Runtime/目录下的AsmDef如ET.MyPlugin.Runtime.asmdef定义AOT预先编译代码的程序集。Editor/目录下的AsmDef如ET.MyPlugin.Editor.asmdef定义仅在Unity编辑器中运行的代码。根目录或Scripts/目录下的AsmDef用于组织Model、Hotfix等逻辑代码。本地链接的关键之一就是确保这些AsmDef定义的引用关系正确无误。Unity在编译时会解析所有被链接Package中的AsmDef并建立正确的程序集依赖链。2.3 ET框架的目录结构约定ET插件Package有自己约定的目录结构理解它你才能正确创建包。一个标准的ET插件Package目录树通常如下MyETPlugin/ ├── package.json # Package清单包含名称、版本、依赖 ├── packagegit.json # ET特有用于声明Git依赖和包ID ├── README.md ├── Runtime/ │ ├── ET.MyPlugin.Runtime.asmdef # AOT层程序集定义 │ └── ... (AOT代码文件) ├── Editor/ │ ├── ET.MyPlugin.Editor.asmdef # 编辑器程序集定义 │ └── ... (编辑器工具代码) └── Scripts/ # 核心逻辑代码支持热更新 ├── Server/ │ ├── Model/ # 服务端Model层 │ └── Hotfix/ # 服务端Hotfix层 ├── Client/ │ ├── ModelView/ # 客户端Model层 │ └── HotfixView/ # 客户端Hotfix层 └── Share/ # 双端共享代码Scripts下的Model/Hotfix等目录需要与你的项目中的Assets/Model,Assets/Hotfix等目录通过AsmDef引用关联起来。ET框架的工具如ET-Refresh菜单会帮你自动化这部分引用配置。3. 实战一步步创建并链接你的第一个ET插件Package理论讲完我们动手创建一个名为cn.etetet.debughelper的简单调试辅助插件并将其本地链接到主项目。3.1 步骤一创建插件Package的骨架首先在你喜欢的位置不要放在Unity项目的Assets或Packages目录内创建一个新文件夹例如D:\Dev\ETPlugins\DebugHelper。初始化package.json在DebugHelper根目录创建package.json。{ name: cn.etetet.debughelper, version: 1.0.0, displayName: ET Debug Helper, description: A debug utility package for ET Framework., unity: 2022.3, dependencies: { cn.etetet.core: 6.0.0 // 假设依赖ET核心包 }, author: { name: YourName } }注意name字段必须全局唯一遵循ET的命名规范。unity字段指定了兼容的Unity最低版本。创建packagegit.json这是ET框架用于管理内部Git依赖的文件。{ Id: cn.etetet.debughelper, Name: ET Debug Helper, GitDependencies: { cn.etetet.core: https://github.com/ET-Packages/cn.etetet.core.git } }创建程序集定义AsmDef在Runtime/目录下创建ET.DebugHelper.Runtime.asmdef。其内容定义了这个程序集的名字和可被引用的程序集。{ name: ET.DebugHelper.Runtime, references: [ ET.Core // 引用ET的核心运行时程序集 ], includePlatforms: [], excludePlatforms: [], allowUnsafeCode: false, overrideReferences: false, precompiledReferences: [], autoReferenced: true, defineConstraints: [], versionDefines: [], noEngineReferences: false }在Editor/目录下创建ET.DebugHelper.Editor.asmdef。注意includePlatforms包含了Editor。{ name: ET.DebugHelper.Editor, references: [ ET.DebugHelper.Runtime, ET.Core.Editor ], includePlatforms: [Editor], autoReferenced: false }创建示例代码在Runtime/下创建一个C#脚本DebugLogger.cs提供简单的日志功能。using UnityEngine; namespace ET.DebugHelper { public static class DebugLogger { public static void Log(object message) { Debug.Log($[ET DebugHelper] {message}); } } }在Editor/下创建一个编辑器工具脚本DebugHelperWindow.cs提供一个简单的编辑器窗口。3.2 步骤二在主项目中配置本地链接现在我们回到你的ET主Unity项目。修改Packages/manifest.json这是最直接的方法。打开项目根目录下的Packages/manifest.json文件。在dependencies区块中添加你的本地Package路径。路径是相对于manifest.json文件所在位置的。{ dependencies: { cn.etetet.core: 6.0.0, cn.etetet.debughelper: file:../../../Dev/ETPlugins/DebugHelper, // 你的本地路径 ... // 其他依赖 }, scopedRegistries: [...] }关键点file:后面的路径是相对路径。../../../表示向上三级目录。你需要根据你的实际目录结构进行调整。一个可靠的技巧是在文件管理器中将本地Package文件夹拖拽到manifest.json所在的Packages文件夹然后看地址栏显示的相对路径。保存manifest.json。切换回Unity编辑器Unity会自动开始导入和编译新添加的本地Package。你可以在Package Manager窗口中选择“Packages: In Project”视图看到你的cn.etetet.debughelper包其版本号会显示为file:开头的路径。3.3 步骤三配置外部工具与项目生成为了让IDE如Rider或VS能正确识别和跳转到本地Package中的代码需要进行关键设置。打开Unity编辑器进入Edit Preferences External Tools。找到“Generate .csproj files for:”这一选项。确保“Local packages”前面的复选框是勾选状态。为什么必须勾选这个选项告诉Unity在为解决方案生成.csprojC#项目文件时需要将本地链接的Package也包含进去。如果不勾选你的IDE将无法看到本地Package中的源代码导致代码提示、跳转和调试功能全部失效。配置完成后点击Unity菜单栏的Assets Open C# Project或者直接在你的IDE中重新加载解决方案。此时你应该能在解决方案资源管理器中看到以你Package名命名的项目例如cn.etetet.debughelper并且可以自由地浏览和编辑其中的代码。4. 高级技巧与深度配置让本地开发如虎添翼基础链接成功后我们来看看如何应对更复杂的场景让开发体验更上一层楼。4.1 使用packagegit.json管理复杂的Git依赖你的插件可能不仅依赖cn.etetet.core还可能依赖其他ET官方包或团队内部的私有包。packagegit.json就是用来声明这些Git仓库依赖的。{ Id: cn.etetet.debughelper, Name: ET Debug Helper, GitDependencies: { cn.etetet.core: https://github.com/ET-Packages/cn.etetet.core.git, cn.etetet.ui: https://github.com/your-team/et-ui-package.git, cn.etetet.config: https://github.com/ET-Packages/cn.etetet.config.git#v2.1.0 // 指定分支或标签 } }当你在主项目中执行ET框架的刷新命令如通过菜单ET-Refresh时框架工具会读取这个文件并确保这些Git依赖被正确克隆或更新到项目的Packages目录下通常在一个特定的缓存位置。这使得多包协同开发变得非常清晰。4.2 处理AsmDef引用与宏定义的“坑”这是本地链接中最容易出错的地方之一。ET框架的Scripts目录下的代码Model, Hotfix等需要被主项目中的程序集引用。运行ET-Refresh这是最关键的一步。这个命令会扫描所有Package中的packagegit.json和AsmDef并自动配置主项目Assets目录下那几个核心Asmdef如Model,Hotfix,ModelView,HotfixView对Package中对应代码的引用。你不需要手动去修改这些Asmdef的references列表。处理INITED宏对于包含Model等代码的Package常被称为“Demo包”或“功能包”其AsmDef通常需要添加一个INITED编译符号。这个宏的作用是只有当你在主项目中执行了ET-Init操作后这些代码才会被编译。这是为了防止在项目初始克隆、依赖尚未完全拉取时因代码引用缺失而导致的编译错误。如何添加在你的Package的AsmDef文件例如Scripts/Server/Model/下的那个的defineConstraints字段或通过AsmDef Inspector面板添加INITED条件。避坑指南如果你明明链接了包但里面的代码在Unity里显示“找不到类型或命名空间”第一件事就是检查这个AsmDef是否加了INITED宏以及主项目是否已经执行过ET-Init。4.3 实现真正的“编辑-运行”无缝调试本地链接的最大优势是即时反馈。但为了达到最佳效果避免在Play模式下修改Package代码虽然Unity支持一定程度的运行时重编译但对于ET这种涉及热更新层和AOT层交互的复杂框架在游戏运行时修改底层Package代码可能导致不可预知的行为或崩溃。最佳实践是停止运行 - 修改代码 - 等待编译完成 - 再次运行。利用Unity的“Asset Pipeline”如果你在Package的Editor目录下编写了工具脚本它们会像项目内的编辑器脚本一样在Unity编译后立即生效。你可以创建菜单项、编辑器窗口并直接调用主项目或PackageRuntime中的API。5. 常见问题排查与解决方案实录即使按照步骤操作你也可能会遇到一些问题。下面是我在实践中总结的“故障排查手册”。问题现象可能原因解决方案Unity Package Manager中看不到本地包或显示为灰色。1.manifest.json中的file:路径错误。2. 本地Package的package.json格式错误或缺少必填字段。1. 检查并修正file:后的相对路径。使用绝对路径如file:///D:/Dev/...也可行但不利于团队协作。2. 使用JSON验证工具检查package.json确保name,version等字段正确。IDERider/VS中无法打开本地Package的源代码提示“项目未加载”。1. Unity的External Tools设置中未勾选“Local packages”。2..csproj文件生成失败或已过时。1. 确认Edit Preferences External Tools下的“Local packages”已勾选。2. 在Unity中执行Assets Open C# Project重新生成。或关闭IDE删除项目根目录的.sln和.csproj文件让Unity重新生成。编译错误The type or namespace name ET could not be found。1. Package的AsmDef未正确引用ET核心程序集如ET.Core。2. 主项目未正确引用包含该代码的Package程序集。3. 涉及Model/Hotfix的代码未执行ET-Refresh。1. 检查Package中Runtime目录下AsmDef的references是否包含ET.Core。2. 对于Scripts下的代码确保已执行ET-Refresh命令。3. 检查是否有INITED宏限制并确认主项目已初始化。修改本地Package的代码后Unity没有自动重新编译。1. Unity的脚本编译检测有延迟。2. Package目录可能被某些工具如杀毒软件、Dropbox锁定了文件更改通知。1. 尝试手动触发编译点击Unity编辑器任意位置或按CtrlRWindows刷新。2. 检查Package目录是否在Unity项目的Assets或Library子目录内错误位置应移至外部。将目录添加到杀毒软件排除列表。本地链接的Package在团队其他成员的机器上失效。manifest.json中使用了绝对路径file:///。强制使用相对路径。约定一个团队内统一的仓库目录结构例如所有本地包都放在与项目同级的../ExternalPackages/目录下。这样file:../../ExternalPackages/DebugHelper对所有人都会指向正确的位置。执行ET-Refresh后原先的代码引用丢失了。Refresh命令会基于packagegit.json重新配置引用如果该文件配置不全或错误会导致引用丢失。仔细检查Package中的packagegit.json确保GitDependencies部分包含了所有必要的依赖包。并确保这些依赖包本身也能被正确获取如果是私有仓库需要配置Git凭证。一个真实的踩坑案例我曾将一个工具包的Editor代码放在Runtime目录下因为它包含了一些运行时也能用的工具函数。结果在打包Build时Unity试图将这些编辑器代码打包进玩家版本导致编译错误。教训严格遵循Unity的目录约定。Editor文件夹下的代码只在编辑器中运行和编译Runtime下的代码则会打入所有平台的玩家包。用AsmDef的includePlatforms来精确控制代码的运行环境。6. 从本地链接到发布自动化工作流建议本地链接用于开发最终你的优秀插件可能需要分享给团队或社区。这时就需要发布到包仓库。版本管理在package.json中更新正式的版本号如1.0.0遵循语义化版本控制。准备发布配置在package.json中添加publishConfig指向你的npm仓库如GitHub Packages。publishConfig: { registry: https://npm.pkg.github.com/你的组织名 }使用GitHub Actions自动化这是ET官方推荐的方式。在你的插件Package仓库中创建.github/workflows/release-package.yml工作流文件。这个工作流可以在你创建Git标签时自动运行npm publish将包发布到配置的仓库。你可以从ET官方包仓库如cn.etetet.yiui中复制现成的workflow文件来修改。切换依赖发布成功后将主项目manifest.json中的依赖从本地路径file:...改为版本号cn.etetet.debughelper: 1.0.0并确保scopedRegistries配置正确指向你的包仓库。从本地链接的便捷开发到自动化发布的规范流程这套组合拳能让你在ET框架的插件开发中游刃有余。记住本地链接的核心价值在于提升开发迭代速度而规范的发布流程则保证了代码的可复用性和可维护性。花点时间搭建好这个环境后续的插件开发工作会顺畅得多。