Unity/Programming
Unity Package Manager My Assets(구매 에셋) 목록 CSV 추출
CatDarkGame
2024. 10. 14. 23:35
반응형
개요
Unity Package Manger에 표시되는 My Assets (구매 에셋) 목록을 CSV 데이터로 일괄 추출하는 스크립트입니다.
기능 동작 검증을 위한 샘플 코드인점 참고 바랍니다. (사용성이 조잡하다는 의미)
사용법
1. 스크립트 제작
- 아래 코드를 복사해서 프로젝트 내부 Editor 스크립트를 생성합니다.
using UnityEditor;
using UnityEngine;
using System.Reflection;
using System.IO;
using System.Text;
namespace CatDarkGame.Editor
{
public class PackageManagerHooker : EditorWindow
{
private static string k_OutputFileName = "MyAssetsList.csv";
[MenuItem("Tools/PackageManager Hooker/Export MyAssets Info to CSV")]
public static void ExportAssetStoreProductInfoToCSV()
{
var packageManagerWindowType = typeof(UnityEditor.Editor).Assembly.GetType("UnityEditor.PackageManager.UI.PackageManagerWindow");
if (packageManagerWindowType == null)
{
Debug.LogError("먼저 Package Manager를 실행 후, My Assets 리스트를 로드하고 이 기능을 실행하세요.");
return;
}
var packageManagerWindow = GetFirstInstance(packageManagerWindowType);
if (packageManagerWindow == null) return;
var packageList = GetPackageList(packageManagerWindow);
if (packageList == null) return;
var mAssetStoreCache = GetFieldValue(packageList, "m_AssetStoreCallQueue", "m_AssetStoreCache");
if (mAssetStoreCache == null) return;
var productInfos = GetFieldValue(mAssetStoreCache, "m_SerializedProductInfos") as object[];
if (productInfos == null)
{
Debug.LogError("m_SerializedProductInfos is null.");
return;
}
StringBuilder csvBuilder = new StringBuilder();
csvBuilder.AppendLine("category,displayName,publisherName,publishedDate,assetStoreLinkUrl");
foreach (var productInfo in productInfos)
{
var data = ExtractProductInfo(productInfo);
csvBuilder.AppendLine(string.Join(",", data));
}
SaveCSV(csvBuilder.ToString());
}
private static object GetFirstInstance(System.Type type)
{
var instances = Resources.FindObjectsOfTypeAll(type);
if (instances.Length == 0)
{
Debug.LogError("No PackageManagerWindow instance found.");
return null;
}
return instances[0];
}
private static object GetPackageList(object window)
{
var mRoot = GetFieldValue(window, "m_Root");
if (mRoot == null) return null;
var packageListProperty = mRoot.GetType().GetProperty("packageList", BindingFlags.NonPublic | BindingFlags.Instance);
if (packageListProperty == null)
{
Debug.LogError("packageList property not found.");
return null;
}
return packageListProperty.GetValue(mRoot);
}
private static object GetFieldValue(object instance, string fieldName, string nestedFieldName = null)
{
var field = instance.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
if (field == null)
{
Debug.LogError($"{fieldName} field not found.");
return null;
}
var value = field.GetValue(instance);
if (value == null)
{
Debug.LogError($"{fieldName} is null.");
return null;
}
if (!string.IsNullOrEmpty(nestedFieldName))
{
var nestedField = value.GetType().GetField(nestedFieldName, BindingFlags.NonPublic | BindingFlags.Instance);
if (nestedField == null)
{
Debug.LogError($"{nestedFieldName} field not found.");
return null;
}
value = nestedField.GetValue(value);
}
return value;
}
private static string[] ExtractProductInfo(object productInfo)
{
var productInfoType = productInfo.GetType();
string category = (string)productInfoType.GetField("category").GetValue(productInfo);
string displayName = (string)productInfoType.GetField("displayName").GetValue(productInfo);
string publisherName = (string)productInfoType.GetField("publisherName").GetValue(productInfo);
string publishedDate = (string)productInfoType.GetField("publishedDate").GetValue(productInfo);
var assetStoreLink = productInfoType.GetField("assetStoreLink").GetValue(productInfo);
string assetStoreLinkUrl = "";
if (assetStoreLink != null)
{
assetStoreLinkUrl = (string)assetStoreLink.GetType().GetField("url").GetValue(assetStoreLink);
}
return new string[] { category, displayName, publisherName, publishedDate, assetStoreLinkUrl };
}
private static void SaveCSV(string csvData)
{
string filePath = EditorUtility.SaveFilePanel(
"Save CSV File",
Application.dataPath,
k_OutputFileName,
"csv"
);
if (!string.IsNullOrEmpty(filePath))
{
File.WriteAllText(filePath, csvData);
Debug.Log($"CSV export complete: {filePath}");
// 파일을 탐색기에서 선택
EditorUtility.RevealInFinder(filePath);
}
else
{
Debug.LogWarning("File save canceled.");
}
AssetDatabase.Refresh();
}
}
}
2. Package Manager My Assets 목록 로드
- Package Manger 실행 후, My Assets 목록을 전부 로드합니다.
- Load / All까지 완료되야합니다.
- 스크롤을 끝까지 천천히해서 로딩 아이콘이 전부 완료되도록 합니다.
3. 아무 파일 선택해서 Reimport
- 프로젝트에서 아무 파일 선택해서 Reimport 합니다.
- 이 작업이 되야 PackageManger 리스트에서 정보 참조가 가능합니다.
4. CSV 추출 툴 실행
- 위 3번 과정 완료 후, Package Manager를 계속 켜 놓습니다.
- 그리고 Export MyAssets Info to CSV 기능을 실행하면 CSV 파일로 추출됩니다.
기타
CSV 파일은 "," 문자로 Colume을 구분하는데, 따로 예외처리 하지 않아서 CSV 파일 데이터가 이상하게 저장될 수 있습니다.
그 외 다른 Colume 정보
var productInfoType = productInfo.GetType();
string id = (string)productInfoType.GetField("id").GetValue(productInfo);
string packageName = (string)productInfoType.GetField("packageName").GetValue(productInfo);
string description = (string)productInfoType.GetField("description").GetValue(productInfo);
string publisherName = (string)productInfoType.GetField("publisherName").GetValue(productInfo);
string category = (string)productInfoType.GetField("category").GetValue(productInfo);
string versionString = (string)productInfoType.GetField("versionString").GetValue(productInfo);
string versionId = (string)productInfoType.GetField("versionId").GetValue(productInfo);
string publishedDate = (string)productInfoType.GetField("publishedDate").GetValue(productInfo);
string displayName = (string)productInfoType.GetField("displayName").GetValue(productInfo);
string state = (string)productInfoType.GetField("state").GetValue(productInfo);
string publishNotes = (string)productInfoType.GetField("publishNotes").GetValue(productInfo);
string firstPublishedDate = (string)productInfoType.GetField("firstPublishedDate").GetValue(productInfo);
string publisherLink = (string)productInfoType.GetField("publisherLink").GetValue(productInfo);
var assetStoreLinkField = productInfoType.GetField("assetStoreLink");
var assetStoreLink = assetStoreLinkField.GetValue(productInfo);
string assetStoreLinkName = "";
string assetStoreLinkUrl = "";
if (assetStoreLink != null)
{
var assetStoreLinkType = assetStoreLink.GetType();
assetStoreLinkName = (string)assetStoreLinkType.GetField("name").GetValue(assetStoreLink);
assetStoreLinkUrl = (string)assetStoreLinkType.GetField("url").GetValue(assetStoreLink);
}
반응형