패키지 관리자 스크립팅 API를 사용하면 C# 스크립트를 통해 패키지 관리자와 상호 작용할 수 있습니다. 예를 들어 타겟 머신의 플랫폼에 따라 특정 패키지나 버전을 설치할 수 있습니다.
이 시스템은 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 메서드는 상태, 오류 또는 새로 추가된 패키지에 대한 PackageInfo 정보를 포함하는 Request 응답을 가져오는 데 사용할 수 있는 AddRequest 인스턴스를 반환합니다.
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 작업 상태, 오류, 또는 반복할 수 있는 PackageCollection을 포함하는 Request 응답을 가져올 수 있습니다.
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 메서드는 임베드 작업의 상태, 오류 또는 새로 임베드된 패키지에 대한 PackageInfo 정보를 포함하는 Request 응답을 가져오는 데 사용할 수 있는 EmbedRequest 인스턴스를 반환합니다.
또한 이 예제에서는 Client.List 메서드를 사용하여 프로젝트에 현재 설치된 패키지 컬렉션에 액세스한 후 포함되거나 내장되지 않은 첫 번째 패키지를 선택합니다.
Client.List 메서드는 ListRequest 인스턴스를 반환합니다. 이 인스턴스를 사용하면 List 작업 상태, 오류, 또는 반복할 수 있는 PackageCollection을 포함하는 Request 응답을 가져올 수 있습니다.
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()
{
// First get the name of an installed package
LRequest = Client.List();
EditorApplication.update += LProgress;
}
static void LProgress()
{
if (LRequest.IsCompleted)
{
if (LRequest.Status == StatusCode.Success)
{
foreach (var package in LRequest.Result)
{
// Only retrieve packages that are currently installed in the
// project (and are neither Built-In nor already Embedded)
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)
{
// Embed a package in the project
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;
}
}
}
}
Events 클래스를 사용하여 패키지 관리자에 이벤트 핸들러를 등록합니다. Events 클래스에는 구독할 수 있는 두 가지 이벤트가 포함되어 있으며, 패키지 관리자는 다음 지점에서 이 이벤트를 발생시킵니다.
다음 예는 이러한 두 이벤트를 모두 사용하는 방법을 보여줍니다.
using UnityEditor.PackageManager;
using UnityEngine;
namespace Unity.Editor.Example
{
public class EventSubscribingExample_RegisteringPackages
{
public EventSubscribingExample_RegisteringPackages()
{
// Subscribe to the event using the addition assignment operator (+=).
// This executes the code in the handler whenever the event is fired.
Events.registeringPackages += RegisteringPackagesEventHandler;
}
// The method is expected to receive a PackageRegistrationEventArgs event argument.
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}");
}
// The changedFrom and changedTo collections contain the packages that are about to be updated.
// Both collections are guaranteed to be the same size with indices matching the same package name.
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}");
}
}
}
}
using UnityEditor;
using UnityEditor.PackageManager;
using UnityEngine;
namespace Unity.Editor.Example
{
public class EventSubscribingExample_RegisteredPackages
{
// You must use '[InitializeOnLoadMethod]' or '[InitializeOnLoad]' to subscribe to this event.
[InitializeOnLoadMethod]
static void SubscribeToEvent()
{
// This causes the method to be invoked after the Editor registers the new list of packages.
Events.registeredPackages += RegisteredPackagesEventHandler;
}
static void RegisteredPackagesEventHandler(PackageRegistrationEventArgs packageRegistrationEventArgs)
{
// Code executed here can safely assume that the Editor has finished compiling the new list of packages
Debug.Log("The list of registered packages has changed!");
}
}
}