본문 바로가기
프로그래밍/디자인패턴

유니티(C#)로 사용해 보는 디자인 패턴_ProtoType Pattern_프로토타입

by 리뷰하는 (게임)프로그래머_리프TV 2020. 5. 30.

 

프로토 타입

 

이번 예제에서는 몬스터의 리스폰을 프로토 타입으로 구현해 보았습니다.

 

 

Monster.cs

public class KMS_Monster
{
    public int health;
    public int speed;

    public int positionX;
    public int positionY;

    public virtual KMS_Monster Clone()
    {
        return new KMS_Monster();
    }
}

 가상 함수인 Clon이 존재

 

Demon.cs

public class KMS_Demon : KMS_Monster
{
    public KMS_Demon(int hp, int spd, int x, int y)
    {
        health = hp;
        speed = spd;
        positionX = x;
        positionY = y;
    }

    public override KMS_Monster Clone()
    {
        return new KMS_Demon(health, speed, positionX, positionY);
    }
}

Ghost.cs

public class KMS_Ghost : KMS_Monster
{
    public KMS_Ghost(int hp, int spd, int x, int y)
    {
        health = hp;
        speed = spd;
        positionX = x;
        positionY = y;
    }

    public override KMS_Monster Clone()
    {
        return new KMS_Ghost(health, speed, positionX, positionY);
    }
}

 

몬스터를 상속 받은 친구들은 Clone 함수를 각자 가지고 있어야 함

기본 생성자로 생성하는게 아니라

이미 가지고 있는 정보에 복사본을 만든다고 생각하면 된다

 

PrototypePattern.cs

public delegate KMS_Monster SpawnCallBack();

public class KMS_ProtoTypePattern
{
    SpawnCallBack spawnCallBack = null;

    // 처음 생성자로 생성할 때 어떤 함수가 호출될지를 저장
    public KMS_ProtoTypePattern(SpawnCallBack callBack)
    {
        spawnCallBack = new SpawnCallBack(callBack);
    }

    public KMS_Monster SpawnMonster()
    {
        // 생성자때 입력한 함수 호출
        return spawnCallBack();
    }
}

 

실제 사용 할 때 ProtoTypePattern에 스폰 지역을 선택

코드를 쓰고나니 뭔가 이상해 지긴했는데

 

중요한 부분은 하단 코드에서 여기라고 생각 

baseGhost.Add(baseGhost[0].Clone());

본인이 본인의 클론을 들고 동일한 값으로 만들어 주는 부분인데

굉장히 제한적인 패턴이라고 생각함

 

 

Manager.cs

using System.Collections.Generic;
using UnityEngine;

public class KMS_GameManager : MonoBehaviour
{
    // 프로토 타입 패턴으로 스폰 생성
    KMS_ProtoTypePattern spawnMonster;
    KMS_ProtoTypePattern spawnMonster2;

    // 각각의 몬스터를 저장할 컨테이너
    List<KMS_Monster> baseGhost = new List<KMS_Monster>();
    List<KMS_Monster> baseDemon = new List<KMS_Monster>();

    void Start()
    {
        // 콜백 메시지를 등록
        spawnMonster = new KMS_ProtoTypePattern(spawnGhost);
        spawnMonster2 = new KMS_ProtoTypePattern(spawnDemon);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {
            // spawnGhost 함수가 호출 되서 기본 Ghost를 하나 생성
            var monster = spawnMonster.SpawnMonster();
            // 해당 부분을 저장한다
            baseGhost.Add(monster);
            Debug.Log("Create Ghost");
        }
        else if (Input.GetKeyDown(KeyCode.B))
        {
            if (baseGhost.Count > 0)
            {
                // 이 부분이 복사 만들어 놓은 첫번째(순서는 중요치 않음)의 클론 생성해서 다시 보관
                baseGhost.Add(baseGhost[0].Clone());
                Debug.Log("Create clone Ghost");
            }
        }
        else if (Input.GetKeyDown(KeyCode.C))
        {
            // spawnDemon 함수가 호출되서 Demon하나 생성
            baseDemon.Add(spawnMonster2.SpawnMonster());
            Debug.Log("Create Demon");
        }
        else if (Input.GetKeyDown(KeyCode.D))
        {
            if (baseDemon.Count > 0)
            {
                // 클론 생성해서 저장
                baseDemon.Add(baseDemon[0].Clone());
                Debug.Log("Create clone Demon");
            }
        }
        else if (Input.GetKeyDown(KeyCode.E))
        {
            // 지금까지 만든 데이터 출력
            for (int i = 0; i < baseGhost.Count; ++i)
            {
                Debug.Log(baseGhost[i] + " " + i);
            }
        }
        else if (Input.GetKeyDown(KeyCode.F))
        {
            // 지금까지 만든 데이터 출력
            for (int i = 0; i < baseDemon.Count; ++i)
            {
                Debug.Log(baseDemon[i] + " " + i);
            }
        }
    }

    public KMS_Monster spawnGhost()
    {
        return new KMS_Ghost(10, 10, 10, 10);
    }

    public KMS_Monster spawnDemon()
    {
        return new KMS_Demon(20, 20, 20, 20);
    }
}