Version: 2021.3
Package Manifest 窗口
访问包资源

包的脚本 API

您可以编写 C#脚本使用 Package Manager 脚本 API 与 Package Manager 进行交互。例如,可能需要根据目标机器的平台来安装特定的包或版本。

系统在很大程度上依赖 PackageManager.Client 类,可使用该类来查找包、浏览包列表以及通过脚本安装和卸载包。

另一个重要的类是 PackageManager.PackageInfo,其中包含包的状态,包括从包清单和注册表获取的元数据。例如,可获取适用于包的版本列表,或者获取在查找或安装包时可能发生的所有错误的列表

将包添加到项目

以下示例演示了如何使用 Client 类来安装包或者将包添加到项目中。

可以使用 Client.Add 添加包:在调用 Client.Add 方法时,您只需指定包名称或具有特定版本的名称。例如,使用 Client.Add("com.unity.textmeshpro"),则会安装(或更新到)TextMesh Pro 包的最新版本;使用 Client.Add("com.unity.textmeshpro@1.3.0"),则会安装 TextMesh Pro 包版本 1.3.0。

Client.Add 方法将返回 AddRequest 实例,可以用来获取状态、任何错误或 Request 响应(包含新添加的包的 PackageInfo 信息)。

using System;
using UnityEditor;
using UnityEditor.PackageManager.Requests;
using UnityEditor.PackageManager;
using UnityEngine;

namespace Unity.Editor.Example {
   static class AddPackageExample
   {
       static AddRequest Request;

       [MenuItem("Window/Add Package Example")]
       static void Add()
       {
           // Add a package to the project
           Request = Client.Add("com.unity.textmeshpro");
           EditorApplication.update += Progress;
       }

       static void Progress()
       {
           if (Request.IsCompleted)
           {
               if (Request.Status == StatusCode.Success)
                   Debug.Log("Installed: " + Request.Result.packageId);
               else if (Request.Status >= StatusCode.Failure)
                   Debug.Log(Request.Error.message);

               EditorApplication.update -= Progress;
           }
       }
   }
}

浏览项目中的包列表

以下示例演示了如何使用 Client 类来遍历项目中的包。

Client.List 方法将返回 ListRequest 实例,可以用来获取 List 操作的状态、任何错误或者 Request 响应(包含您可以遍历的 PackageCollection)。

using System;
using UnityEditor;
using UnityEditor.PackageManager.Requests;
using UnityEditor.PackageManager;
using UnityEngine;

namespace Unity.Editor.Example {
   static class ListPackageExample
   {
       static ListRequest Request;

       [MenuItem("Window/List Package Example")]
       static void List()
       {
           Request = Client.List();    // List packages installed for the project
           EditorApplication.update += Progress;
       }

       static void Progress()
       {
           if (Request.IsCompleted)
           {
               if (Request.Status == StatusCode.Success)
                   foreach (var package in Request.Result)
                       Debug.Log("Package name: " + package.name);
               else if (Request.Status >= StatusCode.Failure)
                   Debug.Log(Request.Error.message);

               EditorApplication.update -= Progress;
           }
       }
   }
}

在项目中嵌入包

以下示例演示了如何使用 Client 类来嵌入您的项目中已经安装的某个包。主方法是 Client.Embed 方法,可生成包的副本并存储在项目的 Packages 文件夹下面。

Client.Embed 方法将返回 EmbedRequest 实例,可以用来获取 Embed 操作的状态、任何错误或 Request 响应(包含新嵌入的包的 PackageInfo 信息)。

此示例还使用 Client.List 方法来访问项目中当前安装的包的集合,并选择第一个既不是嵌入式包也不是内置包的包。

Client.List 方法将返回 ListRequest 实例,可以用来获取 List 操作的状态、任何错误或者 Request 响应(包含您可以遍历的 PackageCollection)。

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.PackageManager.Requests;
using UnityEditor.PackageManager;
using UnityEngine;

namespace Unity.Editor.Example
{
    static class EmbedPackageExample
    {
        static String targetPackage;
        static EmbedRequest Request;
        static ListRequest LRequest;

