Unity

[Unity][방법] Object충돌_1(Collision) OnCollisionEnter, OnTriggerEnter, OverlapSphere(설정반경오브젝트 확인) 방법

usingsystem 2022. 10. 5. 13:41
728x90

OnCollisionEnter

OnCollisionEnter 보통 서든어택 같은 fps에서 사용할때 좋다. 총알이 맞은 후 행위

 1) 나한테 혹은 상대에게 RigidBody가 있어야한다(IsKinematic : off) 
 2) 나한테 Collider가 있어야한다(IsTrigger : off) 
 3) 상대한테 Collider가 있어야한다(IsTrigger : off) 

 

IsKinematic  - unity 물리엔진 사용유무

mass - 질량

 

public class TestCollision : MonoBehaviour
{
    //1) 나한테 혹은 상대에게 RigidBody가 있어야한다(IsKinematic : off) 
    //2) 나한테 Collider가 있어야한다(IsTrigger : off) 
    //3) 상대한테 Collider가 있어야한다(IsTrigger : off) 
    private void OnCollisionEnter(Collision collision)
    {
        Debug.Log("coll");   
    }
}

OnTriggerEnter 

OnTriggerEnter는 단순히 접촉을 했는지에 대해 이벤트를 발생할 때 좋다.(검이 닿았는지 안닿았는지, 투명한 오브젝트 범위안에 닿았을때 다른 던전으로 변경)

1) 둘 중 하나라도 Collider가 있으면 가능 
2) 둘 중 하나는 IsTrigger : On인 상태
3) 둘 중 하나는 RigidBody가 있어야한다.

 

public class TestCollision : MonoBehaviour
{
    //검이 닿았을지 안닿았을지, 투명한 오브젝트에 입장했을때 다른 던전으로 넘어가기
    //1) 둘 중 하나라도 Collider가 있으면 가능 
    //2) 둘 중 하나는 IsTrigger : On인 상태
    //2) 둘 중 하나는 RigidBody가 있어야한다.
    private void OnTriggerEnter(Collider other)
    {
        Debug.Log($"trigger{other.gameObject.name}");
    }
}



OverlapSphere

    void Update()
    {
        float detectDistance = (this.transform.position.x / 2) / 2;
        //Collider[] hitColliders = (Physics.OverlapSphere(this.transform.GetComponent<MeshRenderer>().bounds.center, detectDistance));
        Collider[] hitColliders = Physics.OverlapSphere(this.transform.position, Math.Abs(detectDistance));

        foreach (var item in hitColliders)
        {
            if (item.name.Contains("Man"))
                Debug.Log(item.name);
            if (item.transform.root.name.Contains("Man"))
            {
                this.gameObject.GetComponent<MeshRenderer>().material.SetColor("_Color", Color.red);
            }
        }
    }

 


Unity 전체 링크

 

유니티 링크

- 환경설정, 디버깅 - 기본 - 유니티 에디터 스크립팅 - 수학 - Canvas / UI - Unity C# - 카메라 조작 - 오브젝트 조작 및 배치 - 쉐이더, 머티리얼 - 시네머신 환경설정, 디버깅 GitHub Desktop - 유니티 프로

bloodstrawberry.tistory.com

 

OverlapSphere를 이용하여 주변 콜라이더를 감지할 수 있다.

 

먼저 콜라이더를 감지할 오브젝트는 따로 색깔을 구분해두자.

아래의 보라색 Sphere에 OverlapSphereTest.cs를 추가한다.

그리고 Cube, Capsule, Sphere를 주변에 배치하자.

 

Cube, Capsule, Sphere는 미리 Layer를 추가해서 설정해두자.

아래는 Layer를 추가한 스크린샷이다.

 

Cube는 아래의 그림과 같이 Layer = Cube로 변경해두었다.

나머지도 마찬가지로 변경해두자.


OverlapSphereTest.cs를 검출의 중심이 되는 오브젝트에 추가하자.

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

public class OverlapSphereTest : MonoBehaviour
{
    public float radius = 0.1f;
    public Material detectedMat;

    void changeMaterial(GameObject go, Material changeMat)
    {
        Renderer rd = go.GetComponent<MeshRenderer>();
        Material[] mat = rd.sharedMaterials;
        mat[0] = changeMat;
        rd.materials = mat;
    }
    void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.green;
        Gizmos.DrawSphere(this.transform.position, radius);
    }

    void Update()
    {
        Collider[] colliders =
                    Physics.OverlapSphere(this.transform.position, radius);

        foreach (Collider col in colliders)
        {
            if (col.name == "Sphere" /* 자기 자신은 제외 */) continue;

            changeMaterial(col.gameObject, detectedMat);
        }
    }
}

 

