当前位置: 首页 > news >正文

ET框架插件开发:Unity Package本地链接实战指南

1. 项目概述:为什么本地链接是ET插件开发的命门?

如果你正在用ET框架做游戏开发,尤其是涉及到需要频繁修改和测试的自定义插件或模块,那你一定对“打包-发布-导入-测试”这个循环深恶痛绝。每次改几行代码,都要经历一遍完整的打包发布流程,效率低得令人发指。而Unity Package的本地链接(Local Linking)技术,就是打破这个效率瓶颈的“金钥匙”。它允许你将一个正在开发的Package,像引用本地文件夹一样直接链接到你的主项目中,实现代码的实时同步和即时编译。对于ET框架这种强调热更新、模块化开发的架构来说,掌握本地链接技巧,就意味着你的插件开发效率能提升一个数量级。

ET框架本身就是一个由大量Package(如cn.etetet.corecn.etetet.hotfix等)构成的生态系统。无论是为ET开发一个通用的网络协议包、一个UI组件库,还是一个特定的游戏逻辑模块,最终都会以Package的形式存在。本文将从一线开发者的实战角度,彻底拆解在ET框架生态下,进行Unity Package本地链接的完整流程、核心配置、高级技巧以及那些官方文档里不会写的“坑”。我们的目标很简单:让你能像开发普通Unity脚本一样,流畅地开发ET插件。

2. 核心原理:ET Package与本地链接的本质

在深入实操之前,我们必须先理解两个核心概念:ET Package的构成和本地链接的工作原理。这能帮你从根本上避开配置错误。

2.1 ET Package的“基因”:它不只是个文件夹

一个标准的ET Package,远不止是几个C#脚本的集合。它是一个严格遵循ET框架模块化与热更新设计理念的完整单元。

首先,从命名上就有严格规范。ET Package采用类似Java包名的反向域名格式:cn.etetet.+ 你的包名。例如,你开发一个任务系统插件,包名可能就是cn.etetet.quest。这种命名确保了在全球范围内的唯一性,避免了与Unity官方或其他第三方包冲突。

其次,它的目录结构是功能导向的。一个典型的ET Package核心目录如下:

cn.etetet.yourpackage/ ├── package.json // 包的元数据与依赖声明 ├── packagegit.json // **ET特有**,用于管理Git依赖和代码引用 ├── Runtime/ // 存放AOT(预先编译)代码,如核心系统接口、数据结构 │ └── ET.YourPackage.asmdef ├── Scripts/ // **核心区域**,存放热更新相关代码 │ ├── Model/ // 服务端模型层代码(双端均可执行) │ ├── Hotfix/ // 客户端热更新层代码(仅客户端热更) │ ├── ModelView/ // 客户端模型层代码(视图相关,双端) │ └── HotfixView/ // 客户端热更新视图层代码(仅客户端热更) │ ├── Client/ // 纯客户端代码 │ ├── Server/ // 纯服务端代码 │ └── Share/ // 客户端与服务端共享代码 ├── Editor/ // 编辑器扩展脚本 │ └── ET.YourPackage.Editor.asmdef └── Tests/ // 单元测试(可选)

关键在于Scripts目录下的划分,这直接对应了ET框架的ModelHotfixModelViewHotfixView四大程序集。本地链接时,Unity和ET的工具链需要正确识别这些目录,并将代码关联到正确的程序集。

2.2 本地链接的“魔法”:file协议与符号链接

当我们说“本地链接”时,在Unity的语境下,主要指的是在项目的Packages/manifest.json文件中,使用file:协议来声明对一个本地路径的依赖。

{ "dependencies": { "com.unity.collab-proxy": "2.0.4", "cn.etetet.core": "file:../../../ET-Packages/cn.etetet.core", "cn.etetet.yourplugin": "file:../MyETPlugins/yourplugin" } }

这行配置告诉Unity Package Manager (UPM):”别去Registry服务器上找cn.etetet.yourplugin这个包,直接去我本地../MyETPlugins/yourplugin这个文件夹里读取。“

在这个过程中,Unity实际上会在项目的Library/PackageCache目录下,为该包创建一个符号链接(Symbolic Link)或直接引用。这意味着,你在本地Package目录下的任何修改(添加、删除、修改脚本),都会实时反映到主项目中,触发Unity的重新编译。这才是实现高效迭代的核心。

