게임 프로그래밍 패턴 3장
경량
경량 패턴은 어떤 객체의 수가 너무 많을 때 가볍게 만들기 위해 사용한다.
공통적으로 쓰이는 데이터(고유 상태)는 공유하고, 개별적인 데이터(외부 상태)만 별도로 주어진다.
땅, 숲, 강이 섞인 넓은 지형 구현한다고 했을 때 각 지형 타입에 들어가는 Texture는 고유 상태이고, 각 지형의 서로 다른 position, rotation 값 등이 외부 상태다.
# TerrainType.cs
public class TerrainType
{
private Sprite _sprite;
private int _movementCost;
public Sprite Sprite => _sprite;
public int MovementCost => _movementCost;
public Terrain(Sprite sprite, int cost)
{
_sprite = sprite;
_movementCost = cost;
}
}
# Terrain.cs
public class Terrain
{
private TerrainType _terrainType;
private Vector2 _position;
public Terrain(TerrainType terrainType, Vector2 position)
{
_terrainType = terrainType;
_position = position;
}
}
# World.cs
각 속성별(water, ground, forest) TerrainType을 만들어두고 Terrain 객체를 생성할 때마다 공유한다.
각 속성별 객체 1, 2, 3은 서로 다르지만, 모두 동일한 속성의 TerrainType을 참조하고 있다.
각 속성별 데이터를 확인하기 위해 Terrain을 거칠 필요없이 TerrainType 객체에서 확인할 수 있고,
Terrain과 독립적으로 TerrainType을 수정할 수 있다.
using UnityEngine;
using UnityEngine.UI;
public class World : MonoBehaviour
{
public Canvas canvas;
public Sprite water, ground, forest;
private TerrainType _waterTerrainType;
private TerrainType _groundTerrainType;
private TerrainType _forestTerrainType;
void Start()
{
Initialize();
}
private void Initialize()
{
_waterTerrainType = new TerrainType(water, 20);
_groundTerrainType = new TerrainType(ground, 5);
_forestTerrainType = new TerrainType(forest, 10);
}
private void MakeWorld()
{
var water1 = new Terrain(_waterTerrainType, GetRandomPosition());
var water2 = new Terrain(_waterTerrainType, GetRandomPosition());
var water3 = new Terrain(_waterTerrainType, GetRandomPosition());
var ground1 = new Terrain(_groundTerrainType, GetRandomPosition());
var ground2 = new Terrain(_groundTerrainType, GetRandomPosition());
var ground3 = new Terrain(_groundTerrainType, GetRandomPosition());
var forest1 = new Terrain(_forestTerrainType, GetRandomPosition());
var forest2 = new Terrain(_forestTerrainType, GetRandomPosition());
var forest3 = new Terrain(_forestTerrainType, GetRandomPosition());
}
private TerrainType GetRandomTerrain()
{
var randomNum = Random.Range(0, 3);
if (randomNum == 0) return _waterTerrainType;
if (randomNum == 1) return _groundTerrainType;
return _forestTerrainType;
}
private Vector2 GetRandomPosition()
{
return new Vector2(Random.Range(0, 100), Random.Range(0, 100));
}
}
GPU 인스턴싱
경량패턴은 GPU 렌더링에 전달하는 데이터 양을 줄이기 위해 사용하는 디자인 패턴이다.
책에도 나와있듯이 요즘 그래픽 카드에서는 하드웨어에서 GPU Instancing, Instance Rendering이란 이름으로 해당 기능을 지원한다.
Unity에서는 코드 상 별도의 구현없이 GUI Instancing을 간단하게 적용할 수 있다.
https://docs.unity3d.com/kr/2018.4/Manual/GPUInstancing.html
참고
1) https://www.reddit.com/r/Unity3D/comments/4t3z8a/does_unitys_prefabs_implement_the_flyweight/
2) https://answers.unity.com/questions/1176171/implementing-flyweight-patterns.html
'Design Pattern' 카테고리의 다른 글
프로토타입 (Prototype) (0) | 2020.07.19 |
---|---|
관찰자 (Observer) (0) | 2020.07.05 |
명령 (Command) (0) | 2020.06.18 |