Quick Comparison
flyweight는 여러 instance가 같은 변하지 않는 definition을 참조하고, instance마다 달라지는 state는 따로 갖게 하는 구조입니다. Unity에서는 ScriptableObject·shared mesh·shared material이 후보지만, shared material이나 asset을 runtime 중 바꾸면 그 reference를 쓰는 모든 renderer·instance 또는 Project asset에 영향이 갈 수 있습니다.
| 데이터 | 둘 위치 | runtime 변경 |
|---|---|---|
| 적 종족의 base stat·icon·prefab | EnemyDefinition ScriptableObject | definition 자체는 읽기 전용으로 취급 |
| 현재 HP·target·cooldown | Enemy instance 또는 state component | actor 하나만 변경 |
| 공통 mesh·material | shared asset | 모든 사용처 영향 여부 확인 |
| renderer별 tint·damage flash | instance property 또는 pipeline-compatible 방식 | shared material을 직접 수정하지 않음 |
[CreateAssetMenu]
public sealed class EnemyDefinition : ScriptableObject
{
public int BaseHp;
public float MoveSpeed;
public GameObject Prefab;
}
public sealed class Enemy : MonoBehaviour
{
private int currentHp;
public void Initialize(EnemyDefinition definition) => currentHp = definition.BaseHp;
}공유와 instance state의 경계
shared data는 같은 archetype이 모두 읽어도 되는 definition입니다. instance state는 actor의 현재 위치, HP, target, cooldown, save progress처럼 개별 lifecycle을 가집니다. 둘을 분리하면 memory 중복을 줄일 뿐 아니라 designer가 definition을 관리하고 runtime system이 state를 관리하는 owner도 분명해집니다.
ScriptableObject는 GameObject에 붙이지 않는 asset data container이며 여러 prefab·object가 같은 asset을 참조할 수 있습니다. 따라서 play 중 EnemyDefinition.CurrentHp처럼 mutable field를 쓰면 같은 definition을 쓰는 instance의 state가 섞이고, editor에서 asset 변경이 남을 위험도 생깁니다. runtime save data와 per-player override는 별도 instance·save model에 둡니다.
material과 renderer의 공유 범위
sharedMaterial을 바꾸면 그 material asset을 공유하는 renderer가 함께 바뀔 수 있습니다. 반대로 renderer.material은 renderer별 material instance를 만들어 메모리와 batch 조건에 영향을 줄 수 있습니다. 색 하나를 instance마다 다르게 보이게 하려면 사용 중인 pipeline·shader의 instancing/SRP Batcher compatibility를 확인하고 MaterialPropertyBlock 또는 shader-supported instance data를 선택합니다.
이 선택은 “항상 property block” 같은 규칙이 아닙니다. shared material edit가 의도된 global theme change인지, object별 visual state인지, target pipeline에서 batching path가 유지되는지 Frame Debugger와 Profiler로 확인합니다.
도입과 검증
많은 instance가 같은 immutable data를 쓰거나 authoring source를 한 곳에서 관리해야 할 때 flyweight를 사용합니다. data가 작고 instance 수가 적으면 reference 계층만 늘릴 수 있습니다. shared definition 변경, instance spawn, save/load, renderer override를 함께 test해 “어떤 object까지 바뀌는가”를 확인합니다.
공유 data를 읽기 전용처럼 설계하지 않으면 memory 절감 패턴이 전역 mutable state가 됩니다. asset·shared material·runtime instance 중 어디를 바꾸는지 코드에서 드러내세요.
참고 링크
2 sources