유니티(Unity) 프로그래밍

Unity 충돌감지

게임첫걸음 2024. 9. 20. 17:58

 Unity에서 오브젝트 충돌감지에 중요한 두 가지 Component가 있습니다.

Inspector - Collider, Rigidbody

  • Collider: 충돌체크
  • Rigidbody: 물리체크

Collider, Rigidbody

Collider는 충돌체크에 필요한 Component이고 Rigidbody는 물리 기능에 필요한 Component입니다. 둘 중 하나라도 없으면 플레이어 캐릭터가 벽을 통과하는 불상사가 발생할 수 있습니다.

 유니티에서 충돌체크를 하는 방법은 4가지가 있습니다.

  • 픽셀: 픽셀 하나하나 비교하여 닿으면 충돌 체크하는 방식, 정확하지만 느리다.
  • 원: 원 둘의 서로의 중심에서의 거리가 각 반지름의 합보다 낮으면 충돌 처리하는 방식, 정확하진 않지만 빠르다.
  • AABB: Axis-Aligned Bounding Box의 준말로 충돌박스가 오브젝트의 형태에 크기가 바뀌는 방식
  • OBB: Oriented Bounding Box의 준말로 충돌박스가 오브젝트의 형태에 따라 바뀌는 방식

충돌 체크 4가지 방식 예시
벽에 충돌되어 움직이는 오브젝트

 이제 위의 그림처럼 세팅한 후, 빨간색 오브젝트를 움직이는 3가지 방법을 코딩하겠습니다.

//MovingTranslate.cs

using UnityEngine;

public class MovingTranslate : MonoBehaviour
{
    [SerializeField][Range(1f, 20f)] private float moveSpd = 10f;

    private void Update()
    {
        if (Input.GetKey(KeyCode.W))
        {
            transform.Translate(Vector3.forward * moveSpd * Time.deltaTime);
        }
        else if(Input.GetKey(KeyCode.S))
        {
            transform.Translate(Vector3.back * moveSpd * Time.deltaTime);
            //transform.position = transform.position +
            //(-transform.forward * moveSpd * Time.deltaTime);
        }
    }
}

 첫 번째 방법은 Translate의 값을 직접적으로 바꾸는 방식입니다. moveSpd 변수를 선언하고 W, S를 누르면 moveSpd의 초기값에 따라 앞, 뒤로 움직이는 코드입니다.

 

//MovingVelocity.cs
using UnityEngine;
using UnityEngine.InputSystem.LowLevel;

//AABB : Axis - Aligned Bounding Box

//[RequireComponent(typeof(Rigidbody))]   //Rigidbody 추가하는 코드
//이렇게하면 실수로 Rigidbody 속성을 지우는 일을 방지함.
public class MovingVelocity : MonoBehaviour
{
    private Rigidbody rb = null;
    [SerializeField][Range(1f, 20f)] private float moveSpeed = 10f;

    private void Awake()
    {
        rb = gameObject.AddComponent<Rigidbody>();  //해당 오브젝트에 Rigidbody 추가하는 코드
        //게임 ON/OFF -> Rigidbody ON/OFF
        //AddComponent는 이미 해당값이 있을 경우 null이 반환
        //AddComponent는 없으면 추가해서 가져옴

        if(rb == null)
        {
            //GetComponent는 이미 해당값이 있어도 그 값을 반환
            //GetComponent는 없으면 null을 반환
            rb = GetComponent<Rigidbody>();
        }
    }

    private void Update()
    {
        if(Input.GetKey(KeyCode.W))
        {
            //linear(선형)
            rb.linearVelocity = new Vector3(0f, 0f, moveSpeed);
        }

        if(Input.GetKey(KeyCode.S))
        {
            rb.linearVelocity = -transform.forward * moveSpeed;
        }

        if(Input.GetKeyDown(KeyCode.Space))
        {
            rb.AddForce(Vector3.up * 10f, ForceMode.Impulse);   //움직이다 점프는 가능 / 점프하다 움직이면 이상함.
        }
    }
}

 두 번째 방법은 선형 속도를 사용하는 방법입니다. 몇 개의 코드를 알아보겠습니다.

  • [RequireComponent(typeof(Rigidbody))] : 주석과 같이 Rigidbody를 추가해 주는 코드로 이 스크립트가 켜져 있는 상태에서는 Inspector창에서 Rigidbody를 삭제할 수 없습니다.
  • linearVelocity: 선형 속도라는 뜻으로 오브젝트의 앞에 임의의 길이와 방향이 존재합니다. new Vector( 0f, 0f, moveSpeed); 에서 길이는 moveSpeed, 방향은 z축입니다.
  • -transform.forward * moveSpeed; : 선형 속도에서 방향은 forward로 z축 양수, 길이는 * moveSpeed입니다.
  • AddForce: 직역 그대로 힘을 추가한다는 뜻입니다. Vector3.up*10f는 y축으로 10만큼의 힘을 준다는 뜻이고 힘의 적용 방식을 정하는 4가지가 존재합니다. ForceMode입니다.
  • ForceMode.Force: 지속적인 힘을 적용합니다.
  • ForceMode.Impulse: 순간적인 힘을 적용합니다. 예를 들어, 점프와 같은 효과에 사용됩니다.
  • ForceMode.Acceleration: 질량을 고려하지 않고 힘을 적용합니다.
  • ForceMode.VelocityChange: 즉시 속도를 변경합니다.

위에선 점프를 하는 용도이기 때문에 Impulse를 사용합니다.

//MovingAxis.cs
using UnityEngine;

public class MovingAxis : MonoBehaviour
{
    [SerializeField][Range(1f, 20f)] private float moveSpeedo = 10f;

    private void Update()
    {
        float h = Input.GetAxis("Horizontal");
        float v = Input.GetAxis("Vertical"); 
        //direction 방향
        Vector3 dir = new Vector3(h, 0f, v);    //

        transform.position = transform.position + (dir.normalized * moveSpeedo * Time.deltaTime);
    }
}

 

  • "Horizontal": 일반적으로 키보드의 A/D 키 또는 좌/우 화살표 키를 사용하여 수평(x축)  이동을 감지합니다. 반환값은 -1(왼쪽)에서 1(오른쪽) 사이의 값입니다.
  • "Vertical": 일반적으로 W/S 키 또는 위/아래 화살표 키를 사용하여 수직(z축) 이동을 감지합니다. 반환값은 -1(뒤)에서 1(앞) 사이의 값입니다.

Input.GetKey(KeyCode.W, S, A, D)를 안 해도 WASD로 이동이 가능합니다. dir은 h, v에 들어가는 WASD입력값과 입력시간 등을 담고 있는데 이를 좌표값에 적용하는 변수입니다. dir.normalized(단순화)를 이용하여 방향값만을 가지고 이동합니다.

 

'유니티(Unity) 프로그래밍' 카테고리의 다른 글

Unity Prefabs과 Stack, Queue  (1) 2024.09.26
Unity Collider(Trigger, Collision)  (2) 2024.09.24
유니티3D 아날로그 시계  (0) 2024.09.19
Unity3D 추격2  (1) 2024.09.18
Unity3D 추격  (1) 2024.09.12