레트로의 유니티 게임 프로그래밍 에센스 - 5.2

Cosmos·2023년 4월 3일
0

학습 매체 : 책

책이름 : 레트로의 유니티 게임 프로그래밍 에센스

저자 : 이제민


본 내용은 해당 강의 내용을 공부하면서 정리한 글입니다.


5.2 C# 클래스 만들기


  • c#에서 클래스와 오브젝트가 어떻게 동작하는지 확인해보자. 동물(Animal) 클래스를 만들고 그것을 사용하여 동물 오브젝트들이 모여 있는 동물원을 만들자.


5.2.1 Animal 클래스 만들기

  • 동물원을 만들기 위해서는 동물 오브젝트를 만들어야 하며, 동물 오브젝트를 만들기 위해선 동물 클래스를 만들어야 한다.

  • Animal 클래스부터 만들자. 동물은 변수로 '이름'과 '울음소리'만 가지며, 메서드는 '울음소리를 내는 기능'만 가지고 있다고 하겠다.

  • 우리가 만들 Animal 클래스는 다음과 같이 구성된다.

  • C# 스크립트 Animal을 생성하고 코드를 작성하자.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Animal : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}
  • Animal 스크립트 내용을 수정하자.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Animal
{
    public string name;
    public string sound;

    public void PlaySound()
    {
        Debug.Log(name + " : " + sound);
    }
}
  • 완성된 Animal 클래스는 이름 name과 울음소리 sound 변수를 가지며, 울음소리를 재생하는 메서드 PlaySound()를 가진다.

  • Animal 클래스를 새로 정의했지만, 아직은 어떠한 일도 일어나지 않는다. Animal 클래스는 실체(오브젝트)가 아니기 때문이다.

MonoBehaviour를 상속하지 않은 경우

  • 이 장은 순수한 클래스의 역할만 살펴본다. 따라서 Animal 스크립트에서 MonoBehaviour를 지웠다. 그러면 Animal 클래스는 MonoBehaviour 클래스를 상속하지 않는다.
  • MonoBehaviour 클래스는 게임 오브젝트의 컴포넌트로서 필요한 기능들을 제공한다. 따라서 이 클래스를 상속하지 않은 Animal 클래스는 게임 오브젝트에 컴포넌트로 추가할 수 없다.

5.2.2 Animal 오브젝트 만들기

  • Animal 클래스를 기반으로 Animal 오브젝트를 만드는 Zoo 스크립트를 작성한다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Zoo : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}
  • Zoo 스크립트의 Start() 메서드에서 Animal 클래스를 바탕으로 해서 Tom이라는 동물을 생성하자.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Zoo : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Animal Tom = new Animal();
        Tom.name = "톰";
        Tom.sound = "냐옹!";

        Tom.PlaySound();
    }
}
  • 스크립트를 완성했다고 해서 코드가 동작하는 것은 아니라고 했다. 프로젝트 창의 Zoo 스크립트는 단순 텍스트일 뿐이다.

  • Zoo 스크립트를 게임 오브젝트에 컴포넌트로 추가해야 한다. 그렇게 해야 Zoo 스크립트는 게임상의 오브젝트가 되고 게임 속에서 동작한다.

  • 빈 게임 오브젝트를 생성하자.

  • Zoo 스크립트를 빈 게임 오브젝트로 드래그&드롭 하자.

  • 플레이 버튼을 눌러 씬을 시작하고 콘솔 창의 로그를 확인해보자.

  • 플레이 버튼을 눌러 플레이 모드를 해제하자.

5.2.3 Zoo 스크립트 분석하기

  • 먼저, 새로운 Animal 오브젝트를 생성하는 부분부터 보자.
Animal Tom = new Animal();
  • 앞의 코드는 새로운 Animal 오브젝트를 생성하고 그것을 Animal 타입의 변수 Tom에 할당한다. 여기서 new 연산자를 자세히 살펴보자.
new Animal();

new 연산자는 클래스로부터 인스턴스를 생성한다.

  • 어떤 클래스의 오브젝트를 새로 하나 생성한다. 여기서는 새로운 Animal 오브젝트를 생성했다. new 연산자 뒤에는 실행할 클래스의 생성자가 나온다.

Animal 메서드는 Animal 클래스의 생성자다.

  • 생성자의 이름은 클래스의 이름과 같다. ( C++과 동일 ) 생성자는 오브젝트를 생성할 때 실행되며, 오브젝트가 생성될 때 어떻게 초기화할지 정의하기 위해 사용하는 특수한 메서드이다.
  • 클래스를 정의할 때 생성자를 따로 만들지 않아도 기본 생성자암시적으로 생성된다. ( C++과 동일 ) 우리가 사용한 Animal() 생성자가 Animal 클래스의 기본 생성자다.

  • Animal() 기본 생성자는 초기화에 필요한 별다른 입력을 받지 않는다.

  • 생성자에서 초기화에 필요한 입력을 받는 경우는 6장 Vector3 타입을 처음 사용할 때 보게 될 것이다. 지금은 생성자를 새로운 오브젝트를 생성할 때 실행하는 특수한 메서드라는 정도만 이해하면 된다.

  • 정리하면, new Animal();은 '새로운 Animal 오브젝트(인스턴스)를 탄생시켜라!'라고 하는 명령이다.

  • 그다음 생성한 Animal 오브젝트를 Animal 타입의 변수 tom에 할당했다.

