표준 물리(2D)를 사용한 충돌 처리

페이지 업데이트 :
페이지 생성 날짜 :

검증 환경

윈도우
  • 윈도우 11
Unity 에디터
  • 2021.3.3f1
입력 시스템 패키지
  • 1.3.0

이 팁의 전제 조건

이 팁에 대한 설명의 전제로 다음 설정이 미리 이루어졌습니다.

처음에

이 팁은 한 오브젝트를 조작하고 Unity의 표준 물리를 사용하여 다른 오브젝트와 접촉할 때 다른 오브젝트를 밀어내는 동작을 구현할 수 있도록 두 개의 오브젝트를 배치합니다.

그건 그렇고, 대부분의 설정은 이전 기사 "객체가 서로 충돌하는지 여부 확인 (2D)"에서 설명한 절차와 동일합니다.

준비

여기의 절차는 이전 팁 과 거의 동일하므로 원활하게 진행합시다.

프로젝트를 만든 후 객체가 될 두 개의 스프라이트 이미지를 준비하고 추가합니다. 이름은 각각 "UnityTips"와 "UnityTips_2"입니다.

두 개의 이미지 파일을 뷰에 놓아 추가합니다.

키보드로 왼쪽 개체를 이동하는 스크립트를 추가합니다. 스크립트 이름은 Player 입니다.

using UnityEngine;
using UnityEngine.InputSystem;

public class Player : MonoBehaviour
{
  // 一定時間ごとに呼ばれます
  void FixedUpdate()
  {
    // キーボードの情報を取得
    var keyboard = Keyboard.current;

    // スプライトの移動処理
    if (keyboard.leftArrowKey.isPressed)
    {
      transform.Translate(-0.1f, 0, 0, Space.World);
    }
    if (keyboard.rightArrowKey.isPressed)
    {
      transform.Translate(0.1f, 0, 0, Space.World);
    }
    if (keyboard.upArrowKey.isPressed)
    {
      transform.Translate(0, 0.1f, 0, Space.World);
    }
    if (keyboard.downArrowKey.isPressed)
    {
      transform.Translate(0, -0.1f, 0, Space.World);
    }
  }
}

스크립트를 실행할 개체에 연결합니다.

게임을 실행하고 키보드의 커서 키와 함께 작동하는지 확인하십시오.

마지막으로 충돌 감지 상태를 표시할 텍스트 개체를 배치합니다. 개체 이름은 TextState 입니다.

충돌 처리 설정

여기에서 충돌과 관련된 설정을 구성할 수 있습니다.

먼저 이동할 오브젝트인 "UnityTips"를 선택하고 인스펙터에서 "Add Component"를 클릭합니다. Physics 2D 목록에서 선택합니다. Physics 는 3D 개체이므로 실수하지 마십시오.

Physics 2DBox Collider 2D 에서 선택합니다. 이 스프라이트는 직사각형이므로 Box가 선택되지만 예를 들어 원 모양인 경우 Circle과 같은 다른 모양을 선택합니다.

전회는 맞았는지 안 맞았는지에 대해서만 정보를 얻고 싶었기 때문에 "트리거 만들기"를 체크했습니다만, 이번은 하지 않습니다. 이를 통해 물리학에서 충돌 처리가 가능합니다.

Rigidbody 2D 그런 다음 의 구성 요소를 추가합니다. "Physics 2D -> Rigidbody 2D"에서 추가할 수 있습니다. Rigidbody 객체에 물리 정보를Collider 제공하고 .

중력 스케일(Gravity Scale) 을 0 으로 설정하여 아래로 자유 낙하하는 것을 방지합니다.

마찬가지로, 다른 객체 "UnityTips_2"에 구성 요소를 추가하여 히트를 표시합니다 Box Collider 2D .

또한 이번에는 상대방의 힘으로 움직여야하므로Rigidbody 2D . 중력 눈금은 0이어야 합니다.

그게 전부입니다. 현재로서는 프로그램이 필요하지 않습니다. 게임을 실행하고 다른 물체를 만져보십시오.

이렇게 상대를 밀어 넣으면 상대가 밀린 것처럼 행동한다는 것을 확인할 수 있다고 생각합니다. 프로그램이 필요하지 않기 때문에 표준 함수의 물리학을 사용하는 것은 매우 쉽습니다.

물체가 회전하지 않도록 방지

터치하면 볼 수 있지만 히트 포인트가 조금이라도 이동하면 각 개체가 회전합니다. 게임으로서는 부자연스러워지는 경우가 많기 때문에 회전하지 않도록 설정해야 합니다.

Rigidbody 2D 구성 요소에는 "Constraints"에 "Fixed rotation"이라는 항목이 있으므로 Z를 선택하십시오. 이제 회전하지 않도록 작업할 수 있습니다. 두 개의 오브젝트로 설정하고 게임을 실행하여 확인해 보세요.

어떤 각도에서 밀어도 회전하지 않는다는 것을 확신할 수 있다고 생각합니다.

물체가 서로 부딪쳤을 때 뭔가를 하십시오

예를 들어, 적의 체력을 감소시키면서 상대를 밀면서 적을 명중하는 총알을 구현할 수 있습니다. 이것은 이벤트가 발생하므로 이전 팁 과 동일하므로 처리 할 수 있습니다.

Player 스크립트를 열고 다음과 같이 각 필드와 메서드를 추가합니다.

using System;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;

public class Player : MonoBehaviour
{
  /// <summary>状態表示用テキストオブジェクト。</summary>
  [SerializeField] private Text TextState;

