콘텐츠로 이동

Unity Performance Testing — 자동화 성능 검증

Unity Performance Testing 패키지(com.unity.test-framework.performance)는 Unity Test Framework 위에서 동작하는 성능 벤치마크 도구입니다. 프레임 시간, 메모리, GC 할당을 자동 측정하고 결과를 JSON으로 저장해 CI 파이프라인에서 성능 회귀를 감지할 수 있습니다.


Packages/manifest.json
{
"dependencies": {
"com.unity.test-framework": "1.3.9",
"com.unity.test-framework.performance": "3.0.3"
}
}
Unity.PerformanceTesting
// Assembly Definition — Tests 어셈블리에 추가

using NUnit.Framework;
using Unity.PerformanceTesting;
using UnityEngine;
using UnityEngine.TestTools;
using System.Collections;
public class BasicPerformanceTests
{
// 동기 메서드 측정
[Test, Performance]
public void MathOperations_Performance()
{
Measure.Method(() =>
{
float result = 0f;
for (int i = 0; i < 10000; i++)
result += Mathf.Sqrt(i);
})
.WarmupCount(5)
.MeasurementCount(20)
.IterationsPerMeasurement(1)
.GC() // GC 할당도 측정
.Run();
}
// 비동기/코루틴 측정
[UnityTest, Performance]
public IEnumerator SceneLoad_Performance()
{
using (Measure.Frames().Scope())
{
yield return SceneManager.LoadSceneAsync("GameScene");
}
// Scope 내 모든 프레임의 시간을 수집
}
}

[Test, Performance]
public void ECS_Query_Performance()
{
// 커스텀 SampleGroup 정의
var queryTime = new SampleGroup(
"ECS Query Time",
SampleUnit.Millisecond,
increaseIsBetter: false);
var entityCount = new SampleGroup(
"Entity Count",
SampleUnit.None,
increaseIsBetter: true);
Measure.Method(() =>
{
var sw = System.Diagnostics.Stopwatch.StartNew();
int count = RunECSQuery();
sw.Stop();
Measure.Custom(queryTime,
sw.Elapsed.TotalMilliseconds);
Measure.Custom(entityCount, count);
})
.WarmupCount(3)
.MeasurementCount(15)
.Run();
}

[UnityTest, Performance]
public IEnumerator GameplayLoop_FrameTime()
{
// 씬 로드
yield return SceneManager.LoadSceneAsync("BattleScene");
// 설정 단계 (측정 제외)
SpawnEnemies(100);
yield return new WaitForSeconds(1f);
// 60프레임 측정
yield return Measure.Frames()
.WarmupCount(10)
.MeasurementCount(60)
.SampleGroup(new SampleGroup(
"Frame Time",
SampleUnit.Millisecond))
.Run();
}
// 특정 구간만 측정
[UnityTest, Performance]
public IEnumerator ExplosionEffect_Performance()
{
yield return SceneManager.LoadSceneAsync("TestScene");
using (Measure.Frames()
.SampleGroup("Explosion Frame Time")
.Scope())
{
TriggerExplosion();
yield return new WaitForSeconds(2f);
}
}

[Test, Performance]
public void ObjectPool_Memory()
{
// 메모리 할당량 측정
Measure.Method(() =>
{
var pool = new List<GameObject>();
for (int i = 0; i < 100; i++)
pool.Add(new GameObject());
foreach (var go in pool)
Object.DestroyImmediate(go);
})
.GC() // GC.Collect() 호출 및 할당 추적
.MeasurementCount(10)
.Run();
// SampleGroup으로 메모리 직접 샘플링
var memGroup = new SampleGroup(
"Total Memory MB",
SampleUnit.Megabyte);
Measure.Custom(memGroup,
GC.GetTotalMemory(false) / (1024f * 1024f));
}

Terminal window
# 테스트 실행 및 JSON 결과 저장
Unity -batchmode -projectPath . \
-runTests \
-testPlatform EditMode \
-testResults results.xml \
-performanceTestResults perf_results.json
# 결과 파일 위치
# Assets/StreamingAssets/PerformanceTest*.json
// 결과 JSON 구조
// {
// "results": [{
// "name": "MathOperations_Performance",
// "sampleGroups": [{
// "name": "Time",
// "unit": "Millisecond",
// "samples": [0.12, 0.11, 0.13, ...],
// "median": 0.12,
// "average": 0.12,
// "standardDeviation": 0.005
// }]
// }]
// }

// 임계값 기반 회귀 감지
[Test, Performance]
public void Pathfinding_Performance_Threshold()
{
float totalTime = 0f;
const int runs = 50;
Measure.Method(() =>
{
var sw = System.Diagnostics.Stopwatch.StartNew();
RunPathfinding();
totalTime += (float)sw.Elapsed.TotalMilliseconds;
})
.MeasurementCount(runs)
.Run();
float avg = totalTime / runs;
// 5ms 초과 시 실패
Assert.Less(avg, 5f,
$"경로 탐색 평균 시간이 임계값 초과: {avg:F2}ms");
}

Unity Performance Testing은 Measure.Method로 CPU 코드를, Measure.Frames로 렌더링 성능을 측정하세요. .GC()를 항상 포함해 GC 할당 제로화(zero-alloc) 목표를 수치로 검증하고, JSON 결과를 CI에서 이전 빌드와 비교해 성능 회귀를 자동으로 감지하는 파이프라인을 구축하면 게임 최적화 작업이 훨씬 체계적으로 진행됩니다.