Unity之一键创建自定义Package包

内容将会持续更新,有错误的地方欢迎指正,谢谢!
 

Unity之一键创建自定义Package包
     
TechX 坚持将创新的科技带给世界!

拥有更好的学习体验 —— 不断努力,不断进步,不断探索
TechX —— 心探索、心进取!

助力快速掌握 自定义Package 快速创建

为初学者节省宝贵的学习时间,避免困惑!


前言:

  在之前的文章从零开始创建Unity自定义包Package:一步一步实现您的功能,我已经详细的介绍了该如何一步一步的去创建自己的自定义Package包,但是我相信有的小伙伴还是觉得文章很长不想看,或者觉得创建一个自定义包很麻烦,又要创建包,又要导入包的。

  今天小伙伴们可以轻松的去做这件事了,你可以直接一键的去生成包和导入包到Unity,真正的做到了省心、省时、省力,接下来就让我们一起来看怎么实现的吧。

TechX 教程效果:

在这里插入图片描述


文章目录

  • 一、绘制package创建器面板
  • 二、创建包
    • 1、创建文件夹和Assembly Definition
    • 2、创建包清单文件 (package.json)
    • 3、创建CHANGELOG.md
    • 4、创建README.md
  • 三、安装包
  • 四、项目地址


一、绘制package创建器面板


创建器面板的绘制基本上是package.json文件中的内容,包含大多数的包清单中的内容,包含:包名,包版本,包展示名,包描述,Unity版本,Unity发布版本号,文档地址,改变日志地址,证书地址,依赖列表,关键词列表,作者信息,案例列表等。

其中还包含了创建包时的选项,包含是否创建Scripts文件夹,是否创建Tests文件夹,是否创建CHANGELOG文件,是否创建ReadMe文件。

