ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [졸업작품] 턴제 게임을 만들자 #2.5 코딩노트(1)
    유니티3D/졸업작품 2023. 5. 2. 16:19

    이번 글에는 지난 개발일지 #2를 작성하면서 공부가 되었던 부분들을 정리해보려 한다.

    아마 이제 앞으로도 #3, #4, …를 작성하면서 #n.5 넘버링으로 코딩노트를 작성하게 될 것 같다.

    물론 공부가 된 코딩스킬을 곧이곧대로 적어놓진 않을거고, 내가 공부하여 깨달은 방식 그대로 적어놓을 것이기 때문에, 이 글 또한 튜토리얼로 써먹기엔 문제가 있을 것이다. 혹시 내가 잘못 공부했거나, 추가하고픈 내용이 있으면 댓글로 알려주길 바란다.

     

    1. System.Serializable, SerializeField

    아직은 개발을 이제 막 시작한 단계이고, 내 코딩 스킬도 아직 굉장히 어린 수준이어서, 조금 남발한 감이 있나 싶은 요소다. 하지만 그렇다고 안 쓸 수 없는 게, 이걸 쓰면 private 선언(기본적으로 유니티 C# 클래스 안에 있는 요소는 맨 앞에 어떤 범위지정자도 없으면 private로 자동으로 범위가 지정된다.)된 멤버변수라도, 인스펙터로 꺼내올 수 있다!

    인스펙터에 나타난 private 맴버변수들. 인스펙터에 올라왔으니, private 맴버변수라도 인스펙터에서 값을 수정할 수 있다!

    원래 인스펙터에 어떤 맴버변수를 띄우려면, 그 멤버변수가 public으로 선언되어야 한다.

    하지만 public으로 선언하면, 다른 클래스에서도 함부로 꺼내 쓸 수 있게 되어, 자칫 잘못하면 예상 못한 부분에서 값이 이상하게 바뀔 수 있다. 이럴 때 해당 멤버변수 바로 윗줄에 [SerializeField]를 선언하면, 해당 멤버변수를 private로 선언하면서 인스펙터에 띄울 수 있게 된다. [System.Serializable]는 이것의 클래스 버전이고.

    주의할 점은 [SerializeField] 바로 아랫줄에 있는 멤버변수만 인스펙터에 노출시킬 수 있다는 거다.

    위쪽 사진에서 한 줄에 연달아 선언된 hp, mp, def, atk, comp는 인스펙터에 노출되었지만, 그 아래 선언된 crit은 노출되지 않았다.

    2. Header, Range

    SerializeField로 온갖 것을 인스펙터로 노출시키다 보니, 인스펙터가 너무 길어지고, 좀 정리가 필요해졌다. 그래서 간단하게나마 인스펙터를 커스터마이징 하는 법을 구글링 하고, 이 두 가지를 써먹기로 했다.

    2.1. [Header()]

    인스펙터에 제목을 달아주는 요소다. 원하는 위치에 [Header("아무말")]를 넣어주면, 인스펙터에서 Bold체로 "아무말"이 출력된다.

    2.2. [Range(n, N)]

    멤버변수 선언 전에 집어넣는 요소다.

    n~N까지의 범위를 가진 슬라이더를 인스펙터에 표시한다.

    3. error CS0051

    Skill 클래스를 멤버 클래스로 갓 선언했을 때, 콘솔에 이런 에러들이 떴었다.

    구글링을 해보니 접근범위와 관련된 오류였다.

    여기까지 보았을 땐, 솔직히 잘 이해가 되지 않았다.

    아니, private 선언이 된 클래스를 가지고, 같은 private 멤버변수로 선언하는 건데, 왜 문제가 생기는 거지?

    하지만 콘솔은 자세히 읽어봐야 한다고. 영어가 싫고, 가독성이 절망적이어도 꼭 읽어보아야 한다고.

    자세히 읽어보니 문제는 이 부분이 아니었다. 콘솔에서 Assets\Script\CharacterBehavor.cs(141, 16)이라 적힌 부분이 보이는가? 이 부분이 에러가 난 부분이 어디인지 가리켜주는 것이다. 이를 해석해 보면, 141번 줄과 155, 163번 줄의 16번째 글자에서 에러가 났다는 뜻이란 걸 알 수 있다.

    문제의 141번, 155, 163번 줄

    알았다. Skill 클래스는 private 멤버 클래스다.

    외부 클래스가 아니고, CharacterBehavor클래스에 속해있는 맴버 클래스다.

    CharacterBehavor 클래스가 없으면 바깥에 따로 존재할 수 없는 클래스다. 게다가 private 맴버 클래스로 선언되었으니, 다른 CharacerBehavor 인스턴스에서 이 Skill 클래스에 접근할 수도 없는 것이다.

    그런데 그걸 외부에서 쓰라고 만들어놓은 메서드에 인수로 요구하고 있으니, 외부에서 볼 땐 없는 것이나 마찬가지인 것을 내놓으라고 왈가왈부 하는 꼴인 것이었다. 그러니 에러가 날 수밖에.

    이 에러를 해결하는 방법은 쉽다. 이 모든 문제의 중심인 Skill 클래스의 접근제한을 public으로 선언하면 된다.

    문         제                      해         결

    너무 쉽게 public으로 접근제한을 바꿔버리는 거 아니냐 할 수 있겠지만, Skill 클래스 자체가 외부로 불려 갈 일이 많은 클래스다.(UI만 생각하더라도, 스킬 목록을 만들기 위해 UI에서 주구장창 불러와 표시해야 한다.)

    그럼 멤버 클래스로 만들지 않고, 따로 다른 클래스로 빼라! 아예 Skill을 인수로 받지 않는 메서드를 새로 만들라! 할 수도 있다. 하지만 그런건 지금 내 실력이 아직 이수준이라는 핑계를 대고 넘어가도록 하겠다. 나중에 코딩 스킬이 더 늘면 스태틱 클래스로 만들든, 아예 다른 클래스로 빼든 후속 조치를 취할지도 모르지.

    4. 맴버 클래스 배열 선언하기

    나는 궁극기와 방어, 회피, 반격을 제외한 나머지 스킬은 배열로 묶어 관리하겠다고 했었다.

    마지막 노트는 이 배열을 만들며 겪은 시행착오다.

    C#의 배열은 C++의 배열과는 사뭇 다르다.

    크기 3의 int형 배열을 만든다면, int[] a = new int[3]; 으로 선언해야 한다.

    그래서 Skill 클래스의 배열을 위와 같이 Skill[] skills = new Skill[skillCNT];로 선언했다. (skillCNT는 int로, 위쪽에 선언)

    그랬더니..

    에러가 떴다.

    알아보니 배열의 크기를 상수가 아닌 변수로 설정했기 때문이었다.

    SkillCNT에 const를 붙여 상수취급 하게 하고, Awake에서 배열 속 각 원소에 새로운 Skill 클래스 공간을 할당해준다.

    이로써 인스펙터에서 문제 없이 스킬의 가짓수를 정하고, 스킬을 만들어낼 수 있게 되었다.

     

Designed by Tistory.