注意file:后面的路径是相对于manifest.json文件所在位置(即项目根目录下的Packages文件夹)的路径。使用相对路径比绝对路径更安全,便于团队协作和项目迁移。

3. 实战第一步:搭建你的本地ET Package开发环境

理论懂了,现在开始动手。假设我们要为一个ET项目开发一个名为cn.etetet.achievement的成就系统插件。

3.1 创建标准的ET Package目录骨架

首先,在你喜欢的位置(比如与你的ET主项目同级目录)创建插件开发文件夹。

  1. 创建根文件夹ET-AchievementPlugin
  2. 创建Package核心文件夹:在ET-AchievementPlugin内,创建cn.etetet.achievement文件夹。这个文件夹的名字必须与将来在manifest.json中声明的包名完全一致。
  3. 填充标准目录:在cn.etetet.achievement内,创建RuntimeScriptsEditor目录,并在Scripts下创建ModelHotfixModelViewHotfixView及其子目录ClientServerShare

你的初始结构应该像这样:

ET-AchievementPlugin/ └── cn.etetet.achievement/ ├── Runtime/ ├── Scripts/ │ ├── Model/ │ ├── Hotfix/ │ ├── ModelView/ │ └── HotfixView/ │ ├── Client/ │ ├── Server/ │ └── Share/ └── Editor/

3.2 编写核心配置文件:package.json与packagegit.json

这是最容易出错,也是最关键的一步。两个文件各司其职。

1. package.json:定义包的元数据和UPM依赖cn.etetet.achievement根目录创建package.json

{ "name": "cn.etetet.achievement", "displayName": "ET Achievement System", "version": "1.0.0", "unity": "2022.3", "description": "A complete achievement system plugin for ET Framework.", "dependencies": { "cn.etetet.core": "file:../../../ET-Packages/cn.etetet.core" }, "publishConfig": { "registry": "https://npm.pkg.github.com/@ET-Packages" } }
  • name:必须与文件夹名完全一致。
  • dependencies:声明此插件依赖的其他ET包。这里使用file:协议链接到本地的cn.etetet.core包。请务必根据你的实际路径调整
  • publishConfig:这是为将来发布到GitHub Packages准备的,在本地开发阶段不影响使用,但最好保持一致。

2. packagegit.json:ET框架的“灵魂”配置文件这是ET框架特有的文件,用于管理代码到特定程序集的引用关系。在cn.etetet.achievement根目录创建packagegit.json

{ "Id": "cn.etetet.achievement", "Name": "成就系统", "GitDependencies": { "cn.etetet.core": "https://github.com/ET-Packages/cn.etetet.core.git" } }
  • Id:包的标识,通常与name相同。
  • GitDependencies:这里定义的Git依赖,在运行ET的Refresh命令时,会被用来建立代码引用。注意:本地开发时,即使你通过file:链接了本地包,这里最好也填写该包的Git仓库地址(如果存在),以保证工具链能正确理解依赖关系。

3.3 创建程序集定义文件(.asmdef)

为了让Unity正确编译和隔离代码,每个需要独立编译的模块都需要一个.asmdef文件。

  1. Runtime程序集:在Runtime/文件夹内,右键创建Assembly Definition,命名为ET.Achievement。这个程序集将包含你的成就系统核心接口、数据结构和AOT代码。
  2. Editor程序集:在Editor/文件夹内,创建Assembly Definition,命名为ET.Achievement.Editor。在它的Inspector面板中,在Assembly Definition References里添加对ET.Achievement的引用,并在Platforms中取消勾选Any Platform,只保留Editor。这确保了编辑器代码只在Unity编辑器中运行。
  3. Scripts下的“占位”程序集:在Scripts/文件夹内,创建一个名为Ignore.asmdef文件。这是一个ET框架的惯例,目的是让该Package默认不被包含到任何程序集中,防止代码错误引用。真正的引用关系由packagegit.json和ET的Refresh命令来动态管理。

4. 实现本地链接:将你的插件“挂载”到主项目

环境搭建好了,现在要把这个正在开发的插件链接到你的ET游戏主项目中。

4.1 修改主项目的manifest.json

打开你的ET游戏主项目,找到Packages/manifest.json文件。在dependencies区块中,添加你的本地包路径。

