본문 바로가기
유니티 게임 개발

[유니티 강좌] 2D RPG 게임 만들기 - 16 / 스테이터스 클래스 정리하기

by 호일이 2021. 5. 13.

처음에는 정말 기초만 포스팅하고 끝내려 했는데 예상치 못하게 많이 진행이 되면서 점점 코드가 복잡해지고 있습니다.

스크립트 파일을 나누지 않으면 점점 개발이 힘들어지니 이번 포스팅에서 약간이나마 깔끔하게 정리하는 시간을 가지려고 합니다. 

 

한 분이 질문 주셨는데요.

 

"여러 적을 만들 때 일일이 스크립트를 만들어서 스테이터스를 설정하는 건 비효율적이고 귀찮은 작업인 것 같다. 이 문제를 해결할 방법이 있는지 궁금하다"

 

라고 질문해주셨습니다.

 

질문한 분의 고민은 기존에 스테이터스 객체가 정의되지 않아서 발생했던 문제로 이번 포스팅을 따라해보시면 해결하실 수 있을 겁니다.

 

먼저 설명을 드리기 전에 말씀드리고 싶은 것은 제가 설명드릴 방법이 실무에서 쓰이는 정석이 아닐 수 있다는 점, 그리고 제가 프로그래밍을 공부하면서 얻는 지식을 나름대로 정리한 것이라고 말씀드리겠습니다.

 

지금까지 스테이터스를 사용한 방식

소드맨

각각의 변수를 public으로 선언해 에디터에서 스테이터스를 설정했었습니다.

 

Enemy

각각의 스크립트에 스테이터스가 정의되어 있는 모습입니다.

 

Enemy의 스테이터스를 정하는 방법

Enemy마다 다른 스테이터스를 설정하려면 위의 함수를 통해 Enemy.cs에 적어야 합니다.

Enemy의 종류가 늘어날수록 스크립트의 길이가 늘어나게 되고, 복잡해지는 구조입니다.

 

처음에 이 방법을 선택한 이유는 직관적이기 때문입니다. 처음 코드를 보는 사람도 추측할 수 있도록 만들고 싶었는데, 계속 사용하기에는 무리가 있는 방법이었습니다.

 

새로운 방식

총 2개의 파일을 만들어서 정리했습니다.

 

1. UnitCode.cs

public enum UnitCode {
    swordman,
    enemy1
}

UnitCode를 설정하는 Enum 클래스입니다. 유닛을 구분하기 위해 만들었습니다.

 

enum에 대해 간단하게 설명하겠습니다.

변수를 ,(콤마)로 나열하면 각각 변수에 숫자가 자동으로 들어가게 됩니다.

위와 같이 쓰면

swordman = 0,

enemy1 = 1

이렇게 자동으로 설정됩니다.

enum도 클래스라서 별도의 클래스 정의 없이 사용 가능합니다.

 

2. Status.cs

public class Status
{
    public UnitCode unitCode { get; } // 바꿀 수 없게 get만
    public string name { get; set; }
    public int maxHp { get; set; }
    public int nowHp { get; set; }
    public int atkDmg { get; set; }
    public float atkSpeed { get; set; }
    public float moveSpeed { get; set; }
    public float atkRange { get; set; }
    public float fieldOfVision { get; set; }

    public Status()
    {
    }

    public Status(UnitCode unitCode, string name, int maxHp, int atkDmg, float atkSpeed, float moveSpeed, float atkRange, float fieldOfVision)
    {
        this.unitCode = unitCode;
        this.name = name;
        this.maxHp = maxHp;
        nowHp = maxHp;
        this.atkDmg = atkDmg;
        this.atkSpeed = atkSpeed;
        this.moveSpeed = moveSpeed;
        this.atkRange = atkRange;
        this.fieldOfVision = fieldOfVision;
    }

    public Status SetUnitStatus(UnitCode unitCode)
    {
        Status status = null;

        switch (unitCode)
        {
            case UnitCode.swordman:
                status = new Status(unitCode, "소드맨", 50, 10, 1f, 8f, 0, 0);
                break;
            case UnitCode.enemy1:
                status = new Status(unitCode, "Enemy1", 100, 10, 1.5f, 2f, 1.5f, 7f);
                break;
        }
        return status;
    }
}

 

스테이터스에 사용되는 변수들과 함수를 정의한 클래스입니다. 

저는 설명을 최대한 압축하기 위해 Player(소드맨)와 Enemy의 스테이터스를 통일해서 하나의 Status 클래스를 만들었지만, 둘이 나눠서 만들 수도 있습니다.

 

사용 방법

Sword_Man.cs

기존에 스테이터스를 설정했던 코드는 전부 지웁니다. 그리고 Status를 저장할 변수를 선언하고, SetUnitStatus 함수로 소드맨의 UnitCode를 이용해 Status를 불러옵니다.

 

Enemy.cs

여러 Enemy 종류가 있을 때 각각의 스테이터스를 다르게 해야 하니 public UnitCode로 에디터에서 바꿀 수 있게 했습니다.

 

에디터에서 본 화면입니다.

public으로 UnitCode를 선언해서 Enemy 종류에 맞게 스테이터스를 설정할 수 있습니다.

 

확실히 기존의 방법보다 스테이터스 설정이 훨씬 간단하게 바뀐 것 같습니다.

 

에러 수정 방법

기존의 스테이터스 설정 코드를 지우고 위와 같이 바꿨을 경우 다른 스크립트들에서 오류가 발생합니다.

일일이 스크립트를 열면서 수정하는 것보다 빨리 수정하는 방법을 알려드리겠습니다.

 

우선 저장하고 에디터로 돌아가 보면 여러 에러가 발생해 있습니다.

에러 메시지를 더블클릭하면 문제가 있는 스크립트로 이동하게 됩니다.

 

수정 전
수정 후

status를 추가해서 쓰고 저장 -> 에러 메시지 클릭 -> ...

이렇게 반복하시면 비교적 빠르게 수정이 가능합니다.

 

추가 설명

Status 클래스에서 get, set를 사용한 이유

Status 클래스에서 get, set를 사용해 변수를 정의했습니다.

프로퍼티를 사용하지 않고도 정의가 가능한데 굳이 사용한 이유는 unitCode를 변경하지 못하게 하려고도 있지만 통일성 때문이기도 합니다. 보통 C#으로 개발할 때 프로퍼티를 많이 사용하므로, 전체적인 코드의 통일성을 위해 사용했습니다.

 

반응형

댓글