레이블이 Unity Technology인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Unity Technology인 게시물을 표시합니다. 모든 게시물 표시

2014. 10. 13.

Gameobject.Find() 로 Inactive Object를 찾는 방법

유니티에서 Gameobject.Find(string name) 함수를 사용하면, 해당 name과 일치하는 오브젝트를 찾아줍니다. 무척 편리한 기능이지만, 활성화된 오브젝트만 찾아준다는 단점이 있습니다. 물론, 비활성화된 오브젝트까지 전부 검색하기엔 속도가 느려지기에 이런 기능이 적합하지만, 때로는 비활성화된 오브젝트를 포함하여 검색해야할 경우도 종종 나오게 됩니다.
이미 2007년부터 많은 외국인 개발자들이 Gameobject.Find(string name, bool active) 함수를 오버로딩해달라는 요청을 했지만, 7년이 지난 지금까지도 받아들여지지 않고 있습니다. 유니티 정책 방향과 맞지 않기 때문일텐데, 어떠한 이유 때문인지는 잘 모르겠네요. 비활성화된 오브젝트를 찾는 비용보다 타입별로 찾는 비용이 더 적게 든다고 생각한걸까요? 여하튼, 유니티에서 공시적인 API를 지원해주지 않는다면, 직접 만들어 쓰는건 당연한 이치! 이미 구글을 뒤져보면 많은 대체 방법들이 나와 있습니다.

제일 간단해보이는 방법으로는 GameObject.FindObjectWithTag("Tag name") 입니다. 구글링을 하면, 가장 먼저 나오는 방법일텐데 아쉽지만 이 함수는 유니티4 버전에 들어오면서 더 이상 inactive 오브젝트를 찾아주지 않습니다.

비활성화된 오브젝트를 찾는 방법은 결국 GameObject.FindObjectsOfTypeAll(Type type) 함수를 쓰셔야합니다. 이 함수는 비활성화된 오브젝트도 포함하여 찾아주지만, 해당 타입의 오브젝트를 모두 불러오기에 성능적인 문제가 발생할 가능성이 농후하기에 사용에 주의하셔야 합니다.

유니티 함수를 사용하지 않는 방법으로는 오브젝트는 활성화 시켜준 채, 렌더러쪽만 비활성화 시킨다던가, 오브젝트를 비활성화 시키기전에 미리 오브젝트를 변수에 담아 두거나, 처음부터 오브젝트를 참조하게 만들어주는 방식의 방법이 있습니다.

2014. 10. 5.

유니티에서 Auto Destroy Particle System 제작하기

유니티의 파티클은 화려하고 사용하기 쉬운 훌륭한 시스템이지만, 기본적으로 파티클이 끝나도 오브젝트가 여전히 게임상에 남아있어, 파티클이 끝나면 오브젝트를 지워주는 작업을 해줘야합니다.
화려한 파티클! 하지만, Destroy를 직접 해주지 않으면, 파티클 LifeTime이 끝나도 오브젝트가 계속 남아있다
유니티에서 제공하는 IsAlive 함수는, 파티클이 끝났는지 여부를 알려줍니다. 이것을 이용해 ParticleSystemAutoDestroy라는 스크립트를 만들고, 어떤 파티클을 만들던 이 스크립트만 추가해주면, 자동으로 파티클이 끝났을 때, 파티클 오브젝트도 사라지도록 만들어봅시다.
using UnityEngine;
using System.Collections;

public class ParticleSystemAutoDestroy : MonoBehaviour
{
  private ParticleSystem ps;

  void Start ()
  {
    ps = GetComponent ();
  }
 
  void Update ()
  {
    if (ps) {
      if (!ps.IsAlive ()) {
        Destroy (gameObject);
      }
    } 
  }
}
이제 어떤 파티클을 만들건 이 스크립트만 추가해주면, 파티클 LifeTime이 끝남과 동시에 파티클 오브젝트도 사라지게 됩니다.

2014. 10. 1.

유니티에서 Death Trigger 를 구현해보자

Death Trigger란 플레이어가 언제 죽는지 기점을 잡는 역할을 합니다. 2D 러닝 게임을 예로 들자면, 낭떠러지로 떨어지거나 장애물/적 등과 충돌했을때 Death Trigger가 발동 되어야합니다. 이 경우, Death Trigger의 구현 방법은 크게 두 가지로 나뉘어집니다.

첫 번째는 낭떠러지, 장애물, 적 등 충돌시 플레이어를 죽게 만드는 오브젝트에 Death Trigger를 구현하는 방법입니다. 위 그림과 같이 바닥에 DeathTrigger란 이름의 게임 오브젝트를 생성하고, Box 2d collider를 붙여 길게 늘어뜨린 후, Is Trigger를 체크해줍니다. 그리고, DeathTriggerScript를 만들어 DeathTrigger 오브젝트에 붙여줍니다.
using UnityEngine;
using System.Collections;

public class DeathTriggerScript : MonoBehaviour
{
  void OnTriggerEnter2D (Collider2D collidedObject)
  {
    collidedObject.SendMessage ("hitDeathTrigger");
  }
}
이렇게 구현하면, 이제 DeathTrigger 오브젝트의 붙인 Box 2d Collider에 무언가 충돌하는 순간 SendMessage 함수를 통해 충돌한 오브젝트에 hitDeathTrigger 함수가 호출됩니다(잘 이해가 안가시면 SendMessage 함수의 API를 참조하세요). 이제 플레이어의 collider가 붙어있는 오브젝트에 적당한 스크립트 공간을 찾아서 hitDeathTrigger 함수를 구현해 주면 됩니다. 저는 hitDeathTrigger 함수에 플레이어가 죽는 상태로 바뀌도록 구현하였습니다.

두 번째 방법은 첫 번째 방법과 반대로 플레이어쪽에서 부딪치는 오브젝트를 체크하는 방식입니다. 먼저 DeathTrigger 오브젝트를 첫 번째 방법처럼 Box 2d collider를 붙여 길게 늘어뜨리고, Is Trigger를 체크합니다. 스크립트는 붙이지 않으며, 대신 Tag에 DeathTrigger라는 태그를 선언해줍니다. collider가 붙어있는 플레이어 오브젝트에 적당한 스크립트 공간을 찾아서 아래와 같이 onTriggerEnter2D 함수를 구현합니다(플레이어의 collider에도 IsTrigger를 체크해야합니다).
void OnTriggerEnter2D (Collider2D collidedObject)
{
 switch (collidedObject.tag) {
 case "DeathTrigger":
  // Player hit the death trigger - kill 'em!
  // 여기에 플레이어가 죽도록 구현!
  break;
 }
}

첫 번째 방법은 DeathTrigger 오브젝트 마다 부딪치는 수 많은 오브젝트의 경우의 수를 생각해서 구현을 해야함으로 비용이 많이 드는 작업입니다. 반면 두 번째 방법은 DeathTrigger 오브젝트들에 태그를 붙여주고, 플레이어와 적 유닛 정도에만 OnTriggerEnter2D를 구현해주면 끝나는 일이니 비용이 비교적 적게 듭니다. 이러한 이유로  Death Trigger 구현에는 일반적으로 두 번째 방법을 더 선호합니다.