Implement hit detection with tilemaps
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.
What are the prerequisites for this tip?
- Create a top-down 2D map using standard Unity tilemaps
- Collision Handling with Standard Physics (2D)
About borrowing map materials
We process borrowed from the following sites.
Implementation of walking characters
First, implement a map and a character that performs hit detection. This character can be moved with the cursor keys on the keyboard. However, if you implement a proper walk, it will be long and far from the essence of the book tips, so this time I will only move a simple single picture.
If you want to implement walking animations, see the following tips:
After you create the project, add a sprite image of the object you want to move to the project.
Select the image and set the Pixels Per Unit to 32 from the Inspector. This is because the size of one square of the mapchip is 32 pixels, so it fits that. Once configured, click the "Apply" button below.
Place the sprite in the view.
Create a script to move the sprite. This is similar to the following tips:
Leave the script name Player
as .
Code as follows:
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 sprite you want to move.
Run the game and check if you want to move it with the keyboard.
Preparing MapTips
First of all, we will prepare a mapchip and create a map. This procedure is similar to the following tips: MapTips with 2D Tilemap Extras are also capable of collision detection, but they will not be used in this article because the procedure will be long.
Prepare the original image of the MapTip and add it to your project. To make the operation easier to understand, please prepare a "walkable place" and a "non-walkable place" for the map chip material.
Set it up for MapChips in the Inspector and click the Apply button. Once configured, open the Sprite Editor.
It's a 32-pixel maptip, so I'll split it up at 32.
Select the Tile palette tab. If not, display it with "Window > 2D -> Tile Palette" from the menu. Create a new palette. The name is arbitrary, but for now we will call it "MapChipPalette".
Create a MapChipPalette folder in Scenes and specify it.
Add a maptip by dragging it to the palette. Save it in the MapChipPalette folder you created earlier.
Create a map
This time, the map hit judgment will be performed in units of "Tilemap". Therefore, we will create two Tilemaps, "Tilemap without hit detection" and "Tilemap with hit detection".
First, create two Tilemaps in the hierarchy. You can create two in the Grid. The names are "TilemapObeject" and "TilemapGround" for clarity.
First, create a "TilemapGround". Since it is a movable range, you can simply lay the ground. If it is on the ground, you can change the pattern.
By the way, if the character is hidden, select the character object and set the layer order of the Sprite Renderer
inspector to 2.
The order of the layers is 0 by default and the Tilemap is 0, so if you increase it above this value, it will be displayed in the foreground.
Then select TilemapObject and place the maptip you want to make motionless. Set the layer order to 1 first. This is to make it appear in front of the ground.
This is what it looks like if you hide the ground.
Of course, at this point, there are no settings related to collision detection, so you can ride on high ground normally. After this, we will set the collision detection.
Collision Detection Settings
First, let's set up the character. This setting is almost the same as the tips below, so I will skip the details and briefly explain the procedure.
Select a character object from the hierarchy and select Physics 2D -> Circle Collider 2D from Add Component. If the shape of the object is rectangular, "Box Collider 2D" is fine.
Similarly, add "Physics 2D -> Rigidbody 2D".
Set the gravity scale to 0 to prevent Rigidbody 2D
automatic fall.
Check Z under Constraints to prevent the sprite from rotating when colliding.
Next, select "TilemapObject" you want to hit and select "Tilemap -> Tilemap Collider 2D" from "Add Component".
That's all there is to it. You don't even need any programming. Run the game and try to hit the object that becomes the wall. I think you can make sure it stops properly.
However, when you actually hit it, I think that there will be points of concern in the behavior. Here are some solutions:
Inconvenient behavior of hit detection with the map and solutions
When you hit a wall, you may find a few things that bother you.
If you move against the wall, you will get caught in the middle
Box Collider 2D
I think it will happen if you are using an object.
For example, from the scene below, when you press the key in the lower left, you want it to move to the left along the wall. However, after some progress, I think it will get stuck in something and stop.
Recognize dents in walls by position
Circle Collider 2D
I think it is easy to understand if you attach .
The wall should be flat, but if you move it against the wall, you will see that the wall moves as if it is uneven.
Causes and solutions to snags and bumps
The reason why these occur seems to be that "hit determination is performed on a mapchip basis". In fact, when you select TilemapObject, a green line appears at the place where the hit detection is located, and you can see that this is a line drawn in MapTip units.
So, if the moving object is on a line equivalent to exactly one map chip, it will be judged as a hit with one map chip. If you collide at the boundary of the map chips, two map chips will be hit and judged, so the strength of the bounce will increase.
I think the best way to solve this problem is to combine the hit detection with the attached mapchips. Here's how to do it:
SelectTilemap Collider 2D
"TilemapObject" with hit detection from the inspector and check "Use in composite" from .
As stated in the warning, this alone has no effect, so select "Physics 2D -> Composite Collider 2D" from "Add Component".
Rigidbody 2D is added along with Composite Collider 2D.
It's a little confusing, but I think you can confirm that the green line at the boundary between mapchips with hit detection has disappeared.
I don't want the tilemap to move, so I'll Rigidbody 2D
leave the component body type as "static".
Now run the game and try to get it moving. I think that even if you move diagonally along the wall, it will not get caught and you can move smoothly without bumpy movement.
Eliminate character pushes back from walls
You can see that if you move the character to push the wall and then stop moving, it will behave a little like bounced back from the wall.
To solve this,Rigidbody 2D
select the character object and change "Collision detection" to "Continuous" from the component.
The difference between "discontinuous" and "continuous" is as follows.
Discontinuous
Collision detection is a mechanism that thinks after moving. It is a form that performs collision detection from the state where it is moved and embedded in the wall. It is easy to understand if you associate it with trampolines and rubber, but the more it is embedded, the more repulsive the force will increase, and the bounce will be stronger. Instead, the calculation is performed after moving, so the processing cost is low.
Continuous
It is processed while determining what is on the way. Determine whether there is a wall between the position before and after the move, If there is a wall, it will judge the collision there and stop, so there is practically no repulsion. Instead, the processing cost increases a little because the calculation is included in the middle of the movement.
Caught in the corner of a map object
Depending on the program and location, some are caught and some are not, and the cause has not changed much. By the way, it happens with angular corners like Box Collider 2D, and not with rounded circles.
Even if such a mysterious phenomenon occurs, it is good to have rounded corners of the collider to avoid snags. It's limited to Box Collider 2D, but to make it round, the character object's Box Collider 2D component has an "edge radius" and you put a value there. If you enter 1 as a numerical unit, rounding will occur for the object size. It depends on the size, but it is good to put about 0.1.
By the way, the hit judgment increases only by the size of the roundness, so please adjust it if it is large. Box Collider 2D has a Collider Edit button that allows you to resize it directly in the view by clicking the button. Since the outer green line is the actual hit detection, set the size so that it is not unnatural.
After that, run the game to make sure it doesn't get scratched and make adjustments.