Home Regex를 이용한 에셋 참조 검색
Post
Cancel

Regex를 이용한 에셋 참조 검색

머리

개인 사용 용도로 툴 프로그래밍을 할 때 마음에 드는 부분은 무엇일까요?

저는 개인적으로 ‘동작 시간이 좀 오래걸려도 괜찮다’입니다.

노가다 혹은 삽질 하는거보단 빠르기도 하고, 런타임에는 이런 코드짜면 큰일나니까요.

예전에 커스텀 에디터와 regex 공부할 겸 참조검색하는 코드를 짰었습니다.

그걸로 복습겸 글을 씁니다. 물론 제 gist에서 다시 긁어온거지만 ㅎ.

https://gist.github.com/ashuatz/91c06ec67a3a3a7b395bef44676e9b22

274183833-ead2117c-f6cd-40ed-a49f-9e0aa4be464a.gif

주요 구현은 크게 두가지입니다.

‘파일’을 찾는것과 ‘오브젝트’를 찾는것 (그리고 많은 GUI 코드)

파일찾기

Prefab구성을 보면 guid를 통해 링킹이 되어있는 것을 알 수 있습니다.

Untitled

그럼뭐다? 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;
}

Untitled

위와 같이 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);
}

Untitled

이만큼의 영역을 regex로 따내고

1
@"m_GameObject: {fileID: (\d+)}"

Untitled

따낸 부분에서 해당식을 통해 값을 찾아옵니다.

이 찾은 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 쓰다가 화나서 겸사겸사 다시 글을 썻었습니다.

This post is licensed under CC BY 4.0 by the author.
Contents