본문 바로가기

[내배캠] 본 캠프 개발 학습/매일매일 쓰는 TIL

11월 13일 수요일 본 캠프 개발 일지 | 오브젝트의 조작과 스크립트와의 연결

📌

 

 숙련 주차 강의의 늪에서 벗어나 환기를 위해 특강 정리를 하고자 한다!

학습 내용 


1. 오브젝트와 스크립트의 관계
2. 다른 오브젝트를 참조하는 방법 
3. 관련한 유용한 지식 


# 기초 

1. 오브젝트와 스크립트의 관계 

 게임 오브젝트에는 한 개 이상의 컴포넌트가 존재한다. 컴포넌트는 게임 오브젝트와 동작에 관한 기본 구성 요소로 모든 게임 오브젝트의 작동과 관련된 부품이다.   

 만약 게임 오브젝트에 스크립트를 추가했다면, 그 스크립트 역시 해당 오브젝트의 컴포넌트가 된다. 이때의 스크립트는 현재 오브젝트 자체를 참조하고 있기 때문에 기본 속성 데이터를 바로 접근할 수 있다. 

Class A 

void Start()
 {
     Debug.Log(gameObject.name); // 현재 오브젝트의 이름을 출력한다
     Debug.Log(gameObject.tag); // 현재 오브젝트의 태그를 출력한다
 }


  하지만 이름, 태그 등과 달리 Rigidbody, Collider, AudioSource 같은 다른 컴포넌트는 직접 접근할 수 없기 때문에 GetComponent로 불러와야 한다. 단, Transform은 특별히 모든 GameObject에 기본적으로 포함된 컴포넌트이기 때문에, GetComponent<Transform>()를 쓰지 않고도 바로 접근할 수 있다.

 

2. 다른 오브젝트를 참조하는 방법 

  그렇다면 스크립트에서 현재 오브젝트가 아닌 다른 오브젝트와 상호작용하는 방법은 무엇이 있을까?   


✅ Find 메서드 

 

오브젝트 A에 붙어있는 A 스크립트에서 오브젝트 B를 참조하려고 한다고 가정해보자. 

class A 
{
    public GameObject B;

    void Start()
    {
        cube = GameObject.Find("B");
        Debug.Log(cube.name);
    }

 

 현재 씬에서 특정 이름을 가진 오브젝트를 찾을 때 사용되는 Find 메서드를 활용하면 쉽게 B 오브젝트를 찾을 수 있다. 

cube = GameObject.FindTag("//B 오브젝트의 태그");

// 태그가 달린 오브젝트를 리스트로 불러온다.
GameObject[] cube = GameObject.FindGameObjectWithTag("//B 오브젝트의 태그");


상황에 따라 다양한 Find 메서드를 사용할 수도 있다. 그러나 
Find 메서드는 씬에 있는 모든 오브젝트를 검색하기 때문에 성능에 영향을 미칠 수 있어 최대한 사용을 피하는 게 좋다. 

 

✅ 직렬화를 통한 인스펙터에서의 참조 

 필드에 맴버 변수를 만들고 인스펙터에 오브젝트를 드롭 앤 드롭으로 연결해서 참조 관계를 형성할 수 있다. 

// 필드 

public gameObject B
[SerializeField] private GameObject B;

 

 여기서 B 오브젝트의 컴포넌트를 가져오려면 어떻게 해야할까? 


✅ Getcomponent<T> 

 위에서 잠깐 언급했듯이 오브젝트의 컴포넌트를 가져올 때 사용하는 메서드이다. Getcomponent<T>에서 <>안에는 가져올 컴포넌트의 타입을 찾는다. 만약 Collider 컴포넌트를 쓰려면 Getcomponent<Collider>로 사용할 수 있다. 

gameObject.GetComponent<Collider>


 그러나 이 경우 스크립트가 있는 현재 오브젝트의 콜라이더 컴포넌트를 가져오게 된다. 따라서 B 오브젝트의 컴포넌트를 가져오려면 B.GetComponet를 사용해야 한다. 

// 필드에서 변수 선언 
Collider b

// 컴포넌트 가져오기
b = B.GetComponent<Collider>();


   만약 B 오브젝트의 스크립트를 가져오고 싶을 때도 방법은 동일하다.

// 필드에서 변수 선언 
B 클래스 = b 클래스

// 컴포넌트 가져오기 
b 클래스 = B.GetComponent<Collider>();

 

 찾으려는 컴포넌트가 없다면 null을 반환하기 때문에 예외 처리를 해주는 게 좋다.  

Getcomponent<T>의 종류 
 

GetComponents<T>() : 현재 게임 오브젝트에서 타입 T의 모든 컴포넌트를 배열로 반환한다. 

GetComponentInChildren<T> (bool includeInactive = false) : 현재 게임 오브젝트의 자식들 중에서 타입 T의 컴포넌트를 찾는다. IncludeInactive가 false(기본값)인 경우, 활성화된 오브젝트에서만 컴포넌트를 찾고, true로 설정하면 비활성화된 오브젝트와 자식 오브젝트에서도 컴포넌트를 검색한다.

GetComponentsInChildren<T> (bool includeInactive = false) : 현재 게임 오브젝트의 자식들 중에서 타입 T의 컴포넌트를 찾아 배열로 반환한다. 매개변수는 위와 같은 역할이다. 

GetComponentInParent<T>() : 현재 게임 오브젝트와 그 부모들 중에서 타입 T의 컴포넌트를 찾는다. 

GetComponentsInParent<T> (bool includeInactive = false)  현재 게임 오브젝트와 그 부모들 중에서 타입 T의 컴포넌트를 배열로 반환한다. 

 

Getcomponent<T> 사용 시 유의할 점 

 

 최적화를 위해 GetComponent 메서드는 awake나 start에 한번만 초기화를 해두고, 변수로 사용하는 게 좋다.  또한 GetComponentInChildren 메서드는 계층 구조의 깊이에 따라 검색 시간이 더 많이 소요되기 때문에 찾고자 하는 컴포넌트를 계층 구조 상위에 배치하여 검색 시간을 줄이는 게 좋다. 

3. 관련된 유용한 지식 

✅ 오브젝트가 비활성화된 상태로 플레이 모드를 시작하면, 그 오브젝트에 연결된 스크립트가 실행되지 않는다. 또한, GameObject.Find를 사용해도 비활성화된 오브젝트는 찾을 수 없다.

 

 MonoBehavior

 Unity에서 제공하는 모든 스크립트가 상속되어 있는 클래스이다. Awake, Start, Update 등 대표적인 메서드들은 MonoBehavior가 있어야 사용이 가능하다. 스크립트는 비주얼 스튜디오에서 제공해주는 시스템이기 때문에  스크립트 파일 자체로는 사용이 불가능하고, GameObject의 Component로 등록을 해야 사용을 할 수 있다. 이와 마찬가지로 MonoBehavior을 상속받지 않는 클래스라면 Component로 등록이 불가능하다.


 

 델리게이트 특강을 이어서 보면 될 것 같다.