Animal Tom = new Animal();
  • 이제 Tom은 방금 생성한 Animal 오브젝트를 가리키게 된다. 생성된 오브젝트는 변수로 name과 sound를 가진다. tom에 할당된 Animal 오브젝트의 name과 sound의 값을 변경했다.
Tom.name = "톰";
Tom.sound = "냐옹!";
  • 오브젝트 내부의 변수나 메서드를 멤버라고 부른다. 멤버는 점( . ) 연산자로 접근할 수 있다.

  • 같은 원리로 Tom에 할당된 Animal 오브젝트의 PlaySound() 메서드를 점 연산자로 접근하고 실행했다.

Tom.PlaySound();

MonoBehaviour는 new를 사용하지 않는다.

  • 유니티에서 작성하는 대부분의 스크립트는 MonoBehaviour 클래스를 상속한다. 그런데 MonoBehaviour를 상속한 클래스는 new로 오브젝트를 생성할 수 없다.
  • MonoBehaviour를 상속한 클래스는 드래그&드롭 등으로 스크립트를 게임 오브젝트에 컴포넌트로 추가하는 방법으로만 오브젝트로 만들 수 있다.
  • MonoBehaviour를 상속한 클래스는 컴포넌트로 동작하며, 컴포넌트는 게임 오브젝트의 부품으로만 존재할 수 있다. 또한 컴포넌트는 게임 오브젝트에 추가될 때 컴포넌트로서 필요한 초기화 과정을 거친다.
  • new 연산자로 MonoBehaviour를 상속한 클래스를 오브젝트로 생성하면 필요한 초기화 과정과 게임 오브젝트에 추가되는 과정을 전부 생략하고 즉시 오브젝트가 생성된다. 따라서 생성된 오브젝트가 정상적으로 동작하지 않는다.

5.2.4 멤버와 접근 제한자

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Animal
{
    public string name;
    public string sound;

    public void PlaySound()
    {
        Debug.Log(name + " : " + sound);
    }
}
  • 클래스의 멤버

    어떤 클래스에 속하며, 해당 클래스의 데이터와 행위를 표현하는 요소를 멤버라고 한다. 즉, 변수 namesound 그리고 PlaySound( ) 메서드가 Animal의 멤버이다.

  • 클래스의 필드

    클래스의 멤버 중에서 변수를 필드라고 부른다. 변수 name과 sound가 필드이다. 때때로 클래스의 멤버 변수를 특별히 강조할 때 필드라고 표기한다.

접근 제한자

기본적으로 클래스의 멤버들은 외부에서 보이지 않도록 감추어져 있다. 하지만 원한다면 접근 제한자를 사용해 선택적으로 멤버의 공개 여부를 결정할 수 있다.

접근 제한자는 클래스 멤버의 공개 여부를 정하는 키워드다. 다음 세 가지 접근 제한자가 가장 자주 사용된다. ( protected는 16장에서 처음 사용 )

1. public : 클래스 외부에서 멤버에 접근 가능

2. private : 클래스 내부에서만 멤버에 접근 가능

3. protected : 클래스 내부와 파생 클래스에서만 멤버에 접근 가능

public은 멤버를 외부에서 접근 가능하게 공개하는 키워드이다. 클래스 외부에서 어떤 멤버에 접근을 허용하려면 멤버 앞에 public 키워드를 명시해야 한다.

private는 멤버를 외부에서 접근할 수 없도록 감추는 키워드이다. private가 기본값이다. 그러므로 멤버에 어떠한 접근 제한자도 명시하지 않으면 암묵적으로 private가 적용된다.

  • 예를 들어, Animal 클래스의 name은 public, sound는 private로 선언했다고 가정하자.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Animal
{
    public string name;
    private string sound;

    public void PlaySound()
    {
        Debug.Log(name + " : " + sound);
    }
}
  • 이렇게 되면 Zoo 스크립트에서 Animal 타입인 Tom을 다룰 때 Tom.name은 접근 가능하고 Tom.sound는 접근 불가능하다. 따라서 Tom.name = "톰";은 정상적으로 실행되고 Tom.sound = "냐옹!";은 에러가 발생한다.

  • 결론적으로 Zoo 스크립트에서 Tom.name, Tom.sound, Tom.PlaySound( )를 모두 접근하고 사용할 수 있었던 이유는 Animal 클래스에서 이들을 public으로 선언했기 때문이다.

다음 강의에서 계속~

profile
게임 개발을 목적으로 공부하고 있는 대학생입니다.

0개의 댓글