public class PackageCreatorWindow : EditorWindow
{private bool isCreteScriptsFolder = true;private bool isCreteTestsFolder = false;private bool isCreateChangeLog = true;private bool isCreateReadme = true;private string packageName = "";private string version = "";private string displayName = "";private string description = "";private string unity = "";private string unityRelease = "";private string documentationUrl = "";private string changelogUrl = "";private string licensesUrl = "";private List<Dependency> dependencies = new List<Dependency>();private List<string> keywords = new List<string>();private Author author = new Author();private List<Sample> samples = new List<Sample>();private ReorderableList keywordsReorderableList;private ReorderableList samplesReorderableList;private ReorderableList dependenciesReorderableList;private void OnGUI(){DrawGUI();}private void DrawGUI(){GUILayout.Space(5f);GUILayout.Label("Package Config", new GUIStyle { fontSize = 20, padding = new RectOffset() { left = 5 }, fontStyle = FontStyle.Bold, normal = { textColor = Color.white } }); ;GUILayout.Space(5f);scrollPos = EditorGUILayout.BeginScrollView(scrollPos,EditorStyles.helpBox);isCreteScriptsFolder = EditorGUILayout.ToggleLeft("Is Crete Scripts Folder", isCreteScriptsFolder);isCreteTestsFolder = EditorGUILayout.ToggleLeft("Is Crete Tests Folder", isCreteTestsFolder);isCreateChangeLog = EditorGUILayout.ToggleLeft("Is Create ChangeLog File", isCreateChangeLog);isCreateReadme = EditorGUILayout.ToggleLeft("Is Create ReadMe File", isCreateReadme);packageName = EditorGUILayout.TextField("Package Name *", packageName);version = EditorGUILayout.TextField("Version *", version);displayName = EditorGUILayout.TextField("Display Name *", displayName);description = EditorGUILayout.TextArea(description, GUILayout.Height(50));unity = EditorGUILayout.TextField("Unity Version *", unity);unityRelease = EditorGUILayout.TextField("Unity Release *", unityRelease);documentationUrl = EditorGUILayout.TextField("Documentation URL", documentationUrl);changelogUrl = EditorGUILayout.TextField("Changelog URL", changelogUrl);licensesUrl = EditorGUILayout.TextField("Licenses URL", licensesUrl);dependenciesReorderableList.DoLayoutList();keywordsReorderableList.DoLayoutList();autorToogleGroup = EditorGUILayout.BeginFoldoutHeaderGroup(autorToogleGroup, "Author");if (autorToogleGroup){EditorGUI.indentLevel += 1;author.name = EditorGUILayout.TextField("Name", author.name);author.email = EditorGUILayout.TextField("Email", author.email);author.url = EditorGUILayout.TextField("Url", author.url);EditorGUI.indentLevel -= 1;}EditorGUILayout.EndFoldoutHeaderGroup();samplesReorderableList.DoLayoutList();EditorGUILayout.EndScrollView();//创建之前要验证面板信息if (GUILayout.Button("Create Package")){string selectPath = EditorUtility.OpenFolderPanel("Select Folder for New Package", "", "");bool isSuccess = CreateNewPackage(selectPath, packageName, out string packagePath);if (isSuccess == false) return;InstallPackage(selectPath, packagePath);}}
}


二、创建包


1、创建文件夹和Assembly Definition


为创建的包创建一些需要的文件夹,比如Scripts/Editor、Scripts/Runtime、Tests/Editor、Tests/Runtime文件夹。
Scripts/Editor文件夹包含编辑器使用的功能,放置的脚本只在编辑器环境中使用。
Scripts/Runtime文件夹包含游戏运行时使用的功能,放置的脚本将在游戏运行时执行。
Tests/Editor用于编辑器测试,Tests/Runtime用于运行时测试。

/// <summary>
/// 创建包文件夹
/// </summary>
private void CreatePackageFolder(string pacakgePath, string packageName)
{//TODO 创建Scripts文件夹。。。。string scriptsFolderPath = Path.Combine(pacakgePath, "Scripts");Directory.CreateDirectory(scriptsFolderPath);//创建Editor和Runtime文件夹string editorFolderPath = Path.Combine(scriptsFolderPath, "Editor");string runtimeFolderPath = Path.Combine(scriptsFolderPath, "Runtime");Directory.CreateDirectory(editorFolderPath);Directory.CreateDirectory(runtimeFolderPath);// Create .asmdef files//这里的asmdef的文件的包名是否首字母大写??string editorAsmdefPath = Path.Combine(editorFolderPath, $"{packageName}.Editor.asmdef");string runtimeAsmdefPath = Path.Combine(runtimeFolderPath, $"{packageName}.Runtime.asmdef");AsmdefConfigProcess.CreateAsmdefContent(editorAsmdefPath, true);AsmdefConfigProcess.CreateAsmdefContent(runtimeAsmdefPath, false);//TODO 创建Tests文件夹。。。。string testsFolderPath = Path.Combine(pacakgePath, "Tests");Directory.CreateDirectory(testsFolderPath);string testseEditorFolderPath = Path.Combine(testsFolderPath, "Editor");string testseRuntimeFolderPath = Path.Combine(testsFolderPath, "Runtime");Directory.CreateDirectory(testseEditorFolderPath);Directory.CreateDirectory(testseRuntimeFolderPath);string testseEditorAsmdefPath = Path.Combine(testseEditorFolderPath, $"{packageName}.Editor.Tests.asmdef");string testseRuntimeAsmdefPath = Path.Combine(testseRuntimeFolderPath, $"{packageName}.Runtime.Tests.asmdef");AsmdefConfigProcess.CreateAsmdefContent(testseEditorAsmdefPath, true);AsmdefConfigProcess.CreateAsmdefContent(testseRuntimeAsmdefPath, false);
}

在每个文件夹创建完成之后,我们都需要在文件夹中定义一个程序集文件,注意在不同的文件夹中,程序集文件的名称是不一样的,同时也要注意,对于运行时和编辑器下的程序集平台也是不一样的,运行时的平台一般是Any Platform,而编辑器的平台是Editor。

public class AsmdefConfig
{public string name;public string rootNamespace;public List<string> references;public List<string> includePlatforms;public List<string> excludePlatforms;public bool allowUnsafeCode;public bool overrideReferences;public List<string> precompiledReferences;public bool autoReferenced;public List<string> defineConstraints;public List<string> versionDefines;public bool noEngineReferences;
}public class AsmdefConfigProcess
{/// <summary>/// 创建.asmdef/// </summary>/// <param name="path">创建的位置</param>/// <param name="isEditor">适用于运行时还是编辑器下</param>public static void CreateAsmdefContent(string filePath, bool isEditor){string fileName = Path.GetFileNameWithoutExtension(filePath) ;AsmdefConfig asmdefClass = new AsmdefConfig();asmdefClass.name = fileName;asmdefClass.rootNamespace = "";asmdefClass.references = new List<string>();asmdefClass.includePlatforms = isEditor ? new List<string> { "Editor" } : new List<string>();asmdefClass.excludePlatforms = new List<string>();asmdefClass.allowUnsafeCode = false;asmdefClass.overrideReferences = false;asmdefClass.precompiledReferences = new List<string>();asmdefClass.autoReferenced = true;asmdefClass.defineConstraints = new List<string>();asmdefClass.versionDefines = new List<string>();asmdefClass.noEngineReferences = false;JObject asmdefJson = JObject.FromObject(asmdefClass);File.WriteAllText(filePath, asmdefJson.ToString());}
}

2、创建包清单文件 (package.json)


每个Unity Package都必须包含一个名为package.json的清单文件。这个文件包含了有关包的元信息,如名称、版本、依赖项等。

/// <summary>
/// 创建package.json文件
/// </summary>
private void CreatePackageFile(string pacakgePath)
{// Create package.jsonPackageConfigProcess.CreatePackageJson(pacakgePath, GetPackageJsonContent());
}

这里定义了包清单的一些相关类型,当需要创建package.json文件时,从面板上获取到包相关信息,并生成PackageConfig实例,将该实例转换成JSON字符串写入到json文件中。

[System.Serializable]
public class Author
{public string name = "";public string email = "";public string url = "";
}[System.Serializable]
public class Dependency
{ public string packageName;public string version;
}[System.Serializable]
public class Sample
{public string displayName;public string description;public string path;
}public class PackageConfig
{public string name = "";public string version = "";public string displayName = "";public string description = "";public string unity = "";public string unityRelease = "";public string documentationUrl = "";public string changelogUrl = "";public string licensesUrl = "";public JObject dependencies = new JObject();public List<string> keywords = new List<string>();public Author author = new Author();public List<Sample> samples = new List<Sample>();
}public class PackageConfigProcess
{public static void CreatePackageJson(string path, PackageConfig packageConfig){JObject packageConfigJson = JObject.FromObject(packageConfig);string fullPath = Path.Combine(path, $"package.json");File.WriteAllText(fullPath, packageConfigJson.ToString());}
}

3、创建CHANGELOG.md


CHANGELOG.md文件是版本信息改变的日志文件,建议在每次发布新版本时更新CHANGELOG.md文件。在文件中记录新增功能、改进和错误修复。

/// <summary>
/// 创建CHANGELOG.md文件
/// </summary>
private void CreateChangeLogFile(string pacakgePath)
{// Create CHANGELOG.mdstring changeLogPath = Path.Combine(pacakgePath, "CHANGELOG.md");File.WriteAllText(changeLogPath, "# Changelog\nAll notable changes to this package will be documented in this file.\n\n");
}

4、创建README.md


README.md文件是关于该插件的介绍和如何使用的。

/// <summary>
/// 创建README.md文件
/// </summary>
private void CreateReadMeFile(string pacakgePath)
{// Create README.mdstring readmePath = Path.Combine(pacakgePath, "README.md");File.WriteAllText(readmePath, $"# {Path.GetFileName(pacakgePath)}\n\n");
}


三、安装包


在包创建完成后,会把包创建到本地的某个文件夹中,但是这个时候并没有把包安装到Unity中,按照一般的方法,在创建完成包后,可以通过Package Manager中的Add package form disk选项去文件夹中选择包的package.json文件来安装本地包。

但是在这里我们在创建完成包后,直接根据包的路径来,直接使用代码来模拟Add package form disk选择package.json文件来安装包。

注意:当我们把包直接创建到工程的Packages文件中时,那么我们就不需要通过代码来添加包到工程中,因为Unity会自动完成这一步。

/// <summary>
/// 安装包
/// </summary>
/// <param name="creteResult"></param>
/// <param name="selectPath"></param>
/// <param name="packagePath"></param>
private void InstallPackage(string selectPath, string packagePath)
{//如果直接创建到了Packages文件加中,那么就不需要手动添加到工程中,Unity会自动添加if (File.Exists(Path.Combine(selectPath, "manifest.json"))) return;//TODO 添加包到工程中PackageInstaller.InstallPackageFromDisk(packagePath);
}

从本地安装包的方式有两种,一种是从文件夹安装,要求包含package.json文件,并且符合包清单的条件,一种是通过.tgz压缩包的方式安装包。

这两种包在安装时都需要在路径前"file:"才能正确的安装包。

public class PackageInstaller
{/// <summary>/// 从本地路径安装包/// 1、可以通过本地文件夹安装包,格式file:pathtopackagefolder,如file:E:/UPMProject/UPM/com.fxb.test/// 2、从.tgz文件安装包,格式file:pathtopackage.tgz,如file:E:/UPMProject/UPM/com.fxb.test.tgz/// </summary>/// <param name="packagePath"></param>public static void InstallPackageFromDisk(string packagePath){//从本地文件夹安装包if (Directory.Exists(packagePath)){// 构造package.json文件的完整路径string packageJsonPath = Path.Combine(packagePath, "package.json");// 检查package.json文件是否存在if (!File.Exists(packageJsonPath)){Debug.LogError("The provided folder does not contain a valid 'package.json' file and is not a valid Unity package.");return;}}//从.tgz文件安装包else if (File.Exists(packagePath)){if (!packagePath.EndsWith(".tgz")){Debug.LogError($"{packagePath} file is not a valid Unity package.");return;}}else{Debug.LogError($"The package at path {packagePath} does not exist.");return;}// 构建正确的标识符string identifier = $"file:{packagePath}";// 如果存在package.json,那么这是一个有效的包,可以继续安装AddRequest request = Client.Add(identifier);CallbackFunction onAddUpdate = null;onAddUpdate = () =>{if (request.IsCompleted){if (request.Status == StatusCode.Success)Debug.Log($"Package from {packagePath} installed successfully.");elseDebug.LogError($"Failed to install package from {packagePath}: {request.Error.message}");// 移除更新回调EditorApplication.update -= onAddUpdate;}};// 注册更新事件EditorApplication.update += onAddUpdate;}
}


四、项目地址


以下是项目地址,已经整理成了Package包,有需要的小伙伴门可以自取:

https://gitcode.com/CTLittleNewbie/com.fxb.unitypackagecreator_v1.0.0/overview





TechX —— 心探索、心进取!

每一次跌倒都是一次成长

每一次努力都是一次进步


END
感谢您阅读本篇博客!希望这篇内容对您有所帮助。如果您有任何问题或意见,或者想要了解更多关于本主题的信息,欢迎在评论区留言与我交流。我会非常乐意与大家讨论和分享更多有趣的内容。
如果您喜欢本博客,请点赞和分享给更多的朋友,让更多人受益。同时,您也可以关注我的博客,以便及时获取最新的更新和文章。
在未来的写作中,我将继续努力,分享更多有趣、实用的内容。再次感谢大家的支持和鼓励,期待与您在下一篇博客再见!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/62344.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python的Flask框架使用

python的Flask框架使用 python环境搭建conda安装python自带的虚拟环境&#xff1a;venv python环境搭建 官网地址 点击downloads 选择你需要的版本&#xff0c;我这里使用的3.12.6 选择Windows installer (64-bit) 选择自定义安装&#xff0c;勾选以管理员权限安装&#xff0…

网络原理(一)—— http

什么是 http http 是一个应用层协议&#xff0c;全称为“超文本传输协议”。 http 自 1991 年诞生&#xff0c;目前已经发展为最主流使用的一种应用层协议。 HTTP 往往基于传输层的 TCP 协议实现的&#xff0c;例如 http1.0&#xff0c;http1.0&#xff0c;http2.0 http3 是…

103.【C语言】数据结构之建堆的时间复杂度分析

1.向下调整的时间复杂度 推导 设树高为h 发现如下规律 按最坏的情况考虑(即调整次数最多) 第1层,有个节点,最多向上调整h-1次 第2层,有个节点,最多向上调整h-2次 第3层,有个节点,最多向上调整h-3次 第4层,有个节点,最多向上调整h-4次 ... 第h-1层,有个节点,最多向上调整1次 第…

用Python爬虫“偷窥”1688商品详情:一场数据的奇妙冒险

引言&#xff1a;数据的宝藏 在这个信息爆炸的时代&#xff0c;数据就像是一座座等待挖掘的宝藏。而对于我们这些电商界的探险家来说&#xff0c;1688上的商品详情就是那些闪闪发光的金子。今天&#xff0c;我们将化身为数据的海盗&#xff0c;用Python这把锋利的剑&#xff0…

Python基础学习-12匿名函数lambda和map、filter

目录 1、匿名函数&#xff1a; lambda 2、Lambda的参数类型 3、map、 filter 4、本节总结 1、匿名函数&#xff1a; lambda 1&#xff09;语法&#xff1a; lambda arg1, arg2, …, argN : expression using arg 2&#xff09; lambda是一个表达式&#xff0c;而不是一个语…

【JavaEE初阶 — 网络编程】TCP流套接字编程

TCP流套接字编程 1. TCP &#xff06; UDP 的区别 TCP 的核心特点是面向字节流&#xff0c;读写数据的基本单位是字节 byte 2 API介绍 2.1 ServerSocket 定义 ServerSocket 是创建 TCP 服务端 Socket 的API。 构造方法 方法签名 方法说明 ServerS…

idea新建springboot web项目

idea新建springboot web项目 写在前面开始项目结构定义依赖初始化创建完成修复配置文件内容乱码修改配置文件名称更新配置文件内容为yml格式 配置项目启动项启动项目 写在前面 以下操作以IntelliJ IDEA 2022.3.3版本为例&#xff0c;其他版本应该大体相似。 开始 项目结构定义…

Docker 容器网络创建网桥链接

一、网络:默认情况下,所有的容器都以bridge方式链接到docker的一个虚拟网桥上; 注意:“172.17.0.0/16”中的“/16”表示子网掩码的长度为16位,它表示子网掩码中有16个连续的1,后面跟着16个连续的0。用于区分IP地址中的网络部分和主机部分; 二、为何自定义网络? 加入自…

智能产品综合开发 - 温湿度检测

1 实训选题目的 本次实训选择的题目是“温湿度检测系统”&#xff0c;旨在提升我们对日常生活中实际应用场景的观察力、问题描述能力、分析力和产品设计能力。通过本项目&#xff0c;我们将能够将所学的人工智能专业知识进行综合应用&#xff0c;包括但不限于Linux操作系统、Py…

人工智能如何改变你的生活?

在我们所处的这个快节奏的世界里&#xff0c;科技融入日常生活已然成为司空见惯的事&#xff0c;并且切实成为了我们生活的一部分。在这场科技变革中&#xff0c;最具变革性的角色之一便是人工智能&#xff08;AI&#xff09;。从我们清晨醒来直至夜晚入睡&#xff0c;人工智能…

vue3 ajax获取json数组排序举例

使用axios获取接口数据 可以在代码中安装axios包&#xff0c;并写入到package.json文件&#xff1a; npm install axios -S接口调用代码举例如下&#xff1a; const fetchScore async () > {try {const res await axios.get(http://127.0.0.1:8000/score/${userInput.v…

Vue前端开发-动态插槽

不仅父组件可以通过插槽方式访问并控制子组件传入的数据&#xff0c;而且可以控制传入父组件时插槽的名称&#xff0c;从而使不同的插槽根据名称的不同&#xff0c;使用场景也不同&#xff0c;例如在一个小区详细页中&#xff0c;可以根据小区类型&#xff0c;调用不同名称的详…

SqlServer强制转换函数TRY_CONVERT和TRY_CAST

SqlServer强制转换函数TRY_CONVERT和TRY_CAST的介绍和案例分享 1、本节内容 CAST 和 CONVERT TRY_CAST TRY_CONVERT 适用于&#xff1a; SQL ServerAzure SQL 数据库Azure SQL 托管实例Azure Synapse Analytics 分析平台系统 (PDW)Microsoft Fabric 中的 SQL 分析端点Micro…

PaddleOCR:一款高性能的OCR工具介绍

一、引言 随着人工智能技术的不断发展&#xff0c;光学字符识别&#xff08;OCR&#xff09;技术在各行各业得到了广泛应用。OCR技术能够将图片、扫描件等非结构化数据中的文字信息提取出来&#xff0c;转换为可编辑的文本格式。在我国&#xff0c;百度开源了一款优秀的OCR工具…

如果在docker 容器中安装ros遇到的问题

1.在容器内部无法修改时间&#xff0c;需要在宿主机外边修改时钟。修改时钟&#xff1a; hwclock --systohc或者执行 date -s "2024-11-24 19:25:10"2.容器内部内置有opencv4.5版本&#xff0c;需要卸载&#xff0c;重新安装4.2.0版本。记录折腾好久的卸载过程。 …

LLM*:路径规划的大型语言模型增强增量启发式搜索

路径规划是机器人技术和自主导航中的一个基本科学问题&#xff0c;需要从起点到目的地推导出有效的路线&#xff0c;同时避开障碍物。A* 及其变体等传统算法能够确保路径有效性&#xff0c;但随着状态空间的增长&#xff0c;计算和内存效率会严重降低。相反&#xff0c;大型语言…

ACL的原理与配置

ACL技术概述 ACL&#xff1b;访问控制列表 技术背景&#xff1a; 园区重要服务器资源被随意访问&#xff0c;容易泄露机密&#xff0c;造成安全隐患 病毒侵入内网&#xff0c;安全性降低 网络宽带被各类业务随意挤占&#xff0c;服务质量要求高的宽带得不到保障&#xff0…

【配置】pycharm运行的项目如何修改名称(项目名称、模块名称)

当我们需要修改项目名称、模块名称的时候&#xff0c;能够在网上找一些修改的方法&#xff0c;但是有没有很保守但很使用的方法可以解决这个问题呢&#xff1f; 创建项目 通过pycharm创建一个django的项目 创建之后的项目目录&#xff1a; 更改项目名称&#xff1a; 往往以…

【新人系列】Python 入门(十四):文件操作

✍ 个人博客&#xff1a;https://blog.csdn.net/Newin2020?typeblog &#x1f4dd; 专栏地址&#xff1a;https://blog.csdn.net/newin2020/category_12801353.html &#x1f4e3; 专栏定位&#xff1a;为 0 基础刚入门 Python 的小伙伴提供详细的讲解&#xff0c;也欢迎大佬们…

MySQL 启动失败问题分析与解决方案:`mysqld.service failed to run ‘start-pre‘ task`

目录 前言1. 问题背景2. 错误分析2.1 错误信息详解2.2 可能原因 3. 问题排查与解决方案3.1 检查 MySQL 错误日志3.2 验证 MySQL 配置文件3.3 检查文件和目录权限3.4 手动启动 MySQL 服务3.5 修复 systemd 配置文件3.6 验证依赖环境 4. 进一步优化与自动化处理结语 前言 在日常…