  // 中略

  /// <summary>衝突した瞬間に呼ばれます。</summary>
  /// <param name="partner">衝突した相手のコリジョン情報。</param>
  private void OnCollisionEnter2D(Collision2D partner)
  {
    TextState.text = $"OnCollisionEnter2D : {partner.collider.tag} {DateTime.Now:HH:mm:ss.fff}{Environment.NewLine}{TextState.text}";
  }

  /// <summary>衝突している間呼ばれます。ただしスリープモードになった場合は呼ばれません。</summary>
  /// <param name="partner">衝突した相手のコリジョン情報。</param>
  private void OnCollisionStay2D(Collision2D partner)
  {
    TextState.text = $"OnCollisionStay2D : {partner.collider.tag} {DateTime.Now:HH:mm:ss.fff}{Environment.NewLine}{TextState.text}";
  }

  /// <summary>衝突状態でなくなったタイミングで呼ばれます。</summary>
  /// <param name="partner">衝突した相手のコリジョン情報。</param>
  private void OnCollisionExit2D(Collision2D partner)
  {
    TextState.text = $"OnCollisionExit2D : {partner.collider.tag} {DateTime.Now:HH:mm:ss.fff}{Environment.NewLine}{TextState.text}";
  }
}

맞았는지 여부에 대한 정보를 표시하고 싶기 때문에 다음과 같이 텍스트 객체에 표시할 수 있도록 합니다.

/// <summary>状態表示用テキストオブジェクト。</summary>
[SerializeField] private Text TextState;

충돌 검출 과정은 다음과 같이 설명된다.

/// <summary>衝突した瞬間に呼ばれます。</summary>
/// <param name="partner">衝突した相手のコリジョン情報。</param>
private void OnCollisionEnter2D(Collision2D partner)
{
  TextState.text = $"OnCollisionEnter2D : {partner.collider.tag} {DateTime.Now:HH:mm:ss.fff}{Environment.NewLine}{TextState.text}";
}

/// <summary>衝突している間呼ばれます。ただしスリープモードになった場合は呼ばれません。</summary>
/// <param name="partner">衝突した相手のコリジョン情報。</param>
private void OnCollisionStay2D(Collision2D partner)
{
  TextState.text = $"OnCollisionStay2D : {partner.collider.tag} {DateTime.Now:HH:mm:ss.fff}{Environment.NewLine}{TextState.text}";
}

/// <summary>衝突状態でなくなったタイミングで呼ばれます。</summary>
/// <param name="partner">衝突した相手のコリジョン情報。</param>
private void OnCollisionExit2D(Collision2D partner)
{
  TextState.text = $"OnCollisionExit2D : {partner.collider.tag} {DateTime.Now:HH:mm:ss.fff}{Environment.NewLine}{TextState.text}";
}

이전 팁 과 비슷하지만------, 메서드 이름은 이제 "OnTrigger2D"가 아닌 "OnCollision------2D"입니다.

Rigidbody 2D 위의 각 이벤트는 있는 개체가 있는 다른 개체 Collider 2D 와 충돌할 때 발생합니다. 이를 통해 올바른지 여부를 결정하고 처리할 수 있습니다.

세 가지 이벤트가 있으며 각 이벤트는 다음 타이밍에 호출됩니다.

OnCollisionEnter2D 물체가 서로 부딪힐 때
온콜리전스테이2D (OnCollisionStay2D) 물체가 서로 부딪히는 동안
OnCollisionExit2D 객체가 충돌 상태를 벗어날 때

두 경우 모두 상대 객체가 상대의 객체를 인자로 받아들이기 때문에 적중한 타겟의 종류(적, Collider2D.collider.tag 아이템 등)를 조회 Collider2D.gameObject 하여 상대 Collision2D 의 객체를 얻을 수 있습니다.

OnCollisionEnter2D 위의 세 가지 이벤트 OnCollisionExit2D 중 충돌당 한 번 호출됩니다.

OnCollisionStay2D 는 충돌 중에 매 프레임마다 호출되지만, 두 오브젝트가 모두 중지된 후 일정 시간이 경과한 후에는 더 이상 이벤트가 호출되지 않습니다. 이는 수면 상태에 들어간 것으로 간주되기 때문이며, 움직이지 않는 무언가와 매 프레임마다 충돌을 계산하는 것은 처리 낭비로 간주됩니다.

Rigidbody 2D 절전 모드를 사용하지 않으려면 매개 변수의 절전 모드를 "절전 모드 안 함"으로 변경하십시오.

코드를 변경한 후 정보를 표시할 텍스트를 설정합니다.

게임을 실행하고 키보드로 개체를 움직여 다른 스프라이트를 터치합니다. 각각에 대해 세 개의 함수가 호출되는 것을 볼 수 있습니다.

그건 그렇고, 물체를 만진 다음 움직임을 멈추면 짧은 시간 동안 OnCollisionStay2D 메서드가 호출됩니다. 일정 시간이 지나면 OnCollisionStay2D 메서드가 더 이상 호출되지 않는 것을 볼 수 있어야 합니다.

이는 절전 상태에 들어갔음을 나타내지만, 이 절전 모드로 들어갈 때까지의 시간을 변경하려면 프로젝트 설정에서 "2D 물리"를 선택하고 "절전 시간" 매개변수를 초 단위로 지정하여 변경할 수 있습니다. 0으로 설정할 수는 없지만 OnCollisionStay2D 무한히 작게 설정하면 메서드 자체가 호출되지 않습니다.