문제
필드 선택 모드에서는 매 프레임 세 개의 인디케이터가 각각 폴리곤 생성 + Sutherland-Hodgman 클리핑 + 메시 배열 재할당·재업로드를 처음부터 다시 수행한다. BuildCircleMesh(235행)는 new List<Vector2>(CircleSegments)(244행, 64세그먼트)를 할당하고, ClipPolygonToFieldInWorldSpace(389행)가 worldPolygon(392행)과 result(405행)를, ClipPolygonToAABB(417행)가 네 번의 ClipByEdge 각각에서 new List<Vector2>(input.Count)(468행)를 할당한다. 425/433/441/449행의 inside/intersect 람다는 min/max를 캡처하므로 호출마다 display class와 델리게이트까지 새로 만들어진다. 이후 Vector3[]/Color[]/int[]를 할당하고 mesh.vertices/triangles/colors에 대입하면서 배열 복사가 또 발생한다. BuildLineMesh(309행)도 같은 클리핑 경로를 탄다. 미리 할당된 캐시(circleVertices/circleTriangles/circleColors, EnsureCircleArrays 514행)가 존재하지만 어디에서도 호출되지 않는 죽은 코드다.
위치
client/Assets/Scripts/GameScene/SkillIndicatorShapeRenderer.cs:235
재현 / 영향
플레이어가 필드 선택 모드에 들어가 마우스를 움직이면, FieldSelector.Update가 IsFieldSelectMode()인 동안 프레임당 세 번 이 경로를 태운다(SetCircleWorldRadius → SetCircle, SetAimIndicator → SetCircle, UpdateSkillIndicator → Circle/LineSkillIndicator.SetIndicator). 렌더링되는 모든 프레임마다 List 약 10개, 클립 호출마다 클로저 display class와 델리게이트 4개, 인디케이터 3개분의 정점/삼각형/컬러 배열, 그리고 메시 재업로드 3회가 발생한다. 대략 프레임당 10-15KB 수준의 가비지가 조준·시전이라는 지연에 민감한 상호작용 구간에서 지속 생성되며, 싱글 스레드에 비세대 GC인 WebGL 타깃에서 프레임 페이싱을 악화시킨다.
수정 방향
클리핑 전 폴리곤과 정점/컬러/삼각형 배열을 인스턴스별로 캐시하고(EnsureCircleArrays가 원래 그 용도다), 반경/위치/회전이 실제로 바뀔 때만 다시 만든다. 메시 갱신은 mesh.SetVertices/SetTriangles/SetColors를 사용하고, ClipByEdge의 술어는 캡처 람다 대신 static 또는 캐시된 델리게이트로 바꾼다.
심각도: medium · 분류: performance
자동 코드 리뷰(멀티 에이전트 검증 통과)에서 발견됨.
문제
필드 선택 모드에서는 매 프레임 세 개의 인디케이터가 각각 폴리곤 생성 + Sutherland-Hodgman 클리핑 + 메시 배열 재할당·재업로드를 처음부터 다시 수행한다.
BuildCircleMesh(235행)는new List<Vector2>(CircleSegments)(244행, 64세그먼트)를 할당하고,ClipPolygonToFieldInWorldSpace(389행)가worldPolygon(392행)과result(405행)를,ClipPolygonToAABB(417행)가 네 번의ClipByEdge각각에서new List<Vector2>(input.Count)(468행)를 할당한다. 425/433/441/449행의 inside/intersect 람다는min/max를 캡처하므로 호출마다 display class와 델리게이트까지 새로 만들어진다. 이후Vector3[]/Color[]/int[]를 할당하고mesh.vertices/triangles/colors에 대입하면서 배열 복사가 또 발생한다.BuildLineMesh(309행)도 같은 클리핑 경로를 탄다. 미리 할당된 캐시(circleVertices/circleTriangles/circleColors,EnsureCircleArrays514행)가 존재하지만 어디에서도 호출되지 않는 죽은 코드다.위치
client/Assets/Scripts/GameScene/SkillIndicatorShapeRenderer.cs:235재현 / 영향
플레이어가 필드 선택 모드에 들어가 마우스를 움직이면,
FieldSelector.Update가IsFieldSelectMode()인 동안 프레임당 세 번 이 경로를 태운다(SetCircleWorldRadius→SetCircle,SetAimIndicator→SetCircle,UpdateSkillIndicator→Circle/LineSkillIndicator.SetIndicator). 렌더링되는 모든 프레임마다 List 약 10개, 클립 호출마다 클로저 display class와 델리게이트 4개, 인디케이터 3개분의 정점/삼각형/컬러 배열, 그리고 메시 재업로드 3회가 발생한다. 대략 프레임당 10-15KB 수준의 가비지가 조준·시전이라는 지연에 민감한 상호작용 구간에서 지속 생성되며, 싱글 스레드에 비세대 GC인 WebGL 타깃에서 프레임 페이싱을 악화시킨다.수정 방향
클리핑 전 폴리곤과 정점/컬러/삼각형 배열을 인스턴스별로 캐시하고(
EnsureCircleArrays가 원래 그 용도다), 반경/위치/회전이 실제로 바뀔 때만 다시 만든다. 메시 갱신은mesh.SetVertices/SetTriangles/SetColors를 사용하고,ClipByEdge의 술어는 캡처 람다 대신 static 또는 캐시된 델리게이트로 바꾼다.심각도: medium · 분류: performance
자동 코드 리뷰(멀티 에이전트 검증 통과)에서 발견됨.