Prosto

유니티, 원하는 게임오브젝트 얻기 -1(GameObject.Find..) 본문

Programing/Unity 3D

유니티, 원하는 게임오브젝트 얻기 -1(GameObject.Find..)

Prosto 2016. 10. 12. 07:39

원하는 게임 오브젝트를 얻어오기 위해선 어떤 작업이 필요할까요?

 

특별히 원하는 대상을 찾고싶다면, 어떤 방법으로 찾을 수 있을까요?

 

 

 - 대상을 이름으로 찾고싶다면

GameObject.Find("이름");

 

이렇게 사용할 수 있고요..

 

 - 대상을 태그로 찾고싶다면

GameObject.FindWithTag("태그명");

혹은

GameObject.FindGameObjectWithTag("태그명");

 

이렇게 사용할 수 있습니다.

 

 

이와 관련된 내용의 예제 프로젝트를 만들어 보여드리겠습니다.

 

2D와 3D 모두 사용 방법은 동일합니다.

저는 주로 2D 작업을 하니 2D로 예제 프로젝트를 생성하겠습니다.

 

 

프로젝트가 생성된 화면이죠?

이제 하나씩 진행과정을 보시죠.

(직접 따라하면서 익혀보는 것도 좋을 것 같네요.)

 

 

Hierarchy 탭에 임시로 몬스터를 생성해줬습니다.

Monsters라는 EmptyObject 아래에

Monster(현재 체크 모양)들을 5개 추가해줬네요.

각각 이름은 Monster1, Monster2, Monster3, Monster4, Monster5 입니다.

 

 

그러면 이제 GameObject.Find 함수를 사용하기 위해 스크립트 작성을 해야겠죠?

 

ClickEvent라는 스크립트를 만들었습니다.

 

간단하게 작성해봅시다.

이렇게 작성이 됐습니다.

 

여기서 중요한 부분은

tempObj = GameObject.Find("Monster" + monsterNumber.ToString());

바로 이 부분이죠.

GameOjbect.Find("이름");이 사용 방법이었습니다.

여기서 이름 부분이 Monster + 번호로 이루어져있으니

현재 몬스터번호를 문자열로 바꿔줘 합쳐 사용했습니다.

하드 코딩보다는 이런식으로 작성해주면

라인 수도 줄고 보기에도 좋죠?

(위의 if문은 예외 부분을 위해 추가해줬습니다. 몬스터 번호는 1부터 5까지죠?)

 

결과적으로 이 소스는 몬스터번호에 맞는 몬스터를 이름으로 찾아서

해당 몬스터가 있다면(찾기에 성공해서 오브젝트를 얻음)

콘솔창에 Debug.Log를 이용하여 해당 오브젝트를 받았다고 알려주고,

몬스터를 못 찾았다면 몬스터를 얻는데 실패했다고 알려주고,

처음부터 없는 몬스터라면 잘못된 몬스터 번호임을 알려주는 소스라고 보시면 됩니다.

 

 

 아래에 소스 붙입니다. 필요하면 복사해서 알맞게 바꿔 사용해보세요.

_M#]

 

 

그럼 만들어진 스크립트를 추가해줘야겠죠?

예제니 메인카메라에 추가해줬습니다.

 

 

자 ClickEvent의 MonsterNumber가 0인 경우는

콘솔창에 "잘못된 몬스터 번호입니다."라고

출력되는 것을 확인할 수 있습니다.

(예외로 처리된 거죠?)

 

(콘솔창에 빨간 느낌표(!)로 나오게 하는 것은 Debug.LogError()를 이용하면 그렇습니다.)

[소스에 Debug.LogError로 사용됐죠?]

 

그리고 이번에는 ClickEvent의 MonsterNumber가 1인 경우는

콘솔창에 "성공적으로 Monster1 오브젝트를 받았습니다."라고

출력되는 것을 확인할 수 있습니다.

(제대로 Find.GameObject를 통해서 얻어냈습니다.)

 

 

그리고 ClickEvent의 MonsterNumber를 2로 바꾼 경우는

콘솔창에 "성공적으로 Monster2 오브젝트를 받았습니다."라고

출력되는 것을 확인할 수 있습니다.

(제대로 Find.GameObject를 통해서 얻어냈습니다.)

 

 

마지막으로 하나만 더 볼까요?

ClickEvent의 MonsterNumber가 5인 경우에는

콘솔창에 "성공적으로 Monster5 오브젝트를 받았습니다."라고

출력되는 것을 확인할 수 있습니다.

 

(범위 내의 몬스터가 Hierarchy 탭에 존재하니 모두 잘 받는 것을 확인할 수 있습니다.)

 

 

그럼 이번에는

태그를 이용하여 게임 오브젝트를 얻어볼까요?

 

먼저 태그를 추가해줘야겠죠?

 

Monster5 게임 오브젝트의 태그를 Monster로 변경해줍시다.

 

(Add Tag로 Monster를 추가해준 후 선택했습니다.)

 

 

아까와 달라진 부분이 하나밖에 없죠?

그래서 소스 제공은 없습니다.

(그래도 이 예제가 끝날 떄 쯤에 전체 소스를 제공할 때에는 들어가있습니다.)

 

GameObject.FindWithTag("Monster");를 이용했습니다.

(아까 얘기했지만 이건 GameObject.FindGameObjectWithTag("Monster");와 같습니다.)

 

 

