AssetDatabase란?
Unity Editor상에서 모든 에셋 관련 파일 처리를 할때 사용하는 클래스로 기본 파일 입출력부터 Material, Prefab, Animationclip, CustomAsset등 파일을 만들고 제어 할 수 있습니다.
응용으로 프로젝트 내의 모든 씬파일을 찾아서 수정을 하거나, 현재 씬에 존재하는 오브젝트들을 자동으로 프리펩으로 만들어주는 기능을 만들 수 있습니다.
주의할 점은 AssetDatabase클래스는 Editor상에서만 동작하며 해당 코드를 사용하는 부분은 #if UNITY_EDITOR 조건 컴파일을 걸어야 빌드할때 에러나지 않습니다.
1. 파일탐색
string[] sAssetGuids = AssetDatabase.FindAssets("t:TextAsset", new[] { "Assets/JsonTest/Datas" });
string[] sAssetPathList = Array.ConvertAll<string, string>(sAssetGuids, AssetDatabase.GUIDToAssetPath);
foreach(string sAssetPath in sAssetPathList)
{
TextAsset pAssetObject = AssetDatabase.LoadAssetAtPath(sAssetPath, typeof(TextAsset)) as TextAsset;
Debug.Log("에셋 로드 : " + AssetDatabase_Function.GetAssetName(sAssetPath));
}
FindAsset
public static string[] FindAssets(string filter, string[] searchInFolders);
public static string[] FindAssets(string filter);
프로젝트의 Assets폴더안에 있는 에셋파일을 찾아서 가져오는 함수입니다.
찾은 에셋의 GUID를 string배열로 반환합니다.
- GUID란?
GUID는 Globally Unique IDentifier의 약자로 에셋의 고유 ID정보입니다.
프로젝트 내부에서 중복될일은 없으나 2개 이상 프로젝트에서 에셋이 와리가리 하면 중복될 가능성이 있습니다.
- string filter
co:이름 검색 (아마 contains?) l:라벨 검색 t:Object의 type (Scene, Material. Model, 등) |
에셋가져오는 목록의 필터입니다.
예시
AssetDatabase.FindAssets ("co:Sword t:prefab t:material", new string[]{ "Assets/Weapons" });
라벨은 에셋의 Inspector 정보의 하단에 위치한 이것입니다.
- string[] searchInFolders
검색할 폴더입니다. "Assets/..."부터 입력하면 되고 여러 경로를 포함할 수 있습니다.
경로 가져오기
string[] sAssetPathList = Array.ConvertAll<string, string>(sAssetGuids, AssetDatabase.GUIDToAssetPath);
foreach(string sAssetPath in sAssetPathList)
{
TextAsset pAssetObject = AssetDatabase.LoadAssetAtPath(sAssetPath, typeof(TextAsset)) as TextAsset;
Debug.Log("에셋 로드 : " + AssetDatabase_Function.GetAssetName(sAssetPath));
}
이전에 GUID로 가져온 리스트를 AssetDatabase.GUIDToAssetPath을 통해서 실제 경로로 변환하고
LoadAssetAtPath함수를 통해 에셋으로 가져오면 됩니다.
추가 응용
public static class AssetDatabase_Function
{
//! AssetPath를 넣으면 해당 에셋 파일 이름을 반환
public static string GetAssetName(string sAssetPath)
{
string sAssetName = sAssetPath.Substring(sAssetPath.LastIndexOf("/") + 1);
return sAssetName;
}
//! AssetPath를 넣으면 해당 에셋 파일 경로를 반환(파일 이름 제외)
public static string GetAssetPath(string sAssetPath)
{
string sAssetName = sAssetPath.Substring(0, sAssetPath.LastIndexOf("/"));
return sAssetName;
}
}
AssetDatabase를 사용하다보면 에셋 이름만 가져오기, 경로가져오는 일이 많은데 편리하게 사용하기 위해 Static함수 만들 었습니다.
결과
2. 선택한 에셋 경로 가져오기
[MenuItem("Assets/GetAssetPath")]
static void GetAssetPath()
{
UnityEngine.Object pSelectObj = Selection.activeObject;
string sAssetPath = AssetDatabase.GetAssetPath(pSelectObj.GetInstanceID());
Debug.Log(sAssetPath);
}
Selection.activeObject로 Project 탭에서 선택한 파일 포인터정보를 가져옵니다.
AssetDatabase.GetAssetPath(pSelectObj.GetInstanceID()); 그리고 이 코드를 통해 해당 에셋의 경로를 가져 올 수 있습니다.
3. 에셋 생성하기
public static bool IsFolder(UnityEngine.Object obj)
{
if (obj == null) return false;
string path = "";
path = AssetDatabase.GetAssetPath(obj.GetInstanceID());
if (path.Length > 0)
{
if (Directory.Exists(path)) return true;
}
return false;
}
public static bool IsExist(string sAssetPath)
{
if (string.IsNullOrEmpty(AssetDatabase.AssetPathToGUID(sAssetPath))) return false;
return true;
}
[MenuItem("Assets/CreaetMaterialFile")]
static void CreaetMaterialFile()
{
UnityEngine.Object pSelectObj = Selection.activeObject;
bool bIsFolder = AssetDatabase_Function.IsFolder(pSelectObj);
if (bIsFolder == false)
{
Debug.LogError("폴더를 선택하세요.");
return;
}
string sFolderPath = AssetDatabase.GetAssetPath(pSelectObj.GetInstanceID());
string sAssetPath = string.Format(sFolderPath + "/{0}.mat", "TestMaterial");
bool bIsExist = AssetDatabase_Function.IsExist(sAssetPath);
if (bIsExist == true)
{
Debug.LogError("파일이 이미 존재함");
return;
}
Material pMat = new Material(Shader.Find("Diffuse"));
AssetDatabase.CreateAsset(pMat, sAssetPath);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
[MenuItem("Assets/CreaetTextFile")]
static void CreaetTextFile()
{
UnityEngine.Object pSelectObj = Selection.activeObject;
bool bIsFolder = AssetDatabase_Function.IsFolder(pSelectObj);
if (bIsFolder == false)
{
Debug.LogError("폴더를 선택하세요.");
return;
}
string sFolderPath = AssetDatabase.GetAssetPath(pSelectObj.GetInstanceID());
string sAssetPath = string.Format(sFolderPath + "/{0}.txt", "TestText");
bool bIsExist = AssetDatabase_Function.IsExist(sAssetPath);
if (bIsExist == true)
{
Debug.LogError("파일이 이미 존재함");
return;
}
System.IO.FileInfo file = new System.IO.FileInfo(sAssetPath);
file.Directory.Create();
File.WriteAllText(file.FullName, "ABCDEFG");
AssetDatabase.Refresh();
}
[MenuItem("Assets/CreaetPrefabFile")]
static void CreaetPrefabFile()
{
UnityEngine.Object pSelectObj = Selection.activeObject;
bool bIsFolder = AssetDatabase_Function.IsFolder(pSelectObj);
if (bIsFolder == false)
{
Debug.LogError("폴더를 선택하세요.");
return;
}
string sFolderPath = AssetDatabase.GetAssetPath(pSelectObj.GetInstanceID());
string sAssetPath = string.Format(sFolderPath + "/{0}.prefab", "TestPrefab");
bool bIsExist = AssetDatabase_Function.IsExist(sAssetPath);
if (bIsExist == true)
{
Debug.LogError("파일이 이미 존재함");
return;
}
GameObject pObj = GameObject.Find("TestPrefab");
if (pObj == null) return;
bool bSuccess = false;
GameObject pPrefab = PrefabUtility.SaveAsPrefabAsset(pObj, sAssetPath, out bSuccess);
if (bSuccess == true)
{
Debug.Log("레벨 프리펩 생성완료");
}
else
{
Debug.LogError("레벨 프리펩 생성 실패");
}
AssetDatabase.Refresh();
}
위 예제 코드에서 핵심은 에셋은 다양한 수단으로 만들수 있으며 에셋을 생성후에
AssetDatabase.Refresh(); 해야합니다.
(안하면 갱신이 안되는 문제가 발생합니다.)
위 코드를 통해 간단하게 3가지 형태의 에셋을 만드는 것을 해봤습니다.
4. 에셋 수정하기
[MenuItem("Assets/EditModelFile")]
static void EditModelFile()
{
UnityEngine.Object pSelectObj = Selection.activeObject;
string sAssetPath = AssetDatabase.GetAssetPath(pSelectObj.GetInstanceID());
string sAssetName = AssetDatabase_Function.GetAssetName(sAssetPath);
if (sAssetName.Contains(".fbx") || sAssetName.Contains(".FBX"))
{
ModelImporter importer = AssetImporter.GetAtPath(sAssetPath) as ModelImporter;
importer.materialImportMode = ModelImporterMaterialImportMode.None;
importer.SaveAndReimport();
EditorUtility.SetDirty(pSelectObj);
AssetDatabase.Refresh();
}
else
{
Debug.LogError("FBX파일이 아닙니다.");
}
}
이번엔 FBX에셋의 정보를 수정하는 코드를 작성했습니다.
간단하게 FBX의 마테리얼 Import 옵션을 끄는 코드입니다.
FBX는 다른 에셋과 달리 Refresh가 잘되지 않은 경험때문에
importer.SaveAndReimport();
EditorUtility.SetDirty(pSelectObj);
AssetDatabase.Refresh();
위 초기화 코드를 다 사용했습니다.
풀 소스 코드
#if UNITY_EDITOR
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
public static class AssetDatabase_Function
{
//! AssetPath를 넣으면 해당 에셋 파일 이름을 반환
public static string GetAssetName(string sAssetPath)
{
string sAssetName = sAssetPath.Substring(sAssetPath.LastIndexOf("/") + 1);
return sAssetName;
}
//! AssetPath를 넣으면 해당 에셋 파일 경로를 반환(파일 이름 제외)
public static string GetAssetPath(string sAssetPath)
{
string sAssetName = sAssetPath.Substring(0, sAssetPath.LastIndexOf("/"));
return sAssetName;
}
//! 해당 오브젝트가 폴더오브젝트인지 판단
public static bool IsFolder(UnityEngine.Object obj)
{
if (obj == null) return false;
string path = "";
path = AssetDatabase.GetAssetPath(obj.GetInstanceID());
if (path.Length > 0)
{
if (Directory.Exists(path)) return true;
}
return false;
}
public static bool IsExist(string sAssetPath)
{
if (string.IsNullOrEmpty(AssetDatabase.AssetPathToGUID(sAssetPath))) return false;
return true;
}
}
public class ADBTest
{
[MenuItem("AssetDataBaseTest/GetAllFiles")]
static void EditorWindow()
{
string[] sAssetGuids = AssetDatabase.FindAssets("t:TextAsset", new[] { "Assets/JsonTest/Datas" });
string[] sAssetPathList = Array.ConvertAll<string, string>(sAssetGuids, AssetDatabase.GUIDToAssetPath);
foreach(string sAssetPath in sAssetPathList)
{
TextAsset pAssetObject = AssetDatabase.LoadAssetAtPath(sAssetPath, typeof(TextAsset)) as TextAsset;
Debug.Log("에셋 로드 : " + AssetDatabase_Function.GetAssetName(sAssetPath));
}
}
[MenuItem("Assets/GetAssetPath")]
static void GetAssetPath()
{
UnityEngine.Object pSelectObj = Selection.activeObject;
string sAssetPath = AssetDatabase.GetAssetPath(pSelectObj.GetInstanceID());
Debug.Log(sAssetPath);
}
[MenuItem("Assets/CreaetMaterialFile")]
static void CreaetMaterialFile()
{
UnityEngine.Object pSelectObj = Selection.activeObject;
bool bIsFolder = AssetDatabase_Function.IsFolder(pSelectObj);
if (bIsFolder == false)
{
Debug.LogError("폴더를 선택하세요.");
return;
}
string sFolderPath = AssetDatabase.GetAssetPath(pSelectObj.GetInstanceID());
string sAssetPath = string.Format(sFolderPath + "/{0}.mat", "TestMaterial");
bool bIsExist = AssetDatabase_Function.IsExist(sAssetPath);
if (bIsExist == true)
{
Debug.LogError("파일이 이미 존재함");
return;
}
Material pMat = new Material(Shader.Find("Diffuse"));
AssetDatabase.CreateAsset(pMat, sAssetPath);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
[MenuItem("Assets/CreaetTextFile")]
static void CreaetTextFile()
{
UnityEngine.Object pSelectObj = Selection.activeObject;
bool bIsFolder = AssetDatabase_Function.IsFolder(pSelectObj);
if (bIsFolder == false)
{
Debug.LogError("폴더를 선택하세요.");
return;
}
string sFolderPath = AssetDatabase.GetAssetPath(pSelectObj.GetInstanceID());
string sAssetPath = string.Format(sFolderPath + "/{0}.txt", "TestText");
bool bIsExist = AssetDatabase_Function.IsExist(sAssetPath);
if (bIsExist == true)
{
Debug.LogError("파일이 이미 존재함");
return;
}
System.IO.FileInfo file = new System.IO.FileInfo(sAssetPath);
file.Directory.Create();
File.WriteAllText(file.FullName, "ABCDEFG");
AssetDatabase.Refresh();
}
[MenuItem("Assets/CreaetPrefabFile")]
static void CreaetPrefabFile()
{
UnityEngine.Object pSelectObj = Selection.activeObject;
bool bIsFolder = AssetDatabase_Function.IsFolder(pSelectObj);
if (bIsFolder == false)
{
Debug.LogError("폴더를 선택하세요.");
return;
}
string sFolderPath = AssetDatabase.GetAssetPath(pSelectObj.GetInstanceID());
string sAssetPath = string.Format(sFolderPath + "/{0}.prefab", "TestPrefab");
bool bIsExist = AssetDatabase_Function.IsExist(sAssetPath);
if (bIsExist == true)
{
Debug.LogError("파일이 이미 존재함");
return;
}
GameObject pObj = GameObject.Find("TestPrefab");
if (pObj == null) return;
bool bSuccess = false;
GameObject pPrefab = PrefabUtility.SaveAsPrefabAsset(pObj, sAssetPath, out bSuccess);
if (bSuccess == true)
{
Debug.Log("레벨 프리펩 생성완료");
}
else
{
Debug.LogError("레벨 프리펩 생성 실패");
}
AssetDatabase.Refresh();
}
[MenuItem("Assets/EditModelFile")]
static void EditModelFile()
{
UnityEngine.Object pSelectObj = Selection.activeObject;
string sAssetPath = AssetDatabase.GetAssetPath(pSelectObj.GetInstanceID());
string sAssetName = AssetDatabase_Function.GetAssetName(sAssetPath);
if (sAssetName.Contains(".fbx") || sAssetName.Contains(".FBX"))
{
ModelImporter importer = AssetImporter.GetAtPath(sAssetPath) as ModelImporter;
importer.materialImportMode = ModelImporterMaterialImportMode.None;
importer.SaveAndReimport();
EditorUtility.SetDirty(pSelectObj);
AssetDatabase.Refresh();
}
else
{
Debug.LogError("FBX파일이 아닙니다.");
}
}
}
#endif
'Unity > Programming' 카테고리의 다른 글
Unity URP HLSL 쉐이더 템플릿 생성 스크립트 (0) | 2023.03.07 |
---|---|
[Unity Editor] Particle System에서 싱글 Emission 자동 세팅 (1) | 2020.06.28 |
[Unity Editor] Editor Window (2) | 2020.05.24 |
[Unity Editor] MenuItem 종류 (1) | 2020.05.24 |
Unity에서 Json파일 입출력 (3) | 2020.05.23 |
WRITTEN BY
- CatDarkGame
Technical Artist dhwlgn12@gmail.com