본문 바로가기
공부/유니티

유니티3D 공부(Part4) 유니티짱 터치하기, 레이(Raycast)와 충돌처리

by 라이티아 2024. 10. 1.

이번 글에서는 유니티짱을 터치해서 피드팩을 받는 예제를 제작해 볼것이다

 

기본 세팅들은 앞글에서 많이 다루었으니 스킵하겠다

 

유니티에서 Ray란, 화면에서 지정한 방항(x, y, z)으로 1자로 레이저를 발사해서 레이저(비유이다)가 닿는 물체를 찾는 방법중 하나이다

 

내 개인적 해석이니 정확한건 공식 문서를 찾기를 추천한다

 

일단 핵심은, 레이가 "충돌"을 해야한다. 즉, colider가 없으면 레이도 충돌체를 감지하지 못한다는 것이다

처음 레이를 사용할때 이것때문에 2-3일을 해맨 기억이 있다...

 

 

이런 기반 지식 하에 글을 보면 좋다

 

그래서 유니티짱에게 colider를 넣어준다

이렇게 colider 컴포넌트를 넣어주면 초록색 박스가 생기는데, 이게 충돌을 감지하는 영역을 표시해 주는것이다

 

이제 레이를 발사하는 코드를 작성해보자

 

public class Touch : MonoBehaviour
{
    Ray ray;
    RaycastHit hit;

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out hit, 100)) Debug.Log("hit");
        }
    }
}

코드를 해석하면

마우스 클릭시 레이를 카메라 위치에서 마우스 클릭 좌표에서 발사하고

만약 무언가와 충돌 되었을시 디버그를 콘솔에 띄우게 된다

 

이때 Physics.Raycast는 무언가와 충돌시 True를 나타내게 되며

ray가 충돌한 물체 정보를 hit에 담게된다. 100은 ray가 발사되는 최대 거리를 나타낸다

 

정상적으로 hit 디버그 로그를 확인할 수 있다

 

이제 마우스로 클릭시 효과음이 나오게 추가한다

이는 이전글에서 다루었으니 스킵한다

 

public class Touch : MonoBehaviour
{
    Ray ray;
    RaycastHit hit;

    public AudioClip [] voice = new AudioClip[2];
    private AudioSource audioSource;

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out hit, 100)) Debug.Log("hit");
        }
    }
}

추가적으로 애니메이션을 넣는다

애니메이터를 생성후

애니메이션을 넣어준다

 

기본적으로 있는 idle용 wait, 터치시 반응할 damaged이다

 

이를 transfer로 해도되고, 직접 play해도 된다

 

지금은 transfer로 해보겠다

transfer를 사용하기 위해서는 파라미터를 사용해야 한다

처리를 위해 bool값, Touch를 넣어주었다

그리고 이를 반영하는 transfer를 추가해준다

bool값에 따라 애니메이션을 전환하게 된다

 

이제 이를 스크립트에 반영한다

public class Touch : MonoBehaviour
{
    Ray ray;
    RaycastHit hit;

    public AudioClip [] voice = new AudioClip[2];
    private AudioSource audioSource;
    private Animator animator;

    void Start()
    {
        animator = GetComponent<Animator>();
        audioSource = GetComponent<AudioSource>();
    }

    void Update()
    {
        int a = Random.Range(0, 2);
        animator.SetBool("Touch", false);
        if (Input.GetMouseButtonDown(0))
        {
            ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out hit, 100))
            {
                Debug.Log("Hit");

                animator.SetBool("Touch", true);

                audioSource.clip = voice[a];
                audioSource.Play();
            }
        }
    }
}

클릭시 애니매이터의 Touch, bool값이 true가 되고, 이에따라 애니메이션이 재생되며 효과음이 난다

 

 

이제 여기에 충돌판정을 나누어서 처리해보자

 

겉으로 보기에는 유니티짱의 모델은 통짜 모델인것처럼 보이지만 사실 여러 파츠가 모여있는 것이다

이렇게 자세히 들여다 보면 세세하게 모여있다

여기에서 머리를 찾아서 따로 구분해 보려 한다

 

유니티짱의 머리 부분의 파츠이다

 

전체적으로 확인할때 핵심은, 머리가 따로 오브젝트로 처리되어 있다는 것이다

 

여기에 콜라이더를 추가한다

이렇게 따로 머리에 콜라이더를 넣을 수 있다

 

이런식으로 가슴도 따로 처리한다

이렇게 하면 이제 colider가 머리, 가슴에 따로 들어가있다

 

이제 이걸 ray로 구분할 방법을 만들어야 하는데, 이는 tag기능을 사용한다

이렇게, 가슴에 따로 "Breast"tag를 달아준다 이를 스크립트에서 가져와 검사하는 방식으로 처리한다

 

이제 애니메이션이 머리, 가슴으로 나누어 졌으니, 애니메이션을 1개 더 추가해준 뒤

 

    void Update()
    {
        animator.SetBool("Touch", false);
        animator.SetBool("TouchHead", false);

        GameObject hitObject;
        if (Input.GetMouseButtonDown(0))
        {
            ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out hit, 100))
            {
                Debug.Log("Hit");
                hitObject = hit.collider.gameObject;

                if (hitObject.gameObject.tag == "Head")
                {
                    animator.SetBool("TouchHead", true);
                    audioSource.clip = voice[0];
                }
                else if (hitObject.gameObject.tag == "Breast") 
                {
                    animator.SetBool("Touch", true);
                    audioSource.clip = voice[1];
                }
                audioSource.Play();
            }
        }
    }

ray가 collider와 충돌시 tag로 검사하여 따로 처리되도록 한다

클릭하는 위치에 따라 반응이 다른것을 확인할 수 있다