Collision Handling with Standard Physics (2D)

Page update date :
Page creation date :

Verification environment

Windows
  • Windows 11
Unity Editor
  • 2021.3.3f1
Input System Package
  • 1.3.0

Prerequisites for this tip

The following settings have been made in advance as a premise for the description of this tip.

At first

This tip places two objects so that you can implement the behavior of manipulating one object and using Unity's standard physics to push the other when it comes into contact with the other.

By the way, most of the settings are the same as the procedure described in the previous article "Determining whether objects collide with each other (2D)".

Preparation

The procedure here is almost the same as the previous tips , so let's flow it smoothly.

After creating the project, prepare two sprite images that will be objects and add them. The names are "UnityTips" and "UnityTips_2" respectively.

Add two image files by dropping them into the view.

Add a script to move the left object with the keyboard. The script name Player is .

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);
    }
  }
}

Attach to the object on which you want to run the script.

Run the game and check if it works with the cursor keys on your keyboard.

Finally, place a text object to display the collision detection status. The object name TextState is .

Collision Handling Settings

From here, you can configure the settings related to collisions.

First, select the object you want to move, "UnityTips", and click "Add Component" from the inspector. Select from Physics 2D the list. Physics is a 3D object, so make no mistake.

Physics 2DBox Collider 2D Select from . Since this sprite is rectangular, Box is selected, but if it is circle-shaped, for example, select other shapes such as Circle.

Last time, I wanted to get information only about whether or not I hit it, so I checked "Make it trigger", but this time I won't. This enables collision handling in physics.

Rigidbody 2D Then add the components of . You can add it from "Physics 2D -> Rigidbody 2D". Rigidbody gives physics informationCollider to the object and can also determine collisions with objects that have .

Set the Gravity Scale to 0 to prevent free fall below.

Similarly, add a component to the other object "UnityTips_2" to mark Box Collider 2D hits.

In addition, this time it is necessary to move with the force of the opponent,Rigidbody 2D so add . The gravity scale should be 0.

That's all there is to it. No program is required at this time. Run the game and try to touch another object.

I think you can confirm that if you push the opponent in like this, the opponent will behave as if he is pushed. It is very easy to use the physics of the standard function because no program is required.

Prevent objects from rotating

You can see when you touch it, but if the hit point shifts even slightly, each object will rotate. As a game, it often becomes unnatural, so you need to set it so that it does not rotate.

Rigidbody 2D The component has an item called "Fixed rotation" in "Constraints", so check Z. Now you can work so that it doesn't rotate. Try setting it to two objects and running the game to check it.

I think you can be sure that it doesn't rotate no matter what angle you push it from.

Do something when objects hit each other

For example, you may want to implement a bullet that hits an enemy while pushing the opponent while reducing the enemy's health. This is the same as the previous tips , as the event will occur, so you can deal with it.

Player Open the script and add each field and method using as follows:

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}";
  }
}

Since we want to display information on whether or not it was hit, we will make it possible to display it in a text object as follows.

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

The collision detection process is described as follows.

/// <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}";
}

Similar to the previous tips------, but the method name is now "OnCollision------2D" instead of "OnTrigger2D".

Rigidbody 2D Each of the above events occurs when an object that has collides with another object Collider 2D that has . This will allow you to determine and process whether it is correct or not.

There are three events, each of which is called at the following timing.

OnCollisionEnter2D When objects hit each other
OnCollisionStay2D While objects are hitting each other
OnCollisionExit2D When objects leave the collision state

In both cases, the opponent object receives the opponent's object as an argument, so you can get the opponent's Collision2D object by looking up Collider2D.gameObject the type of target hit by (enemy, Collider2D.collider.tag item, etc.).

Of the OnCollisionEnter2D above three events, and OnCollisionExit2D are called once per collision.

OnCollisionStay2D is called every frame during the collision, but the event is no longer called after a certain amount of time has passed since both objects stopped. This is because it is considered to have entered a sleep state, and it is considered a waste of processing to calculate collisions every frame with something that is not moving.

If you Rigidbody 2D do not want it to sleep, change the sleep mode of the parameter to "Do not sleep".

After changing the code, set the text for displaying information.

Run the game and move the object with the keyboard to touch another sprite. You can see that three functions are called for each.

By the way, if you touch an object and then stop moving, the method will be called for OnCollisionStay2D a short time. You should be able to see that the method is no longer called after OnCollisionStay2D a certain amount of time.

This indicates that you have entered a sleep state, but if you want to change the time until you enter this sleep, you can change it by selecting "2D Physics" from the project settings and specifying the "Sleep time" parameter in seconds. It cannot be set to 0, but if it OnCollisionStay2D is set to infinitely small, the method itself will not be called.