{ "dependencies": { "cn.etetet.core": "file:../../ET-Packages/cn.etetet.core", "cn.etetet.hotfix": "file:../../ET-Packages/cn.etetet.hotfix", "cn.etetet.achievement": "file:../../ET-AchievementPlugin/cn.etetet.achievement", "com.unity.textmeshpro": "3.0.6" } }

保存manifest.json文件。切换回Unity编辑器,Unity会自动检测到manifest.json的变更,并开始导入新添加的本地包。你可以在Package Manager窗口中,切换到“My Registries”或“In Project”视图,看到你的cn.etetet.achievement包,其来源会显示为Local

4.2 关键一步:配置Unity外部工具

很多开发者链接成功后,发现IDE(如Rider、VS)无法识别新包里的类,无法跳转和自动补全。问题往往出在这里。

进入Edit -> Preferences -> External Tools。 在Generate .csproj files for:选项下,确保Local packages被勾选。 这个设置告诉Unity,在为IDE生成解决方案(.sln)和项目文件(.csproj)时,需要将本地链接的包也包含进去。如果不勾选,IDE就“看不见”你的本地包代码。

实操心得:修改此设置后,通常需要手动触发一次项目文件生成。可以关闭Unity,删除项目根目录下的*.sln文件和所有*.csproj文件,然后重新打开Unity,它会自动重新生成包含本地包在内的所有项目文件。或者在Unity中点击Assets -> Open C# Project强制刷新。

4.3 运行ET工具链命令,建立代码引用

本地包被成功链接并导入后,你的成就系统代码还处于“孤立”状态,没有被关联到ET框架的ModelHotfix等核心程序集中。

  1. 在Unity编辑器中,找到ET框架的菜单栏ET -> Refresh。点击运行。
  2. 这个命令会读取所有包(包括本地链接的包)中的packagegit.json文件,分析依赖关系,并将Scripts目录下的代码,自动关联到你的主项目Demo中对应的ModelHotfixModelViewHotfixView这四个程序集定义(.asmdef)上。

完成这一步后,你的AchievementComponent或其他脚本,才能被ET的实体系统正确识别和调用。

5. 高级技巧与深度避坑指南

基本的链接跑通了,但想用得顺手,还得掌握下面这些进阶技巧和避坑方法。

5.1 处理“INITED”宏与Demo包初始化

如果你开发的插件包含Demo示例代码(通常放在Scripts/Demo目录),你会遇到一个特殊问题:这些Demo代码在项目初次打开或包初次下载时,可能会因为依赖的程序集尚未准备好而编译报错。

ET框架的解决方案是使用INITED条件编译宏。

  1. 找到主项目中ModelHotfixModelViewHotfixView这四个核心.asmdef文件。
  2. 在它们的Scripting Define Symbols中,添加INITED宏。
  3. 在你的Demo代码中,将所有类用#if INITED#endif包裹起来。
#if INITED namespace ET.Achievement.Demo { public class AchievementDemoSystem { // 你的演示代码 } } #endif

这样,只有当你通过ET -> Init菜单初始化项目后,INITED宏才会被定义,Demo代码才会被编译。避免了初始状态下的编译错误。

5.2 多包依赖与循环引用陷阱

你的成就系统插件cn.etetet.achievement可能依赖于另一个本地开发的cn.etetet.analytics(数据分析)插件。

  1. achievementpackage.json中声明依赖
    "dependencies": { "cn.etetet.core": "file:../../../ET-Packages/cn.etetet.core", "cn.etetet.analytics": "file:../../ET-AnalyticsPlugin/cn.etetet.analytics" }
  2. achievementpackagegit.json中也声明Git依赖(指向analytics的Git仓库)。
  3. 在主项目的manifest.json中,需要同时链接这两个包

避坑提示:循环引用。绝对禁止包A依赖包B,同时包B又依赖包A。这会导致Unity依赖解析失败,编译错误。设计模块时,要确保依赖关系是单向的、有层次的。公共基础功能应下沉到更底层的包(如core)。

5.3 本地调试与热更新联调