이번 소스는 마우스 클릭이 발생했을 때 "Monster" 태그인 게임 오브젝트가 있다면

성공적으로 해당 오브젝트를 받았다고 알려줄 것이고,

없다면 얻는데 실패했다고 알려줄 것입니다.

 

(얻었다면 tempObj에는 null이 아닌 해당 게임 오브젝트가 들어갈 테니 말이죠.)

 

 

실행하고 테스트해보니

게임 화면 클릭 시 정상적으로

Monster5 게임 오브젝트를 얻은 것을 콘솔창을 통해 확인했습니다.

Tag를 이용하여 찾은 거죠.

 

 

그러면 아까 말했던 FindGameObjectWithTag 똑같은지 확인만 해볼까요?

tempObj = GameObject.FindGameObjectWithTag("Monster");

로 바꿔준 후 실행해봅시다.

 

 

어떤가요 아까와 같죠?

Tag를 이용하여 Monster5 게임 오브젝트를 받아냈고,

그 결과를 콘솔창에 알려줬습니다.

 

 

이렇게 GameObject.Find(string), GameObject.FindWithTag(string) [FindGameObjectWithTag(string)]

함수를 이용하여 원하는 게임오브젝트를 얻는 처리를 하는 방법에 대하여 알아봤습니다.

 

여기서 참고로 알려드리고 싶은 부분은

GameObject.Find(string)함수의 경우 꽤 성능을 많이 잡아먹습니다.

이 함수를 난발하는 것을 안 좋죠.

예를 들어 Update()에서 어떠한 처리를 하는데

다른 오브젝트를 참조하기 위해 Update 안에서 GameObject.Find(string)을 사용해뒀다.

이건 문제가 됩니다. (이런게 하나하나 모이다보면 가벼운 게임도 무거워지겠죠?)

 

제가 여기에서 Update()에 쓴 거는 클릭이 발생한 경우에만 찾도록 사용된 것이고

이걸 그냥 Update(){ ... GameObject.Find(string); ...} 이렇게 사용하지 않았습니다.

 

 

만약 참조를 지속적으로 해야하는 경우가 있다면

참조할 때마다 GameObject.Find로 찾지말고,

필요할 때 한번만 Find()함수를 이용하여 GameObject targetObject;와 같은 변수에 넣어주고

그 후부터는 targetObject.~~~와 같은 방식으로 사용하시는 게 적합합니다.

 

(그리고 사용이 끝난 경우는 targetObject = null; 같은 식으로 참조 해제도 해주시고요.)

 

(몬스터가 플레이어를 참조한다든지 하는 것은 처음 Awake에서 Player오브젝트를 찾아 가지고있으면 되겠죠?)

 

(사용된 전체 소스는 가장 밑에 있습니다!)

 

 

 

다음으로

'유니티, 원하는 게임오브젝트 얻기? -2'와 관련된 내용은 무엇인지,

 어떤 경우에 필요한지에 대한 부분을 간단하게 집고 넘어가겠습니다.

(아래까지 보 필요하신 분은 다음 내용도 확인해보시면 좋을 것 같습니다.)

 

이 GameObject.Find / FindWithTag(FindGameObjectWithTag)함수의 경우는

게임 오브젝트가 활성화(Active값-true) 상태인 오브젝트만 찾을 수 있습니다.

 

비활성화(Active값-false) 상태인 오브젝트는 찾을 수가 없죠.

 

이어서 이미지와 함께 확인해볼까요?

 

아까 태그로 찾는 소스 그대로인 상태에서

Monster5를 활성화 시켰습니다.

 

그리고 화면을 클릭해보니 어떤까요?

 

해당 태그의 몬스터를 얻는데 실패했다고 콘솔 탭에 나오고있죠?

 

바로 이렇게 비활성화된 몬스터를 찾지 못 한다는 점이 있습니다.

 

 

그럼 GameObject.Find()의 경우는 어떨까요? 잘 될까요?

아까 작성했던 부분을 함수로 빼뒀습니다.

FindObjectWithName()이라는 함수로요.

이걸 그대로 마우스 클릭 시 불리도록 하면 되겠죠?

 

 

실제로 Monster1을 비활성화 시킨 후 화면을 클릭해보니

1번 몬스터를 얻는데 실패했다는 문구가 콘솔창에 나왔습니다.

 

역시 GameObject.Find()도

비활성화된 오브젝트에 대해서는 얻어오질 못 한다는 것을 확인할 수 있네요.

 

 

아예 상위(부모) 오브젝ㅌ인 Monsters를 끈(비활성화 시킨) 경우에도 마찬가지입니다.

3번 몬스터를 찾지 못 했죠?

 

다음 글에서는 이런 문제에 대한 해결방안을 찾아보고 그런 경우에

사용하게 되는 transform.FindChild 혹은 transform.GetChild에 대하여 알아보겠습니다.

 

 

 

작업하다 보면 비활성화(Active값-false) 상태인 오브젝트도 찾고 싶을 때가 있습니다.

이때는 어떤 방법으로 해야할까요?

 

그에 대한 내용은 아래의 글에서 확인해볼 수 있습니다.

'유니티, 원하는 게임오브젝트 얻기? -2(transform.FindChild..)'

 

 

마지막으로...

 

 

도움이 됐다면 좋겠습니다.

 

궁금한 점 있으시면 댓글이나 따로 메일로 질문하시면 시간되는 대로 답변드리겠습니다. ( 연락 )

Comments