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 모두 메서드이기 때문에 프로퍼티에 접근한다는건 곧 메서드를 실행한다는 걸 기억하자.
아니면 설명이라도 잘 읽자.