Pooling

객체 풀링은 가비지 컬렉터의 부하를 줄이기 위해 사용됩니다.

풀링은 시스템을 많이 사용하거나 저사양 하드웨어(예: 모바일)에서 실행할 때 성능을 극대화하는 훌륭한 방법입니다. Mono 가비지 컬렉터는 더 이상 사용되지 않는 객체를 잘 수집하지만, 큰 문제는 GC가 실행될 때마다 게임을 일시적으로 멈추어야 한다는 점입니다. 이는 게임에서 몇 초마다 작은 끊김 현상으로 나타날 수 있습니다. 특히 메모리와 프로세서 성능이 제한된 모바일에서는 큰 문제가 됩니다.

이 문제를 해결하는 한 가지 방법은 대부분의 객체를 풀링하는 것입니다. 객체가 더 이상 사용되지 않으면 풀에 넣고, 이후 동일한 유형의 새 인스턴스가 필요할 때 풀에서 쉽게 얻을 수 있는 객체가 있는지 확인합니다. 풀을 사용하면 GC의 부하가 줄어들어 게임의 끊김 현상이 줄어듭니다.

Path Pooling

A* Pathfinding Project에서 풀링은 주로 경로와 리스트에 사용됩니다. 이는 가장 많이 할당되는 것이기 때문입니다. 스크립트에 풀링 로직을 추가하는 것은 매우 적은 코드로 가능하지만, 올바르게 수행하지 않으면 오류가 발생하기 쉽습니다.

A* Pathfinding Project의 풀링은 일종의 수동 참조 카운팅에 기반합니다. 경로 객체를 사용하기 시작할 때 .Claim 함수를 호출해야 하고, 더 이상 사용하지 않을 때(예: 새 경로로 대체될 때)는 Release 함수를 호출해야 합니다. 경로에 대한 Release 함수가 호출되고 다른 스크립트가 사용하지 않을 때, 경로는 언제든지 재활용될 수 있습니다. 이는 변수들이 언제든지 초기화될 수 있음을 의미합니다. 따라서 경로에 대해 Release를 호출한 후에는 해당 경로에 대한 참조를 유지해서는 안 됩니다. 경로 클래스의 vectorPath 및 path 리스트도 경로가 재활용될 때 재활용됩니다. 따라서 이를 다시 사용하지 않도록 주의해야 합니다. 만약 vectorPath/path 변수만 사용하고 경로를 재활용하고 싶다면, 이를 로컬 변수에 저장하고 경로 객체의 vectorPath/path 변수를 null로 설정한 후 경로를 릴리스하십시오. 변수가 null이므로 경로 객체는 이를 재활용할 수 없으며, 따라서 안전하게 사용할 수 있습니다.

참조
Pathfinding.Path.Claim
Pathfinding.Path.Release


경로에 대해 Claim이나 Release를 호출하지 않으면, 단순히 풀링되지 않습니다. 따라서 풀링을 신경 쓰고 싶지 않다면 신경 쓰지 않아도 됩니다. 경로에 대해 Claim을 호출하지만 Release를 호출하지 않고 모든 참조를 제거하면, 여전히 가비지 컬렉터에 의해 수집되지만 풀로 반환되지는 않습니다. Claim을 호출하지 않고 Release를 호출하거나, 동일한 객체에 대해 여러 번 Release를 호출하면 오류가 로그에 기록됩니다.

다음은 경로 풀링 사용의 예입니다:

public class SomeAI : MonoBehaviour {
    ABPath path;

    public IEnumerator Start () {
        while (true) {
            GetComponent<Seeker>().StartPath(transform.position, transform.position + transform.forward * 10, OnPathComplete);
            yield return new WaitForSeconds(1); // Added to prevent infinite loop in this example
        }
    }

    void OnPathComplete (Path p) {
        // 이전 경로를 풀로 반환
        if (path != null) path.Release(this);

        path = p as ABPath;

        // 새로운 경로 요청
        path.Claim(this);
    }

    void Update () {
        // 에디터에서 경로 그리기
        if (path != null && path.vectorPath != null) {
            for (int i = 0; i < path.vectorPath.Count - 1; i++) {
                Debug.DrawLine(path.vectorPath[i], path.vectorPath[i + 1], Color.green);
            }
        }
    }
}


경로가 풀링될 때, vectorPath 및 path 필드(및 경로 유형에 더 많은 리스트가 있는 경우)는 또한 풀링됩니다. 따라서 경로 객체에서 vectorPath를 가져오고 경로 객체를 풀링한 후에도 계속 vectorPath를 사용하는 것은 안전하지 않습니다.

Claim 및 Release 함수는 객체 참조를 가져옵니다. 이는 사용자 오류 가능성을 줄이기 위해 주로 사용됩니다. 동일한 객체를 사용하여 경로가 여러 번 릴리스되거나 여러 번 클레임되지 않도록 오류 검사가 수행됩니다.

List Pooling

대부분의 사용자에게는 중요하지 않을 수 있지만, 고급 사용자에게는 관련이 있을 수 있습니다. 이 프로젝트는 제네릭 리스트의 풀링도 포함합니다. 이는 시스템이 매번 새로운 리스트를 할당하지 않도록 내부적으로 사용됩니다. 리스트 풀링 클래스는 사용하기 매우 간단하며,  Pathfinding.Util.ListPool.Claim 을 사용하여 참조를 얻고, 완료되면  Pathfinding.Util.ListPool.Release 를 사용하여 해제합니다. ListPool 클래스는 타입 인수를 사용하므로 모든 리스트 타입에 사용할 수 있습니다.

// 리스트 참조 얻기
List<int> myList = Pathfinding.Util.ListPool<int>.Claim();

// 작업 수행
for (int i = 0; i < 100; i++) myList.Add(i);
int fiftytwo = myList[52];

// 해제
Pathfinding.Util.ListPool<int>.Release(ref myList);
// Release 호출 시 'ref' 매개변수를 사용하여 myList 변수를 동시에 null로 설정하여
// 리스트를 실수로 다시 사용하는 것을 방지합니다.



Debugging

풀링 설정이 복잡한 스크립트와 함께 사용되는 경우 설정이 어렵고 결과를 즉시 확인할 수 없기 때문에 디버거를 사용하는 것이 좋습니다. A*  Pathfinding Project에는 디버거가 포함되어 있습니다. Components ->  Pathfinding  -> Debugger를 GameObject에 추가하십시오.

Pathfinding.AstarDebugger 에 대한 자세한 정보는 참조하십시오.


또한 최적화 탭에서 ASTAR_POOL_DEBUG 정의를 활성화하는 것도 매우 유용합니다. 무료 버전만 있는 경우(최적화는 프로 전용 기능이므로),  Path.cs 파일을 열고 ASTAR_POOL_DEBUG를 언급하는 상단의 줄을 주석 해제하십시오.

이를 활성화하면 파괴된 모든 경로가 풀링되었는지, 잘못된 사용이 있었는지에 대한 정보를 로그에 기록합니다.

'유니티 에셋 > A* Pathfinding project pro' 카테고리의 다른 글

Deploying for mobile/uwp  (0) 2024.05.28
Optimization > Compiler Directives  (0) 2024.05.28
Optimization > Heuristic Optimization  (0) 2024.05.28
Optimization  (0) 2024.05.28
Deploying  (0) 2024.05.28

+ Recent posts