本地链接最大的优势就是联调。

  • 实时修改:在achievement包的Hotfix/Client目录下修改一个处理成就弹出的UI系统。保存后,Unity主项目几乎立刻开始重新编译包含这部分改动的程序集。
  • 断点调试:由于本地包被包含在IDE的项目文件中,你可以在achievement的代码里直接下断点。在Unity中运行游戏,触发成就逻辑,IDE会正常命中断点,和调试项目内代码毫无二致。
  • 热更新测试:ET框架的热更新机制依赖于将HotfixHotfixView程序集动态加载到游戏里。当你修改了这些程序集里的代码并编译后,可以通过ET的热更新流程(如使用ILRuntimeHybridCLR)直接加载新的DLL,在不停服的情况下测试插件功能。本地链接让“编码-编译-热更测试”这个循环变得极其快速。

5.4 版本管理与团队协作策略

本地链接用的是file:协议,路径是写死的。这在单人开发时没问题,但在团队中,每个人的项目路径可能不同。

解决方案:使用file:协议配合相对路径的公约,或创建符号链接。

  1. 公约法:团队约定,将所有本地开发的ET包都放在一个与主项目同级(或固定相对位置)的LocalPackages目录中。这样每个人的manifest.json都可以使用相同的相对路径(如file:../../LocalPackages/cn.etetet.achievement)。
  2. 符号链接法(更灵活):在项目的Packages目录下,为你开发的包创建一个符号链接。
    • Windows (CMD管理员):
      mklink /J "cn.etetet.achievement" "D:\YourPath\ET-AchievementPlugin\cn.etetet.achievement"
    • macOS/Linux:
      ln -s /path/to/your/ET-AchievementPlugin/cn.etetet.achievement ./Packages/cn.etetet.achievement
    然后在manifest.json中,就可以使用file:协议指向这个符号链接,或者甚至可以直接使用包名(如果UPM能识别符号链接)。这种方法路径更简洁。

6. 从本地开发到正式发布的工作流

本地开发测试完成后,你需要将插件发布出去供其他项目使用。ET框架的包通常发布到GitHub Packages。

6.1 准备发布配置

