[유니티 기초]_3. MonoBehaviour

0

유니티 엔진

목록 보기
3/21

내용을 알아보기 전에

내용에 대해 알기 전에 일단 기초적인 new 키워드를 통해 인스턴스 하나를 생성해봅시다.

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

public class Player : MonoBehaviour
{
    void Start()
    {
        Managers mg = new Managers();	//단순히 인스턴스 생성만 하였다.
    }

    void Update()
    {
        
    }
}

스크립트를 플레이어에 붙여서 실행해 보겠습니다.

[경고]
'new' 키워드를 사용하여 MonoBehaviour를 생성하려고 합니다. 이것은 허용되지 않습니다.
MonoBehaviour는 AddComponent()를 통해서만 추가할 수 있습니다.
또는 스크립트가 ScriptableObject에서 상속하거나 기본 클래스를 전혀 상속하지 않을 수 있습니다.

그저 C#에서 하듯 인스턴스 하나 생성했을 뿐인데 MonoBehaviour를 상속받은 클래스의 인스턴스를 만들지 말아달라고 경고가 날아옵니다.😥
이 경고가 의미하는 바는 Managers클래스는 MonoBehaviour를 상속받았기 때문에 new를 통한 인스턴스 생성을 하지 말고 다른 방법(AddComponent())을 사용하라는 이야기입니다.

MonoBehaviour

우리가 C#을 공부할땐
C# 콘솔 프로젝트를 만들고 => 클래스를 작성하고 => 메인 함수에 클래스의 인스턴스를 생성하여 => 해당 인스턴스 안에 있는 멤버함수를 사용하는 방식으로 만들었습니다.

하지만 유니티에서는 컴포넌트로 만들 클래스에 MonoBehaviour를 상속하고 이렇게 만든 스크립트 컴포넌트를 게임오브젝트에 연결하여 작동시킵니다.

MonoBehaviour란?

MonoBehaviour는 기본 스크립트를 생성하면 기본적으로 상속되어 있는 클래스입니다.
기본적으로 상속되어있는만큼 유니티는 이 MonoBehaviour에 컴포넌트에 필요한 기본 기능을 담아서 제공합니다.
다시 말하자면 이 MonoBehaviour를 상속받아야만 컴포넌트로써의 기능을 쓸 수 있는 것입니다.

클래스는 MonoBehaviour를 상속받음으로써

  • 타 스크립트에서 new를 이용해 객체로 생성할 수 없습니다.
  • 스크립트가 컴포넌트로 기능하게 됩니다.
  • 유니티 이벤트 메시지를 감지,호출할 수 있게 됩니다.(다음 포스트에서 배움)

(참고로 MonoBehaviour는
Object => Component => Behavior => MonoBehaviour 순서로 부모 객체를 상속받았습니다.)

요약

  • new를 이용하여 인스턴스를 생성할 수 없는 MonoBehaviour를 상속받은 컴포넌트들은 어떻게 동작시킬까?
    => 컴포넌트를 게임오브젝트에 연결하여 작동시킨다.

  • 컴포넌트들은 외부의 간섭을 받지 않는 독립적인 부품들인데 외부에서 컴포넌트들이 수행할 기능을 어떻게 알아차릴 것인가?
    => 메시지를 브로드 캐스트 방식으로 전달하여 이벤트 함수를 동작시킨다.(다음 포스트에서 배움)

게임 오브젝트에 연결된 컴포넌트에 접근 하는 방법들

사실 처음으로 하려던 것은 그저 클래스의 인스턴스를 생성해서 써먹으려는 것인데 이야기가 길어졌습니다.
Player 객체를 생성하는것은 MonoBehaviour 때문에 불가능 하므로 플레이어 컴포넌트를 가져와야 합니다.
다음 방법들은 Player 게임오브젝트에 연결된 Player 스크립트 컴포넌트를 찾아오는 방법들입니다.

Object.FindObjectOfType()을 통해 이용한 방법:

  • Object.FindObjectOfType 은 에셋 (메시, 텍스처, 프리팹 등) 또는 비활성 오브젝트를 반환하지 않습니다.
  • 이 기능은 매우 느립니다. 매 프레임마다(업데이트 메소드 내에) 이 기능을 사용하지 않는 것이 좋습니다.
  • 대부분의 경우 싱글톤 패턴을 대신 사용할 수 있습니다.
public class FindObject : MonoBehaviour
{
    void Start()
    {
        Player player = FindObjectOfType<Player>();
  		player.Attack();
    }
}

GameObject.Find()를 이용한 방법:

  • 오브젝트의 이름을 통해서 오브젝트에 접근후 오브젝트 안에있는 클래스에 접근하는 방법입니다.
  • GameObject.Find 는 로드 시 다른 오브젝트에 대한 참조를 자동으로 연결하는 데 유용합니다.
  • 성능상의 이유로 매 프레임마다 이 기능을 사용하지 않는 것이 좋습니다.
  • 비활성 오브젝트를 반환하지 않습니다.
  • 오브젝트의 이름이 변경될경우 오류가 나타납니다.
  • 이름에 띄어쓰기도 신경써야 하므로 실수를 할수있어서 추천하지않습니다.
  • 참고) 자식 게임 오브젝트를 찾으려면 Transform.Find를 사용하는 것이 더 쉬운 경우가 많습니다.
public class FindObject : MonoBehaviour
{
    void Start()
	{
	    Player player = GameObject.Find("Player").GetComponent<Player>();
	    player.Attack();
	}
}

GameObject.FindWithTag()를 이용한 방법:

  • 태그(Tag)의 이름을 통해서 오브젝트에 접근후 오브젝트 안에있는 클래스에 접근하는 방법입니다.

    ▲ Player 오브젝트의 Tag를 Player로 지정한다.
public class FindObject : MonoBehaviour
{
    public GameObject player;

    void Start()
    {
        player = GameObject.FindWithTag("Player");
        player.GetComponent<Player>().Attack();
    }

}

인스펙터에서 직접연결하는 방법:

  • FindObject 컴포넌트에 player 오브젝트를 인스펙터를 통해 직접 Drag&Drop으로 명시해주는 방법입니다.
  • 오류를 범할 가능성이 낮고 이름을 변경하여도 유지되니 추천하는 방법입니다.

    ▲ FindObject에 Player 오브젝트를 연결한다.
public class FindObject : MonoBehaviour
{
    public GameObject player;

    void Start()
    {
        player.GetComponent<Player>().Attack();
    }
}

싱글톤을 사용하는 방법:

  • 클래스의 인스턴스를 static으로 선언하여 어디서든 접근이 가능하게 합니다.
  • 인스턴스 변수를 사용하여 어디서든 접근이 가능합니다.
  • 보통 게임상에 하나여야만 하는 클래스에 사용합니다 ex)매니저 클래스
  • (예제는 다음 포스트(싱글톤과 매니저)에서 배우는 내용을 잠깐 가져왔습니다.)
public class UIManager : Singleton<UIManager>	//싱글톤 상속
{
    void Start() { }
    void Update() { }

    public void Print() 
    {
        //ex)UI매니저에서 해야할 일
    }
}

▲ 플레이어 클래스에 인스턴스를 알아올수있도록 설정한다

public class Player : MonoBehaviour
{
    void Start() 
    {
        UIManager UM = UIManager.Instance;	
        UM.Print();
    }
}

0개의 댓글