프로그래밍(C#) /유니티공부

유니티 physics 충돌 처리 정리

정체불명의 모모 2022. 8. 19. 14:24
Collider란? ( 충돌 감지를 위한 컴포넌트 )

: 콜라이더가 붙어있는 게임 오브젝트가 서로 충돌할 경우 OnCollision 또는 OnTrigger가 호출 됩니다.

  충돌을 감지하기 위해서는 다음 두 가지 조건을 모두 만족해야 합니다.

  • 두 게임오브젝트 모두 콜라이더 컴포넌트가 추가 되어야 합니다.
  • 움직이는 게임 오브젝트에는 반드시 리지드 바디(Rigidbody) 컴포넌트를 추가 해야 합니다.

   리지드 바디 컴포넌트가 붙어 있을 경우 물리 동작을 수행 할 수 있습니다.

 

•  Collider의 종류 :  Box Collider , Sphere Collider , Capsule Collider , Mesh Collider 가  있습니다.

 

• Collider의 처리 속도 순서 : Sphere Collider > Capsule Collider > BoxCollider > MeshCollider
   ( MeshCollider는 정밀 충돌 처리를 하기 때문에 처리 속도가 매우 떨어집니다.
      - 추가하면 기본적으로 성능 저하 방지를 위해 충돌 감지가 꺼져 있습니다.)

 

► Collider Component 속성 정리

  • Is Trigger : 트리거 사용 여부( 체크 시 물리적인 충돌이 발생하지 않음)
  • Material : 콜라이더에 사용되는 재질을 나타냄
  • Center : 콜라이더 중심(로컬)
  • Size : 콜라이더 크기(로컬)  

Collider 컴포넌트 속성

 


OnCollision

: 콜라이더가 붙어있는 게임 오브젝트가 서로 충돌할 경우 OnCollision 함수가 호출되며 물리적인 충돌 현상이 발생 됩니다.

  (콜라이더의 IsTrigger를 체크 해제할 경우 OnCollision 발생)

using UnityEngine;

public class OnCollisionExample : MonoBehaviour
{
    private void OnCollisionEnter(Collision collision)
    {
        Debug.Log("OnCollisionEnter " + collision.gameObject.name);
    }

    private void OnCollisionStay(Collision collision)
    {
        Debug.Log("OnCollisionStay " + collision.gameObject.name);
    }

    private void OnCollisionExit(Collision collision)
    {
        Debug.Log("OnCollisionExit " + collision.gameObject.name);
    }
}
  • OnCollisionEnter : 두 게임오브젝트가 충돌이 일어날 경우 호출
  • OnCollisionStay : 두 게임오브젝트가 충돌이 지속될 경우 호출
  • OnCollisionExit : 두 게임오브젝트가 충돌이 끝난 경우 호출

OnTrigger

: 콜라이더가 붙어있는 게임오브젝트가 서로 충돌할 경우 OnTrigger 함수가 호출 되며 물리적인 충돌 현상은 발생 되지 않고

  물체를 통과하게 됩니다.(콜라이더의 IsTrigger를 체크할 경우 OnTrigger 발생)

using UnityEngine;

public class OnTriggerExample : MonoBehaviour
{
    private void OnTriggerEnter(Collider other)
    {
        Debug.Log("OnTriggerEnter " + other.name);
    }

    private void OnTriggerStay(Collider other)
    {
        Debug.Log("OnTriggerStay " + other.name);
    }

    private void OnTriggerExit(Collider other)
    {
        Debug.Log("OnTriggerExit " + other.name);
    }
}
  • OnTriggerEnter : 두 게임오브젝트가 충돌이 일어날 경우 호출
  • OnTriggerStay : 두 게임오브젝트가 충돌이 지속될 경우 호출
  • OnTriggerExit : 두 게임오브젝트가 충돌이 끝난 경우 호출

리지드바디(RigidBody)

: RigidBody 컴포넌트를 이용하면 게임 오브젝트가 중력과 같은 물리 프로퍼티의 영향을 받습니다.

  여기에는 질량, 속도, 항력(공기 저항)등의 프로퍼티도 포함됩니다.

  질량이 큰 오브젝트는 질량이 작은 오브젝트의 영향을 덜 받으며 반대의 경우도 마찬가지 입니다.

  항력은 시간에 따른 속도의 감쇠에 영향을 주며, 각항력은 각속도에 영향을 미칩니다.

 

  Rigidbody 컴포넌트를 다루는 경우에는 FixedUpdate()를 사용해야 합니다.

  Rigidbody는 내부적으로 Transform을 사용하여 형태를 변경합니다. 

  따라서 게임 오브젝트의 Rigidbody 컴포넌트, transform 컴포넌트 중 하나만 사용하여야 합니다.

  ( 예를 들어, RigidBody로 서로 충돌을 하여, 밀려나도록 하는 물리 로직을 구성하고, 이와 동시에 Transform을 사용하여,

     옆으로 이동하는 로직을 구현하면 안됩니다.)

 

  • Mass : 오브젝트의 질량입니다. 질량은 물질이 가지고 있는 양이며, 질량의 단위는 Kilogram(Kg)입니다. 질량이 작을수록, 힘의 영향을 쉽게, 많이 받습니다. 질량이 크면 클수록 물체를 움직이는데 필요한 힘이 더 많이 필요합니다.
  • Drag : 공기저항을 의미합니다. 오브젝트가 힘에 의해 움직일때, 공기 저항을 받도록 설정하는 값입니다. Drag의 값이 0이면, 공기저항이 없습니다. Drag의 값이 클수록 공기의 저항을 많이 받습니다. 
  • Angular Drag : 오브젝트가 토크로 회전을 할 때 공기의 저항을 받는 정도를 설정합니다. 0일 때에는 공기의 저항을 받지 않습니다.
  • Use Gravity : 중력입니다. 중력을 사용할 것인지, 중력을 사용하지 않을 것인지를 설정합니다. 선택(√)하면 해당 게임오브젝트는 중력의 영향을 받습니다. 중력은 Y축에 영향을 받습니다. 개발 환경에 맞게 선택을 합니다. 
  • Is Kinematic : Rigidbody Component를 사용하기는 하지만, 게임 오브젝트의 상태가 물리 엔진에 의해 변형되지 않습니다. Transform을 사용하여 게임 오브젝트를 동작합니다.

Phycisc 물리 충돌 함수

• Physics.Linecast : 시작과 끝 사이에 선을 교차하는 충돌이 있으면 true를 반환 합니다.

using UnityEngine;
using System.Collections;

public class ExampleClass : MonoBehaviour {
    public Transform target;
    void Update() {
        if (Physics.Linecast(transform.position, target.position)) {
            Debug.Log ("blocked");
        }
    }
}


 Physics.OverlapBox : 지정된 상자 안 또는 상자 안에 접촉 하는 모든 충돌을 찾습니다.

 Physics.OverlapSphere : 중점과 반지름으로 가상의 원을 만들어 추출하려는 반경 이내에 들어와 있는 콜라이더들을
   반환 하는 함수 입니다.

   함수의 반환 값은 Collider 컴포넌트의 배열로 넘어 옵니다.
   또한 OverlapSphere함수는 특정 레이어만 검출할 수도 있습니다.

using UnityEngine;
using System.Collections;

public class ExampleClass : MonoBehaviour{
   void ExplosionDamage(Vector3 center, float radius)
   {
      Collider[] hitColliders = Physics.OverlapSphere(center, radius);
      int i = 0;
      while(i < hitColliders.Length)
      {
         hitColliders[i].SendMessage("AddDamage");
         i++;
       }
    }
}

 Physics.Raycast : 직선을 씬에 투영하여 대상에 적중되면 true를 리턴하는 함수 입니다.
  Raycast 함수는 캐스팅 성공 실패에 따른 결과만 리턴하는 간단한 형태에서 부터 대상과 Ray의 충돌에 관련된 자세한 정보를 
  리턴하는 다양한 버전이 제공 되고 있습니다.

void testRay()
{
    Ray ray = new Ray(transform.position , transform.forward);
    RaycastHit hitData;
    
    Physics.Raycast(ray, out hitData);
    
    // 성공 했을때
    if(Physics.Raycast(ray, out hitData))
    {
        // 충돌한 오브젝트의 데이터를 받아 올 수 있다.
    }
 }

 

 Physics.SphereCast : 광선을 따라 구를 구조하고 무엇이 적중했는지에 대한 자세한 정보를 반환 합니다.


▪︎ 3D 프로젝트의 경우 아래 Physics 메소드 사용

OverlapBox 접촉한 모든 콜라이더나 내부의 박스(box)와 함께 배열을 반환합니다.
OverlapBoxNonAlloc 접촉한 콜라이더의 개수를 반환합니다.
OverlapSphere 접촉한 모든 콜라이더나 내부의 구체(sphere)와 함께 배열을 반환합니다.
OverlapSphereNonAlloc 접촉한 콜라이더의 개수를 반환합니다.

▪︎ 2D 프로젝트의 경우 아래 Physics 메소드 사용

OverlapArea 충돌체가 직사각형 영역 내에 있는지 확인합니다.
OverlapAreaAll 직사각형 영역에 속하는 모든 충돌체 목록을 가져옵니다.
OverlapAreaNonAlloc 지정된 영역에 속하는 모든 충돌체 개수를가져옵니다.
OverlapBox 충돌체가 상자 영역 내에 있는지 확인합니다.
OverlapBoxAll 상자 영역에 속하는 모든 충돌체 목록을 가져옵니다.
OverlapBoxNonAlloc 상자 영역에 속하는 모든 충돌체 개수를가져옵니다.
OverlapCapsule 충돌체가 캡슐 영역 내에 있는지 확인합니다.
OverlapCapsuleAll 캡슐 영역에 속하는 모든 충돌체 목록을 가져옵니다.
OverlapCapsuleNonAlloc 캡슐 영역에 속하는 모든 충돌체 개수를가져옵니다.
OverlapCircle 충돌체가 원형 영역 내에 있는지 확인합니다.
OverlapCircleAll 원형 영역에 속하는 모든 충돌체 목록을 가져옵니다.
OverlapCircleNonAlloc 원형 영역에 속하는 모든 충돌체 개수를가져옵니다.
OverlapCollider 주어진 콜 라이더와 겹치는 모든 콜 라이더 목록을 가져옵니다.
OverlapPoint 충돌체가 공간의 한 지점과 겹치는 지 확인합니다.
OverlapPointAll 공간의 한 지점과 겹치는 모든 충돌체의 목록을 가져옵니다.
OverlapPointNonAlloc 공간의 한 지점과 겹치는 모든 충돌체의 개수를 가져옵니다.

 

---------------------------------------------------------------------------------------------------------------

레이어 기반 충돌 감지

: 레이어 기반 충돌 탐지는 게임오브젝트 특정 Layer 또는 Layers로 설정된 다른 GameObject와 충돌합니다.

Layer를 설정해 줍니다.
Layer 별 충돌 할 수 있는 Phyics 설정을 해줍니다. (Edit >  ProjectSetting > Physics)

레이어에서 어떤 오브젝트가 충돌할 수 있는지를 나타내는 "Collision Matrix(충돌 매트릭스)"를 볼 수 있습니다.

예를 들어 충돌 매트릭스를 오직 같은 레이어에 속하는 GameObjects들이 충돌할 수 있다는 것으로 세팅합니다.

 

ㅁ 레이어 기반 충돌을 감지하기 위한 GameObjects세팅.

 

1. 사용자의 게임 오브젝트가 속할 레이어를 선택합니다.

2. 사용자가 게임 오브젝트들을 레이어에 지정하는 것을 끝낼 때까지 각 게임 오브젝트를 위해 1을 반복합니다.

3. Edit->projectSettings->Physics을 클릭해서 Physics Preference Panel 을 엽니다.

4. 충돌 매트릭스에서의 어떤 레이어가 다른 레이어와 상호 작용 할지 클릭함으로서 선택 합니다.