确保你的package.json中的publishConfig.registry指向正确的地址(如ET官方的是https://npm.pkg.github.com/@ET-Packages)。你需要在本地配置npm或yarn的认证,以便有权限发布到该私有仓库。

6.2 使用GitHub Actions自动化发布

ET-Packages仓库提供了标准的发布工作流模板。这是最高效的方式。

  1. 在你的插件包仓库根目录,创建.github/workflows/release-package.yml文件。
  2. 内容可以直接从已有的ET包(如cn.etetet.yiui)中复制。
  3. 这个工作流通常会在你向仓库打上版本标签(如v1.0.0)时自动触发。它会运行npm pack打包,然后将生成的.tgz文件发布到配置的GitHub Packages Registry。

6.3 更新主项目依赖

发布成功后,其他项目就可以通过Git URL或配置Scoped Registry来引用你发布的包了。你需要将主项目manifest.json中的依赖从本地链接改为版本号或Git引用。

// 从本地链接 "cn.etetet.achievement": "file:../../ET-AchievementPlugin/cn.etetet.achievement" // 改为发布后的版本引用(需配置Scoped Registry) "cn.etetet.achievement": "1.0.0" // 或直接使用Git URL(特定commit或tag) "cn.etetet.achievement": "https://github.com/YourName/cn.etetet.achievement.git#v1.0.0"

7. 常见问题排查与解决方案实录

即使按照指南操作,也难免会遇到问题。这里记录了几个最常见的问题和解决方法。

问题1:Unity Package Manager里看不到我的本地包,或者显示为灰色。

  • 检查manifest.json中的file:路径是否正确。路径是相对于Packages文件夹的。
  • 检查:本地包根目录是否有正确且有效的package.json文件。name字段必须与文件夹名匹配。
  • 解决:尝试关闭Unity,删除项目下的LibraryPackages文件夹(manifest.json保留),然后重新打开Unity。这会强制UPM重新解析所有依赖。

问题2:IDE(Rider/VS)无法识别本地包中的类,没有代码提示和跳转。

  • 检查Edit -> Preferences -> External Tools中,Local packages是否已勾选。
  • 检查:是否在修改设置后,重新生成了项目文件(删除.sln和.csproj后重启Unity)。
  • 解决:在IDE中,尝试“重新加载项目”或“清理解决方案”。有时IDE的缓存会导致问题。

问题3:运行ET -> Refresh后,我的插件代码没有被关联到程序集。

  • 检查packagegit.json文件格式是否正确,IdGitDependencies是否填写无误。
  • 检查:插件包的Scripts目录结构是否符合ET规范(Model, Hotfix等子目录)。
  • 解决:查看Unity Console是否有相关错误日志。确保主项目的几个核心程序集(Model, Hotfix等)存在且名称正确。

问题4:编译错误,提示找不到依赖的包中的类型。

  • 检查:依赖包的.asmdef文件是否已经正确创建,并且其程序集名称是否被正确引用。
  • 检查:在依赖包的.asmdef设置中,是否在Assembly Definition References里添加了被依赖的程序集。
  • 解决:确保所有相关包都已成功链接并导入。有时需要手动点击Package Manager中对应包的“Update”或“Reinstall”。

掌握Unity Package的本地链接,本质上是掌握了ET框架插件开发的“呼吸节奏”。它让开发过程从笨重的“批处理”变成了轻盈的“实时交互”。当你能够随心所欲地在本地编写、调试、验证你的ET插件,并丝滑地将其集成到主项目甚至发布到团队仓库时,你才能真正体会到模块化开发带来的自由与高效。这套流程初期配置略显繁琐,但一旦跑通,它将为你的后续开发节省海量时间。记住,关键点在于路径配置、packagegit.json的理解,以及ET工具链命令的恰当使用。多踩几次坑,这些配置就会变成你的肌肉记忆。

http://www.jsqmd.com/news/1351074/

相关文章:

  • 零基础构建AI自动化图文生产线:Coze与Image2工作流实战
  • Unity触发器实现摄像机广角与防缩进视角控制教程
  • 广州本地防水补漏哪家专业?屋顶、卫生间、外墙、地下室、阳台漏水师傅测评(2026年8月新) - 金信达
  • 重庆本地防水补漏怎么选?屋顶卫生间外墙地下室阳台渗水检测大盘点(2026年8月新) - 金信达
  • 自我改进型RLM代理实战:从强化学习原理到工程落地全解析
  • Nacos 2.5.2与KingBase国产化适配实践
  • 游戏平衡性分析实战:从数据抓取到模拟对战的技术方法
  • 电子元器件封装知识大全:从基础概念到AD实战设计指南
  • AI Agent安全架构:从提示词注入到纵深防御的实战指南
  • 从零到一:使用Phaser 3框架开发微信小游戏全流程指南
  • 跨浏览器书签同步:本地化工具实现Safari与Chrome数据互通
  • COMSOL模拟BIC涡旋激光器的超快控制技术
  • 成都漏水点检测怎么选?2026年双流专业检测漏水服务指南 - 优质品牌商家
  • 武汉市卫生间墙砖空鼓维修_2026长江中游瓷砖空鼓维修攻略与电话 - 雨婺虹修缮
  • 北京本地防水补漏如何挑选?屋顶/卫生间/外墙/地下室/阳台漏水检修实测(2026年8月新) - 金信达
  • Linux服务器文件下载实战:SCP、Rsync与SFTP命令详解与应用场景
  • 2026软文发稿平台哪家好?行业汇总指引及优选推荐
  • 虚幻引擎C++实现时间轴移动:从蓝图TimeLine到自定义组件进阶
  • Altium Designer规则失效?PCB线宽过孔不匹配的排查与解决
  • 2026年考公报名照片怎么改成 295413 像素?亲测可用教程 - 效率工具研究所
  • 用Python做自动化脚本:给日常工作按个快进键
  • Python代码优化入门:让程序运行更快
  • 从零部署智能QQ机器人:整合Astrbot、Napcat与大模型API
  • RAG系统构建:从知识架构设计到智能切片与检索策略
  • 2026年四川自考助学与成人学历提升机构怎么选?基于区域服务能力的多维观察 - 优质品牌商家
  • AI辅助Python爬虫实战:天眼查数据采集入门
  • AI驱动游戏设计:用Fable打造梵高风格城市建造游戏
  • 2026年营业执照照片怎么加水印?亲测好用的免费方法分享 - 图片处理研究员
  • 从零到一:手把手教你用Coze平台开发AI智能体应用
  • QLabel自动换行:原理、布局协同与实战场景解析