머리
개인 사용 용도로 툴 프로그래밍을 할 때 마음에 드는 부분은 무엇일까요?
저는 개인적으로 ‘동작 시간이 좀 오래걸려도 괜찮다’입니다.
노가다 혹은 삽질 하는거보단 빠르기도 하고, 런타임에는 이런 코드짜면 큰일나니까요.
예전에 커스텀 에디터와 regex 공부할 겸 참조검색하는 코드를 짰었습니다.
그걸로 복습겸 글을 씁니다. 물론 제 gist에서 다시 긁어온거지만 ㅎ.
https://gist.github.com/ashuatz/91c06ec67a3a3a7b395bef44676e9b22
몸
주요 구현은 크게 두가지입니다.
‘파일’을 찾는것과 ‘오브젝트’를 찾는것 (그리고 많은 GUI 코드)
파일찾기
Prefab구성을 보면 guid를 통해 링킹이 되어있는 것을 알 수 있습니다.
그럼뭐다? regex를 사용해서 긁어오면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private static bool TryGetObjectFileID(in string prefabContent, in string targetGuid, out List<string> name)
{
string pattern_fildID = @"fileID: (\d+).*?guid: ([a-fA-F0-9]{32})";
name = new List<string>();
foreach (Match match in Regex.Matches(prefabContent, pattern_fildID))
{
string localIdentifier = match.Groups[1].Value.Trim();
string guid = match.Groups[2].Value.Trim();
if (guid == targetGuid)
{
var id = ExtractGameObjectFileID(prefabContent, targetGuid);
if (id.HasValue)
{
name.Add(id.Value.ToString());
Debug.Log(match);
}
}
}
return name.Count > 0;
}
위와 같이 file id와 guid를 동시에 긁어, guid의 일치여부를 확인한 후,
gameobject의 fileID를 긁는작업을 시작합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static long? ExtractGameObjectFileID(string content, string targetGUID)
{
string pattern = @"(?s)m_ObjectHideFlags(?:(?!m_ObjectHideFlags).)*?guid: " + targetGUID;
Match match = Regex.Match(content, pattern);
if (!match.Success)
return null;
string sectionContent = match.Groups[0].Value;
string gameObjectPattern = @"m_GameObject: {fileID: (\d+)}";
Match gameObjectMatch = Regex.Match(sectionContent, gameObjectPattern);
if (!gameObjectMatch.Success)
return null;
return long.Parse(gameObjectMatch.Groups[1].Value);
}
이만큼의 영역을 regex로 따내고
1
@"m_GameObject: {fileID: (\d+)}"
따낸 부분에서 해당식을 통해 값을 찾아옵니다.
이 찾은 fileID들은 추후 프리팹 내 오브젝트, 씬에 존재하는 오브젝트 등에 검사용도로 사용됩니다.
오브젝트 찾기
핵심만보면 아래가 끝입니다.
1
2
3
4
5
6
7
8
enumerator = Resources.FindObjectsOfTypeAll(typeof(GameObject)).GetEnumerator();
var obj = (enumerator.Current) as UnityEngine.Object;
var id = GlobalObjectId.GetGlobalObjectIdSlow(obj.GetInstanceID());
if (!TotalFileIds.Contains(id.targetObjectId.ToString()))
return;
Results.Add(obj);
FindObjectsOfTypeAll을 통해 GameObject를 모두 탐색하고, GetGlobalObjectIdSlow를 통해 아까 가져온 m_GameObject: {fileID: (어쩌구저쩌구)} 의 fileID값을 통해 비교합니다.
정규표현식과 파일구조만 알면 쉽게 검색할 수 있는 단순한 구조입니다.
기타 에디터타임에 동작할 수 있게 코루틴을 못 돌리니 이차저차한 무언가의 흔적들이 좀 있습니다.
꼬리
직렬화 방식이 바뀌면 정규표현식(regex)도 바꿔줘야합니다.
언제나 그렇듯 실제 사용하기엔 더 좋은게 있습니다.
바퀴를 이해하기 위해 구현하는 것은 좋지만 실제 사용할땐 미쉐린 타이어 쓰세요.
https://assetstore.unity.com/packages/tools/utilities/asset-usage-detector-112837
감사합니다.
+이사람은 이 글을 쓴걸 모르고 5월31일에 regex 쓰다가 화나서 겸사겸사 다시 글을 썻었습니다.