Mesh.vertices 프로퍼티 접근 시 GC 생성
public static Vector3[] CalcaultateSmoothNormal(this Mesh mesh)
{
Dictionary<Vector3, List<int>> indicesDict = new(comparer: new Vector3EqualityComparer());
for (int i = 0; i < mesh.vertexCount; i++)
{
if (!indicesDict.ContainsKey(mesh.vertices[i]))
indicesDict.Add(mesh.vertices[i], new());
indicesDict[mesh.vertices[i]].Add(i);
}
Vector3[] normals = new Vector3[originNormals.Length];
foreach (var indices in indicesDict.Values)
{
Vector3 normal = Vector3.zero;
foreach (var index in indices)
normal += mesh.normals[index];
normal /= indices.Count;
foreach (var index in indices)
normals[index] = normal;
}
return normals;
}
정점이 4400개 정도 되는 나무 오브젝트에 코드를 적용해보니 1초 정도 병목이 발생하길래 원인을 찾아보니 코드에서 엄청난 양의 GC가 발생하고 있었다.
Mesh.vertices 프로퍼티는 메시의 정점 배열을 똑같이 복사해서 반환해준다
그런데 나는 이 프로퍼티를 반복문을 돌며 인덱싱 중이었다..........
정점 4400개 * 반복당 최소 2회 복사 = 대략 정점 4천만 개 급의 GC 생성 ,,,,,,
public static Vector3[] CalcaultateSmoothNormal(this Mesh mesh)
{
Dictionary<Vector3, List<int>> indicesDict = new(comparer: new Vector3EqualityComparer());
// 프로퍼티로 접근하면 접근할때마다 복사하기 때문에 로컬변수로 빼놔야함
var originVertices = mesh.vertices;
var originNormals = mesh.normals;
for (int i = 0; i < mesh.vertexCount; i++)
{
if (!indicesDict.ContainsKey(originVertices[i]))
indicesDict.Add(originVertices[i], new());
indicesDict[originVertices[i]].Add(i);
}
Vector3[] normals = new Vector3[originNormals.Length];
foreach (var indices in indicesDict.Values)
{
Vector3 normal = Vector3.zero;
foreach (var index in indices)
normal += originNormals[index];
normal /= indices.Count;
foreach (var index in indices)
normals[index] = normal;
}
return normals;
}
반복문을 돌기 전에 배열을 복사해놓고 반복문을 수행하도록 했다.
프로퍼티는 변수가 아니다... getter와 setter 모두 메서드이기 때문에 프로퍼티에 접근한다는건 곧 메서드를 실행한다는 걸 기억하자.
아니면 설명이라도 잘 읽자.