Design Pattern

경량 (Flyweight)

coucou3 2020. 6. 24. 23:49
반응형

게임 프로그래밍 패턴 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

 

GPU 인스턴싱 - Unity 매뉴얼

GPU 인스턴싱을 사용하면 적은 수의 드로우 콜을 사용하여 동일한 메시의 여러 복제본을 한 번에 그리거나 렌더링할 수 있습니다. 씬에서 반복적으로 나타나는 건물, 나무, 풀 등의 오브젝트를 ��

docs.unity3d.com

 

 

 

 

참고

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