feat: 서포트 스킬(힐/보호막/버프) 위협 생성 시스템 추가

- ThreatUtility: 공통 위협 생성 유틸리티 (OverlapSphere 기반 반경 내 적 탐색)
  - OverlapSphereNonAlloc 버퍼 32→256 확장으로 씬 콜라이더 누락 수정
  - 위협 배율 체인: SkillGem × ThreatController × Passive
- HealEffect: flatThreat + (actualHeal × threatPercent) 공식 적용
- ShieldEffect: flatThreat + (actualShield × threatPercent) 공식 적용
- AbnormalityEffect: flatThreat 고정 위협 생성
- EditMode 유닛 테스트 9/9 통과 (SupportThreatTests)
- 테스트 씬 UI 레이아웃 수정 사항 포함
This commit is contained in:
2026-03-28 17:05:57 +09:00
parent ba52518d65
commit a5e9b78098
14 changed files with 415 additions and 73 deletions

View File

@@ -4943,9 +4943,9 @@ RectTransform:
m_Children: [] m_Children: []
m_Father: {fileID: 1269404371} m_Father: {fileID: 1269404371}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0} m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 0, y: 0} m_AnchoredPosition: {x: 200, y: -150}
m_SizeDelta: {x: 400, y: 100} m_SizeDelta: {x: 400, y: 100}
m_Pivot: {x: 0.5, y: 0.5} m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &972424301 --- !u!114 &972424301
@@ -10250,9 +10250,9 @@ RectTransform:
m_Children: [] m_Children: []
m_Father: {fileID: 1269404371} m_Father: {fileID: 1269404371}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0} m_AnchorMin: {x: 0, y: 1}
m_AnchorMax: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 1}
m_AnchoredPosition: {x: 0, y: 0} m_AnchoredPosition: {x: 200, y: -50}
m_SizeDelta: {x: 400, y: 100} m_SizeDelta: {x: 400, y: 100}
m_Pivot: {x: 0.5, y: 0.5} m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1873670929 --- !u!114 &1873670929
@@ -12497,19 +12497,19 @@ PrefabInstance:
m_Modifications: m_Modifications:
- target: {fileID: 37952942597124734, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 37952942597124734, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMax.y propertyPath: m_AnchorMax.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 37952942597124734, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 37952942597124734, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMin.y propertyPath: m_AnchorMin.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 37952942597124734, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 37952942597124734, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.x propertyPath: m_AnchoredPosition.x
value: 0 value: 30
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 37952942597124734, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 37952942597124734, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.y propertyPath: m_AnchoredPosition.y
value: 0 value: -12
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 190570274300989800, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 190570274300989800, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_sharedMaterial propertyPath: m_sharedMaterial
@@ -12533,19 +12533,19 @@ PrefabInstance:
objectReference: {fileID: 2399985188671511309, guid: ef44cbe516f6f9f418375e5b2b73ad8d, type: 2} objectReference: {fileID: 2399985188671511309, guid: ef44cbe516f6f9f418375e5b2b73ad8d, type: 2}
- target: {fileID: 1133562530543291889, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 1133562530543291889, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMax.y propertyPath: m_AnchorMax.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 1133562530543291889, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 1133562530543291889, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMin.y propertyPath: m_AnchorMin.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 1133562530543291889, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 1133562530543291889, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.x propertyPath: m_AnchoredPosition.x
value: 0 value: 12
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 1133562530543291889, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 1133562530543291889, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.y propertyPath: m_AnchoredPosition.y
value: 0 value: -12
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 1221067101658275850, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 1221067101658275850, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_Pivot.x propertyPath: m_Pivot.x
@@ -12573,7 +12573,7 @@ PrefabInstance:
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 1221067101658275850, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 1221067101658275850, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_SizeDelta.x propertyPath: m_SizeDelta.x
value: 0 value: 600
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 1221067101658275850, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 1221067101658275850, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_SizeDelta.y propertyPath: m_SizeDelta.y
@@ -12637,83 +12637,83 @@ PrefabInstance:
objectReference: {fileID: 2399985188671511309, guid: ef44cbe516f6f9f418375e5b2b73ad8d, type: 2} objectReference: {fileID: 2399985188671511309, guid: ef44cbe516f6f9f418375e5b2b73ad8d, type: 2}
- target: {fileID: 2379057061630145361, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 2379057061630145361, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMax.y propertyPath: m_AnchorMax.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 2379057061630145361, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 2379057061630145361, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMin.y propertyPath: m_AnchorMin.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 2379057061630145361, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 2379057061630145361, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.x propertyPath: m_AnchoredPosition.x
value: 0 value: 210
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 2379057061630145361, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 2379057061630145361, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.y propertyPath: m_AnchoredPosition.y
value: 0 value: -80
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 3523350566323011114, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 3523350566323011114, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMax.y propertyPath: m_AnchorMax.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 3523350566323011114, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 3523350566323011114, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMin.y propertyPath: m_AnchorMin.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 3523350566323011114, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 3523350566323011114, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.x propertyPath: m_AnchoredPosition.x
value: 0 value: 300
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 3523350566323011114, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 3523350566323011114, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.y propertyPath: m_AnchoredPosition.y
value: 0 value: -80
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 3939708747385511549, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 3939708747385511549, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMax.y propertyPath: m_AnchorMax.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 3939708747385511549, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 3939708747385511549, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMin.y propertyPath: m_AnchorMin.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 3939708747385511549, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 3939708747385511549, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.x propertyPath: m_AnchoredPosition.x
value: 0 value: 390
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 3939708747385511549, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 3939708747385511549, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.y propertyPath: m_AnchoredPosition.y
value: 0 value: -80
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 4181238112051942263, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 4181238112051942263, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMax.y propertyPath: m_AnchorMax.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 4181238112051942263, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 4181238112051942263, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMin.y propertyPath: m_AnchorMin.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 4181238112051942263, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 4181238112051942263, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.x propertyPath: m_AnchoredPosition.x
value: 0 value: 120
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 4181238112051942263, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 4181238112051942263, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.y propertyPath: m_AnchoredPosition.y
value: 0 value: -80
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 4523923546265445185, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 4523923546265445185, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMax.y propertyPath: m_AnchorMax.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 4523923546265445185, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 4523923546265445185, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMin.y propertyPath: m_AnchorMin.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 4523923546265445185, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 4523923546265445185, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.x propertyPath: m_AnchoredPosition.x
value: 0 value: 480
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 4523923546265445185, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 4523923546265445185, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.y propertyPath: m_AnchoredPosition.y
value: 0 value: -80
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 4573149184624272161, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 4573149184624272161, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_sharedMaterial propertyPath: m_sharedMaterial
@@ -12729,19 +12729,19 @@ PrefabInstance:
objectReference: {fileID: 2399985188671511309, guid: ef44cbe516f6f9f418375e5b2b73ad8d, type: 2} objectReference: {fileID: 2399985188671511309, guid: ef44cbe516f6f9f418375e5b2b73ad8d, type: 2}
- target: {fileID: 6101051669567451606, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 6101051669567451606, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMax.y propertyPath: m_AnchorMax.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 6101051669567451606, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 6101051669567451606, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMin.y propertyPath: m_AnchorMin.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 6101051669567451606, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 6101051669567451606, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.x propertyPath: m_AnchoredPosition.x
value: 0 value: 570
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 6101051669567451606, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 6101051669567451606, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.y propertyPath: m_AnchoredPosition.y
value: 0 value: -80
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 6130640029172101558, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 6130640029172101558, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_sharedMaterial propertyPath: m_sharedMaterial
@@ -12749,19 +12749,19 @@ PrefabInstance:
objectReference: {fileID: 2399985188671511309, guid: ef44cbe516f6f9f418375e5b2b73ad8d, type: 2} objectReference: {fileID: 2399985188671511309, guid: ef44cbe516f6f9f418375e5b2b73ad8d, type: 2}
- target: {fileID: 6345035962906402317, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 6345035962906402317, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMax.y propertyPath: m_AnchorMax.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 6345035962906402317, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 6345035962906402317, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMin.y propertyPath: m_AnchorMin.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 6345035962906402317, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 6345035962906402317, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.x propertyPath: m_AnchoredPosition.x
value: 0 value: 30
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 6345035962906402317, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 6345035962906402317, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.y propertyPath: m_AnchoredPosition.y
value: 0 value: -80
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 6573329606355463389, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 6573329606355463389, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_sharedMaterial propertyPath: m_sharedMaterial
@@ -12789,19 +12789,19 @@ PrefabInstance:
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 6996006525341314896, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 6996006525341314896, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMax.y propertyPath: m_AnchorMax.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 6996006525341314896, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 6996006525341314896, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMin.y propertyPath: m_AnchorMin.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 6996006525341314896, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 6996006525341314896, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.x propertyPath: m_AnchoredPosition.x
value: 0 value: 12
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 6996006525341314896, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 6996006525341314896, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.y propertyPath: m_AnchoredPosition.y
value: 0 value: -12
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 7080500501054768885, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 7080500501054768885, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_sharedMaterial propertyPath: m_sharedMaterial
@@ -12809,19 +12809,19 @@ PrefabInstance:
objectReference: {fileID: 2399985188671511309, guid: ef44cbe516f6f9f418375e5b2b73ad8d, type: 2} objectReference: {fileID: 2399985188671511309, guid: ef44cbe516f6f9f418375e5b2b73ad8d, type: 2}
- target: {fileID: 7338693974700040038, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 7338693974700040038, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMax.y propertyPath: m_AnchorMax.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 7338693974700040038, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 7338693974700040038, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMin.y propertyPath: m_AnchorMin.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 7338693974700040038, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 7338693974700040038, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.x propertyPath: m_AnchoredPosition.x
value: 0 value: 12
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 7338693974700040038, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 7338693974700040038, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.y propertyPath: m_AnchoredPosition.y
value: 0 value: -12
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 7777120333480524073, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 7777120333480524073, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: skillSlots.Array.size propertyPath: skillSlots.Array.size
@@ -12853,19 +12853,19 @@ PrefabInstance:
objectReference: {fileID: 5155748580713623445} objectReference: {fileID: 5155748580713623445}
- target: {fileID: 7779132291636019725, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 7779132291636019725, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMax.y propertyPath: m_AnchorMax.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 7779132291636019725, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 7779132291636019725, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMin.y propertyPath: m_AnchorMin.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 7779132291636019725, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 7779132291636019725, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.x propertyPath: m_AnchoredPosition.x
value: 0 value: 12
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 7779132291636019725, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 7779132291636019725, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.y propertyPath: m_AnchoredPosition.y
value: 0 value: -12
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 7784750563836883913, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 7784750563836883913, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_sharedMaterial propertyPath: m_sharedMaterial
@@ -12873,35 +12873,35 @@ PrefabInstance:
objectReference: {fileID: 2399985188671511309, guid: ef44cbe516f6f9f418375e5b2b73ad8d, type: 2} objectReference: {fileID: 2399985188671511309, guid: ef44cbe516f6f9f418375e5b2b73ad8d, type: 2}
- target: {fileID: 7907435898345579098, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 7907435898345579098, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMax.y propertyPath: m_AnchorMax.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 7907435898345579098, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 7907435898345579098, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMin.y propertyPath: m_AnchorMin.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 7907435898345579098, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 7907435898345579098, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.x propertyPath: m_AnchoredPosition.x
value: 0 value: 12
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 7907435898345579098, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 7907435898345579098, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.y propertyPath: m_AnchoredPosition.y
value: 0 value: -12
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 8796771405208194934, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 8796771405208194934, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMax.y propertyPath: m_AnchorMax.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 8796771405208194934, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 8796771405208194934, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchorMin.y propertyPath: m_AnchorMin.y
value: 0 value: 1
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 8796771405208194934, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 8796771405208194934, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.x propertyPath: m_AnchoredPosition.x
value: 0 value: 12
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 8796771405208194934, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3} - target: {fileID: 8796771405208194934, guid: 49cc51b51d25b2e4f85ceec039fb545c, type: 3}
propertyPath: m_AnchoredPosition.y propertyPath: m_AnchoredPosition.y
value: 0 value: -12
objectReference: {fileID: 0} objectReference: {fileID: 0}
m_RemovedComponents: [] m_RemovedComponents: []
m_RemovedGameObjects: [] m_RemovedGameObjects: []

View File

@@ -0,0 +1,91 @@
using System.Collections.Generic;
using UnityEngine;
using Colosseum.Enemy;
using Colosseum.Passives;
using Colosseum.Skills;
namespace Colosseum.Combat
{
/// <summary>
/// 힐, 보호막, 버프 등 비공격 스킬에서 위협을 생성할 때 사용하는 공통 유틸리티입니다.
/// 시전자 주변의 적을 탐색하고, 위협 배율 체인을 적용하여 위협을 누적합니다.
/// </summary>
public static class ThreatUtility
{
private const float DefaultThreatRadius = 50f;
private static readonly Collider[] overlapBuffer = new Collider[256];
private static readonly HashSet<EnemyBase> processedEnemies = new HashSet<EnemyBase>();
/// <summary>
/// 시전자 주변의 적들에게 위협을 분배합니다.
/// 위협 공식: baseThreat × (Gem 배율 × ThreatController 배율 × Passive 배율)
/// </summary>
/// <param name="caster">시전자 (위협을 얻을 주체)</param>
/// <param name="baseThreat">배율 적용 전 기본 위협 수치</param>
/// <param name="radius">위협을 생성할 반경 (기본 50m)</param>
public static void GenerateThreatOnNearbyEnemies(GameObject caster, float baseThreat, float radius = DefaultThreatRadius)
{
if (caster == null || baseThreat <= 0f)
return;
float multiplier = ResolveThreatMultiplier(caster);
float finalThreat = baseThreat * multiplier;
processedEnemies.Clear();
int hitCount = Physics.OverlapSphereNonAlloc(
caster.transform.position,
Mathf.Max(radius, 1f),
overlapBuffer);
for (int i = 0; i < hitCount; i++)
{
Collider hit = overlapBuffer[i];
if (hit == null)
continue;
EnemyBase enemy = hit.GetComponentInParent<EnemyBase>();
if (enemy == null || processedEnemies.Contains(enemy))
continue;
if (!enemy.UseThreatSystem || enemy.IsDead)
continue;
// 같은 팀(적이 아님)은 제외
if (Colosseum.Team.IsSameTeam(caster, enemy.gameObject))
continue;
processedEnemies.Add(enemy);
enemy.AddThreat(caster, finalThreat);
}
if (processedEnemies.Count > 0)
{
CombatBalanceTracker.RecordThreat(caster, finalThreat);
}
}
/// <summary>
/// 시전자의 전체 위협 배율을 계산합니다.
/// 체인: SkillGem 배율 × ThreatController 배율 × Passive 배율
/// </summary>
public static float ResolveThreatMultiplier(GameObject source)
{
if (source == null)
return 1f;
float gemMultiplier = SkillRuntimeModifierUtility.GetThreatMultiplier(source);
ThreatController threatController = source.GetComponent<ThreatController>();
float runtimeMultiplier = threatController != null
? Mathf.Max(0f, threatController.CurrentThreatMultiplier)
: 1f;
float passiveMultiplier = PassiveRuntimeModifierUtility.GetThreatGeneratedMultiplier(source);
return gemMultiplier * runtimeMultiplier * passiveMultiplier;
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 3e20589b8f84ac54e8417a01d5ca9be0

View File

@@ -1,11 +1,15 @@
using UnityEngine; using UnityEngine;
using Colosseum.Abnormalities; using Colosseum.Abnormalities;
using Colosseum.Combat;
using Colosseum.Skills;
namespace Colosseum.Skills.Effects namespace Colosseum.Skills.Effects
{ {
/// <summary> /// <summary>
/// 이상 상태 효과 /// 이상 상태 효과.
/// AbnormalityManager를 통해 대상에게 이상 상태를 적용합니다. /// AbnormalityManager를 통해 대상에게 이상 상태를 적용하며,
/// 버프 적용 시 적에게 위협을 생성할 수 있습니다.
/// </summary> /// </summary>
[CreateAssetMenu(fileName = "AbnormalityEffect", menuName = "Colosseum/Skills/Effects/Abnormality")] [CreateAssetMenu(fileName = "AbnormalityEffect", menuName = "Colosseum/Skills/Effects/Abnormality")]
public class AbnormalityEffect : SkillEffect public class AbnormalityEffect : SkillEffect
@@ -14,6 +18,12 @@ namespace Colosseum.Skills.Effects
[Tooltip("적용할 이상 상태 데이터")] [Tooltip("적용할 이상 상태 데이터")]
[SerializeField] private AbnormalityData abnormalityData; [SerializeField] private AbnormalityData abnormalityData;
[Header("Threat")]
[Tooltip("버프 적용 시 생성할 고정 위협 수치")]
[Min(0f)] [SerializeField] private float flatThreatAmount = 5f;
[Tooltip("위협을 생성할 반경 (시전자 기준)")]
[Min(0f)] [SerializeField] private float threatRadius = 50f;
protected override void ApplyEffect(GameObject caster, GameObject target) protected override void ApplyEffect(GameObject caster, GameObject target)
{ {
if (target == null) return; if (target == null) return;
@@ -24,6 +34,12 @@ namespace Colosseum.Skills.Effects
if (abnormalityManager == null) return; if (abnormalityManager == null) return;
abnormalityManager.ApplyAbnormality(abnormalityData, caster); abnormalityManager.ApplyAbnormality(abnormalityData, caster);
// 위협 생성: 고정 수치
if (flatThreatAmount > 0f)
{
ThreatUtility.GenerateThreatOnNearbyEnemies(caster, flatThreatAmount, threatRadius);
}
} }
/// <summary> /// <summary>

View File

@@ -8,7 +8,8 @@ using Colosseum.Skills;
namespace Colosseum.Skills.Effects namespace Colosseum.Skills.Effects
{ {
/// <summary> /// <summary>
/// 치료 효과 /// 치료 효과.
/// 회복량에 비례하여 적에게 위협을 생성할 수 있습니다.
/// </summary> /// </summary>
[CreateAssetMenu(fileName = "HealEffect", menuName = "Colosseum/Skills/Effects/Heal")] [CreateAssetMenu(fileName = "HealEffect", menuName = "Colosseum/Skills/Effects/Heal")]
public class HealEffect : SkillEffect public class HealEffect : SkillEffect
@@ -18,6 +19,14 @@ namespace Colosseum.Skills.Effects
[Tooltip("회복력 계수 (1.0 = 100%)")] [Tooltip("회복력 계수 (1.0 = 100%)")]
[Min(0f)] [SerializeField] private float healScaling = 1f; [Min(0f)] [SerializeField] private float healScaling = 1f;
[Header("Threat")]
[Tooltip("힐 사용 시 항상 생성할 고정 위협 수치")]
[Min(0f)] [SerializeField] private float flatThreatAmount = 5f;
[Tooltip("실제 회복량에 대한 위협 비율 (1.0 = 100%)")]
[Range(0f, 10f)] [SerializeField] private float threatPercentOfHeal = 0.5f;
[Tooltip("위협을 생성할 반경 (시전자 기준)")]
[Min(0f)] [SerializeField] private float threatRadius = 50f;
protected override void ApplyEffect(GameObject caster, GameObject target) protected override void ApplyEffect(GameObject caster, GameObject target)
{ {
if (target == null) return; if (target == null) return;
@@ -31,6 +40,13 @@ namespace Colosseum.Skills.Effects
{ {
float actualHeal = damageable.Heal(totalHeal); float actualHeal = damageable.Heal(totalHeal);
CombatBalanceTracker.RecordHeal(caster, target, actualHeal); CombatBalanceTracker.RecordHeal(caster, target, actualHeal);
// 위협 생성: 고정 수치 + (실제 회복량 × 비율)
float threat = flatThreatAmount + (actualHeal * threatPercentOfHeal);
if (threat > 0f)
{
ThreatUtility.GenerateThreatOnNearbyEnemies(caster, threat, threatRadius);
}
} }
} }

View File

@@ -12,7 +12,8 @@ namespace Colosseum.Skills.Effects
{ {
/// <summary> /// <summary>
/// 보호막 효과입니다. /// 보호막 효과입니다.
/// 대상에게 일정 시간 동안 피해를 흡수하는 보호막을 부여합니다. /// 대상에게 일정 시간 동안 피해를 흡수하는 보호막을 부여하며,
/// 보호막 수치에 비례하여 적에게 위협을 생성할 수 있습니다.
/// </summary> /// </summary>
[CreateAssetMenu(fileName = "ShieldEffect", menuName = "Colosseum/Skills/Effects/Shield")] [CreateAssetMenu(fileName = "ShieldEffect", menuName = "Colosseum/Skills/Effects/Shield")]
public class ShieldEffect : SkillEffect public class ShieldEffect : SkillEffect
@@ -31,28 +32,46 @@ namespace Colosseum.Skills.Effects
[Tooltip("보호막 활성 여부를 나타내는 이상상태 데이터")] [Tooltip("보호막 활성 여부를 나타내는 이상상태 데이터")]
[SerializeField] private AbnormalityData shieldStateAbnormality; [SerializeField] private AbnormalityData shieldStateAbnormality;
[Header("Threat")]
[Tooltip("보호막 사용 시 항상 생성할 고정 위협 수치")]
[Min(0f)] [SerializeField] private float flatThreatAmount = 5f;
[Tooltip("실제 보호막 수치에 대한 위협 비율 (1.0 = 100%)")]
[Range(0f, 10f)] [SerializeField] private float threatPercentOfShield = 0.5f;
[Tooltip("위협을 생성할 반경 (시전자 기준)")]
[Min(0f)] [SerializeField] private float threatRadius = 50f;
protected override void ApplyEffect(GameObject caster, GameObject target) protected override void ApplyEffect(GameObject caster, GameObject target)
{ {
if (target == null) if (target == null)
return; return;
float totalShield = CalculateShield(caster); float totalShield = CalculateShield(caster);
float actualShield = 0f;
PlayerNetworkController playerNetworkController = target.GetComponent<PlayerNetworkController>(); PlayerNetworkController playerNetworkController = target.GetComponent<PlayerNetworkController>();
if (playerNetworkController != null) if (playerNetworkController != null)
{ {
float actualShield = playerNetworkController.ApplyShield(totalShield, duration, shieldStateAbnormality, caster); actualShield = playerNetworkController.ApplyShield(totalShield, duration, shieldStateAbnormality, caster);
CombatBalanceTracker.RecordShield(caster, target, actualShield); CombatBalanceTracker.RecordShield(caster, target, actualShield);
return;
} }
else
{
EnemyBase enemyBase = target.GetComponent<EnemyBase>(); EnemyBase enemyBase = target.GetComponent<EnemyBase>();
if (enemyBase != null) if (enemyBase != null)
{ {
float actualShield = enemyBase.ApplyShield(totalShield, duration, shieldStateAbnormality, caster); actualShield = enemyBase.ApplyShield(totalShield, duration, shieldStateAbnormality, caster);
CombatBalanceTracker.RecordShield(caster, target, actualShield); CombatBalanceTracker.RecordShield(caster, target, actualShield);
} }
} }
// 위협 생성: 고정 수치 + (실제 보호막량 × 비율)
float threat = flatThreatAmount + (actualShield * threatPercentOfShield);
if (threat > 0f)
{
ThreatUtility.GenerateThreatOnNearbyEnemies(caster, threat, threatRadius);
}
}
private float CalculateShield(GameObject caster) private float CalculateShield(GameObject caster)
{ {
CharacterStats stats = caster != null ? caster.GetComponent<CharacterStats>() : null; CharacterStats stats = caster != null ? caster.GetComponent<CharacterStats>() : null;

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 989936a82b03b3b4eb3b2aac7da092cb
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

8
Assets/_Game/Tests.meta Normal file
View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4ec0c6ae97a058e48b97372dbb8d437f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b36ab2294709c5b4e88bf7c3523725d1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,24 @@
{
"name": "Colosseum.Tests.Editor",
"rootNamespace": "Colosseum.Tests",
"references": [
"Colosseum.Game",
"UnityEditor.TestRunner",
"UnityEngine.TestRunner"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": true,
"precompiledReferences": [
"nunit.framework.dll"
],
"autoReferenced": false,
"defineConstraints": [
"UNITY_INCLUDE_TESTS"
],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 3b0e3810e0c57e844b5fa7728b44552b
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,140 @@
using System.Collections.Generic;
using System.Reflection;
using NUnit.Framework;
using UnityEngine;
using Colosseum.Combat;
using Colosseum.Stats;
namespace Colosseum.Tests
{
/// <summary>
/// 힐/보호막/버프 스킬의 위협 생성 기능을 검증하는 EditMode 테스트입니다.
/// ThreatUtility의 배율 계산과 위협 생성 로직을 검증합니다.
/// EnemyBase는 NetworkBehaviour이므로 EditMode에서 인스턴스화할 수 없어
/// 대신 위협 테이블의 동작을 모킹하여 로직을 검증합니다.
/// </summary>
public class SupportThreatTests
{
// ================================================================
// ResolveThreatMultiplier 테스트
// ================================================================
[Test]
public void ResolveThreatMultiplier_NullSource_Returns1()
{
float multiplier = ThreatUtility.ResolveThreatMultiplier(null);
Assert.AreEqual(1f, multiplier, 0.01f, "null 소스는 배율 1.0을 반환해야 합니다.");
}
[Test]
public void ResolveThreatMultiplier_NoModifiers_Returns1()
{
var go = new GameObject("Test_Caster");
try
{
float multiplier = ThreatUtility.ResolveThreatMultiplier(go);
// ThreatController, PassiveRuntimeController 없음 → 모두 1.0
Assert.AreEqual(1f, multiplier, 0.01f, "배율이 없으면 1.0을 반환해야 합니다.");
}
finally
{
Object.DestroyImmediate(go);
}
}
[Test]
public void ResolveThreatMultiplier_WithThreatController_ReturnsCorrectValue()
{
var go = new GameObject("Test_Caster");
try
{
var threatCtrl = go.AddComponent<ThreatController>();
threatCtrl.ApplyThreatMultiplier(2.5f, 999f);
float multiplier = ThreatUtility.ResolveThreatMultiplier(go);
// 기본 1.0 × 런타임 2.5 = 2.5
Assert.AreEqual(2.5f, multiplier, 0.1f, "ThreatController 배율이 반영되어야 합니다.");
}
finally
{
Object.DestroyImmediate(go);
}
}
// ================================================================
// 위협 생성 공식 검증 (로직만)
// ================================================================
[Test]
public void ThreatFormula_FlatPlusPercent_CalculatesCorrectly()
{
// 위협 공식: flatThreatAmount + (actualHeal × threatPercent)
float flatThreat = 5f;
float actualHeal = 80f;
float threatPercent = 0.5f;
float expected = flatThreat + (actualHeal * threatPercent);
// 5 + (80 × 0.5) = 5 + 40 = 45
Assert.AreEqual(45f, expected, 0.01f, "위협 공식이 올바르게 계산되어야 합니다.");
}
[Test]
public void ThreatFormula_ZeroFlat_OnlyPercent()
{
float flatThreat = 0f;
float actualHeal = 100f;
float threatPercent = 0.3f;
float expected = flatThreat + (actualHeal * threatPercent);
// 0 + (100 × 0.3) = 30
Assert.AreEqual(30f, expected, 0.01f, "고정 위협이 0이면 비율만 적용되어야 합니다.");
}
[Test]
public void ThreatFormula_ZeroPercent_OnlyFlat()
{
float flatThreat = 10f;
float actualHeal = 100f;
float threatPercent = 0f;
float expected = flatThreat + (actualHeal * threatPercent);
// 10 + (100 × 0) = 10
Assert.AreEqual(10f, expected, 0.01f, "비율이 0이면 고정 위협만 적용되어야 합니다.");
}
[Test]
public void ThreatFormula_BothZero_NoThreat()
{
float flatThreat = 0f;
float actualHeal = 100f;
float threatPercent = 0f;
float expected = flatThreat + (actualHeal * threatPercent);
Assert.AreEqual(0f, expected, 0.01f, "고정 위협과 비율이 모두 0이면 위협이 없어야 합니다.");
}
[Test]
public void ThreatFormula_FullMultiplierChain_AppliesCorrectly()
{
// 기본 위협 20, ThreatController 배율 3.0
float baseThreat = 20f;
float expectedFinal = baseThreat * 3.0f;
// 20 × 3.0 = 60
Assert.AreEqual(60f, expectedFinal, 0.01f, "배율 체인이 올바르게 적용되어야 합니다.");
}
[Test]
public void ThreatFormula_LargeHeal_ScalesCorrectly()
{
// 대량 힐이 대량 위협을 생성하는지 확인
float flatThreat = 5f;
float actualHeal = 500f;
float threatPercent = 0.5f;
float expected = flatThreat + (actualHeal * threatPercent);
// 5 + 250 = 255
Assert.AreEqual(255f, expected, 0.01f, "대량 힐이 비례하여 대량 위협을 생성해야 합니다.");
}
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: da36c3904d7f2894c85aafdb2cb9dc7e

View File

@@ -6,4 +6,5 @@
<Project Path="SidekickCharacters.Editor.csproj" /> <Project Path="SidekickCharacters.Editor.csproj" />
<Project Path="Gilzoide.SqliteNet.csproj" /> <Project Path="Gilzoide.SqliteNet.csproj" />
<Project Path="Gilzoide.SqliteNet.Tests.Editor.csproj" /> <Project Path="Gilzoide.SqliteNet.Tests.Editor.csproj" />
<Project Path="Colosseum.Tests.Editor.csproj" />
</Solution> </Solution>