OverlapSphere는 설정한 반지름(radius)을 기준으로 구(Sphere) 내에 있는 콜라이더를 검출한다.

그리고 검출된 콜라이더를 확인하기 위해 Material을 교체하도록 detectedMat을 선언하자.

 

    public float radius = 0.1f;
    public Material detectedMat;

 

OnDrawGizmosSelected는 OnDrawGizmos와 달리 개체를 선택한 경우만 Gizmos를 그린다.

    void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.green;
        Gizmos.DrawSphere(this.transform.position, radius);
    }

 

 

아래와 같이 보라색 Sphere가 선택된 경우만 Color.green인 Sphere를 그리는 것을 알 수 있다.

 

아래는 GameObject의 Material을 교체하는 코드다.

    void changeMaterial(GameObject go, Material changeMat)
    {
        Renderer rd = go.GetComponent<MeshRenderer>();
        Material[] mat = rd.sharedMaterials;
        mat[0] = changeMat;
        rd.materials = mat;
    }

 

public으로 선언된 radius를 변경하면서 검출을 확인하기 위해 Update에 OverlapSphere 코드를 넣었다.

매번 검출하는 것은 성능에 영향을 미치기 때문에 실제로는 이벤트나 충돌이 발생할 경우에 사용한다.

 

그리고 자기 자신도 검출이 되기 때문에 예외 처리가 필요하다면 예외 처리를 해야 한다.

    void Update()
    {
        Collider[] colliders =
                    Physics.OverlapSphere(this.transform.position, radius);

        foreach (Collider col in colliders)
        {
            if (col.name == "Sphere" /* 자기 자신은 제외 */) continue;

            changeMaterial(col.gameObject, detectedMat);
        }
    }

 

radius를 적당히 설정해두고, DetectedMat은 원하는 Material로 설정해두자.

 

Radius가 커질수록 멀리 있는 오브젝트가 DetectedMat(Red)로 변경되는 것을 알 수 있다.


이번에는 콜라이더가 있는 물체 중 큐브만 검출해보자.

 

LayerMask를 이용하면 설정된 Layer만 검출할 수 있다.

처음 테스트 환경을 만들 때 큐브에는 미리 "Cube" 레이어를 설정해두었다.

NameToLayer를 이용하여 cubeLayer 변수에 레이어를 받아올 수 있다.

    LayerMask cubeLayer;

    void Start()
    {
        cubeLayer = LayerMask.NameToLayer("Cube");
    }
    
    void Update()
    {
        int layerMask = (1 << cubeLayer);

        Collider[] colliders =
                    Physics.OverlapSphere(this.transform.position, radius, layerMask);

        foreach (Collider col in colliders)
        {
            if (col.name == "Sphere" /* 자기 자신은 제외 */) continue;

            changeMaterial(col.gameObject, detectedMat);
        }
    }

 

OverlapSphere에 layerMask를 추가하면 해당 layer만 검출한다.

layerMask는 레이어를 비트로 판단하기 때문에 (1 << cubeLayer)와 같이 설정해야 한다.

 

반대로 특정 레이어를 제외할 수도 있다. 

특정 비트를 제외하기 위해 " ~ " 비트 연산을 사용하면 된다.

int layerMask = ~(1 << cubeLayer);

 

이제 큐브만 제외하고 콜라이더들이 검출된 것을 볼 수 있다.

 

최종 코드는 다음과 같다.

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

public class OverlapSphereTest : MonoBehaviour
{
    public float radius = 0.1f;
    public Material detectedMat;
    LayerMask cubeLayer;

    void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.green;
        Gizmos.DrawSphere(this.transform.position, radius);
    }

    void changeMaterial(GameObject go, Material changeMat)
    {
        Renderer rd = go.GetComponent<MeshRenderer>();
        Material[] mat = rd.sharedMaterials;
        mat[0] = changeMat;
        rd.materials = mat;
    }

    void Start()
    {
        cubeLayer = LayerMask.NameToLayer("Cube");
    }

    void Update()
    {
        int layerMask = ~(1 << cubeLayer);

        Collider[] colliders =
                    Physics.OverlapSphere(this.transform.position, radius, layerMask);

        foreach (Collider col in colliders)
        {
            if (col.name == "Sphere" /* 자기 자신은 제외 */) continue;

            changeMaterial(col.gameObject, detectedMat);
        }
    }
}

 

출처 - https://bloodstrawberry.tistory.com/877

728x90