        [MenuItem("Window/Embed Package Example")]
        static void GetPackageName()
        {
            // 首先获取一个已安装的包的名称
            LRequest = Client.List();
            EditorApplication.update += LProgress;
        }

        static void LProgress()
        {
            if (LRequest.IsCompleted)
            {
                if (LRequest.Status == StatusCode.Success)
                {
                    foreach (var package in LRequest.Result)
                    {
                        // 仅获取项目中当前安装的包
                        //(既不是内置的包也不是已嵌入的包)
                        if (package.isDirectDependency && package.source
                            != PackageSource.BuiltIn && package.source
                            != PackageSource.Embedded)
                        {
                            targetPackage = package.name;
                            break;
                        }
                    }

                }
                else
                    Debug.Log(LRequest.Error.message);

                EditorApplication.update -= LProgress;

                Embed(targetPackage);

            }
        }

        static void Embed(string inTarget)
        {
            // 将包嵌入项目中
            Debug.Log("Embed('" + inTarget + "') called");
            Request = Client.Embed(inTarget);
            EditorApplication.update += Progress;

        }

        static void Progress()
        {
            if (Request.IsCompleted)
            {
                if (Request.Status == StatusCode.Success)
                    Debug.Log("Embedded: " + Request.Result.packageId);
                else if (Request.Status >= StatusCode.Failure)
                    Debug.Log(Request.Error.message);

                EditorApplication.update -= Progress;
            }
        }
    }
}


Package Manager 事件

使用 Events 类向 Package Manager 注册事件处理程序。Events 类包含两个您可以订阅的事件,Package Manager 在以下时间点引发:

Package Manager 即将更改依赖项列表 (registeringPackages) Package Manager 导入并编译更改的包依赖项列表之后 (registeredPackages)

以下示例演示了如何使用这两个事件。

使用 registeringPackages 事件的示例

using UnityEditor.PackageManager;
using UnityEngine;

namespace Unity.Editor.Example
{
    public class EventSubscribingExample_RegisteringPackages
    {
        public EventSubscribingExample_RegisteringPackages()
        {
            // 使用加法赋值运算符 (+=) 订阅事件。
            // 每当触发事件时,它都会执行处理程序中的代码。
            Events.registeringPackages += RegisteringPackagesEventHandler;
        }

        // 该方法应接收 PackageRegistrationEventArgs 事件参数。
        void RegisteringPackagesEventHandler(PackageRegistrationEventArgs packageRegistrationEventArgs)
        {
            Debug.Log("The list of registered packages is about to change!");

           foreach (var addedPackage in packageRegistrationEventArgs.added)
            {
                Debug.Log($"Adding {addedPackage.displayName}");
            }

            foreach (var removedPackage in packageRegistrationEventArgs.removed)
            {
                Debug.Log($"Removing {removedPackage.displayName}");
            }

            // changedFrom 和 changedTo 集合包含即将更新的包。
            // 保证两个集合的大小相同,索引匹配相同的包名称。
            for (int i = 0; i <= packageRegistrationEventArgs.changedFrom.Count; i++)
            {
                var oldPackage = packageRegistrationEventArgs.changedFrom[i];
                var newPackage = packageRegistrationEventArgs.changedTo[i];

                Debug.Log($"Changing ${oldPackage.displayName} version from ${oldPackage.version} to ${newPackage.version}");
            }
        }
    }
}

使用 registeredPackages 事件的示例

using UnityEditor;
using UnityEditor.PackageManager;
using UnityEngine;

namespace Unity.Editor.Example
{
    public class EventSubscribingExample_RegisteredPackages
    {
        // 必须使用 '[InitializeOnLoadMethod]' 或 '[InitializeOnLoad]' 订阅此事件。
        [InitializeOnLoadMethod]
        static void SubscribeToEvent()
        {
            // 这会导致在编辑器注册新的包列表后调用该方法。
            Events.registeredPackages += RegisteredPackagesEventHandler;
        }

        static void RegisteredPackagesEventHandler(PackageRegistrationEventArgs packageRegistrationEventArgs)
        {
            // 这里执行的代码可以安全地假设编辑器已经完成了新的包列表的编译
            Debug.Log("The list of registered packages has changed!");
        }
    }
}
Package Manifest 窗口
访问包资源