본문 바로가기
프로그래밍/게임 개발

프로그래밍 「 게임 개발 편」순수 C# 클래스(POCO) 작성, 인스턴스화 및 초기화

by grapedoukan 2023. 7. 4.
728x90

순수 C# 클래스(POCO/Plain Old C# Objects)는 MonoBehaviour를 상속하지 않습니다. POCO를 프로그램의 청사진으로 생각하십시오.

POCO를 만들 때의 큰 이점은 POCO를 초기화하는 방법으로 생성자 (또는 여러 생성자)를 만들 수 있다는 것입니다. MonoBehaviour에서 상속할 때 그렇게 할 수 있지만 예측할 수 없는 일이 발생할 수 있으며 권장하지 않습니다.

또한 게임에 100개 이상의 무기가 있다고 가정해 보겠습니다. 모든 무기에는 무기를 정의하는 공유 변수가 있습니다. 각 무기가 무엇인지 정의하기 위해 100개의 C# 스크립트를 작성하는 대신 원하는 만큼 무기를 만들고 싶은 만큼 복사할 수 있는 하나의 POCO를 작성하는 것이 훨씬 더 합리적입니다.

POCO의 예는 다음과 같습니다.

public class Weapon {
    public string name;
    public float fireRate;
    public int ammoCount;
}

그런 다음 다른 클래스에서 Weapon POCO의 핸들을 만들고 인스턴스화하고 machineGun의 값을 초기화할 수 있습니다.

기관총처럼 초기화해야 하는 무기가 여러 개 있다면 어떨까요? 이것은 매우 지루한 과정이됩니다. POCO의 한 가지 이점은 생성자라는 것이 있고 정보를 전달하여 객체를 초기화할 수 있다는 것입니다. 생성자는 POCO 자체에 속하며 POCO와 동일한 이름으로 명명됩니다.

public class Weapon {
    public string name;
    public float fireRate;
    public int ammoCount;

    public Weapon(string name, float fireRate, int ammoCount) {
        //initialize here
    }
}

일반적으로 MonoBehaviour 클래스와 함께 생성자를 사용하고 싶지 않습니다. 이제 여기서 할 수 있는 일은 이 웨폰의 인스턴스를 전달된 데이터로 초기화하는 것입니다.

public class Weapon {
    public string name;
    public float fireRate;
    public int ammoCount;

    public Weapon(string name, float fireRate, int ammoCount) {
        //initialize here
        this.name = name;
        this.fireRate = fireRate;
        this.ammoCount = ammoCount;      
    }
}

예를 들어, Weapon Class의 맨 위에 있는 public string name은 생성자에 전달되는 name으로 설정됩니다. Weapon의 모든 변수에 대해서도 동일한 작업이 수행됩니다.

이러한 파라미터를 전달할 수 있으면 훨씬 더 모듈화되고 원할 때마다 무기 POCO 인스턴스를 더 쉽게 만들 수 있습니다.

매개 변수를 전달하지 않거나 전달할 매개 변수의 다른 조합을 만들기 위해 여러 생성자를 만들 수 있습니다.

이제 플레이어 클래스로 돌아가서, machineGun 초기화 방법을 변경해 보겠습니다.

public class Player : MonoBehaviour {
    //other code
    
    private Weapon machineGun;

    void Start() {
        /* OLD CODE
        machineGun = new Weapon;
        machineGun.name = "Machine Gun";
        machineGun.fireRate = 0.1f;
        machineGun.ammoCount = 100;
        */

        machineGun = new Weapon("Machine Gun", 0.1f, 100);
    }

이제 machineGun을 모두 한 줄로 인스턴스화 및 초기화하고 생성자를 통해 매개 변수를 전달합니다.

 

POCO 인스턴스화 및 초기화를 단순화하는 또 다른 방법은 사용자 지정 클래스를 초기화하려는 클래스 내에 메서드를 만드는 것입니다. POCO에 생성자를 원하지 않는 경우입니다. 거의 동일하게 작동합니다.

public class Player : MonoBehaviour {
    //other code
    
    private Weapon machineGun;

    void Start() {
        //machineGun = new Weapon("Machine Gun", 0.1f, 100);

        machineGun = CreateWeapon("Machine Gun", 0.1f, 100);
    }

    private Weapon CreateWeapon(string name, float fireRate, int ammoCount) {
        Weapon weapon = new Weapon(name, fireRate, ammoCount);
        return weapon;
    }

개인적으로, 나는 POCO와 관련된 모든 것을 그 클래스에 유지하기 위해 POCO에 생성자를 만들 것입니다.

 

MonoBehaviour를 상속하지 않기 때문에 POCO의 변수가 공개되어 있더라도 변수가 인스펙터에 표시되지 않습니다.

데이터를 직렬화하면 Unity가 인스펙터에서 오브젝트를 읽을 수 있습니다. 객체 또는 POCO를 직렬화하려면 해당 클래스로 이동하고 클래스 위에 아래와 같은 속성을 추가 할 수 있습니다.

[System.Serializable] //attribute
public class Weapon {
    public string name;
    public float fireRate;
    public int ammoCount;

    public Weapon(string name, float fireRate, int ammoCount) {
        //initialize here
        this.name = name;
        this.fireRate = fireRate;
        this.ammoCount = ammoCount;      
    }
}

[Serializable] 클래스, 구조체 및 기타 형식을 표시합니다. 인스턴스 필드를 표시합니다.[SerializeField]

MonoBehaviour는 컴포넌트로 추가할 때 Unity 에디터에서 인스턴스화되거나, 여기서 T는 MonoBehaviour 타입으로 인스턴스화됩니다. 일반 클래스는 MonoBehaviour 아래에 그룹화되지 않는 한 인스펙터에 표시되지 않습니다.gameObject.AddComponent<T>()

정규 클래스(POCO)는 . 이는 Unity에 이 데이터 타입을 인스펙터에 표시하거나 JSON으로 저장/로드할 수 있음을 알려줍니다(인스펙터와 동일한 직렬화 규칙 사용). MonoBehaviours에는 엔진에서 생성해야 하는 C++ 백킹 사이드가 있습니다. Awake 및 OnEnable을 사용하면 이 모든 설정이 완료되고 바로 사용할 수 있습니다.[Serializable](using System;)JsonUtility

그러나 생성자는 C #에서 너무 빨리 발생하여 준비가되지 않습니다.
C# MonoBehaviour 스크립트가 오브젝트 컨스트럭션(MonoBehaviour 클래스에서 생성자 생성) 중에 Unity 코드를 실행하기 시작하면 좋지 않은 일이 발생하므로 MonoBehaviours(MB)에 사용하지 않는 것이 좋습니다. POCO에는 생성자가 필요하며, 그렇지 않으면 생성자를 만들 수 없습니다.

728x90