Minimaps are very common in video games these days. You can find them in almost every video game genre, like RPGs, MOBAs and FPSes. Minimaps are actually a mini representation of the entire game map, which helps players to get a quick snapshot of the in-game map. Games like Valorant and MMORPG games allow players to interact with the minimap itself in order to move or use some specific powerups.
A few weeks back I was trying to replicate the base mechanics of an FPS game character attribute. In this game, the character places some marks on the map. Then, after he presses the right mouse button, the game drops smokes in the same exact area as the minimap marking. The challenge was to get the exact position of the player's click in the minimap then convert it into the real world position and finally place the smokes ready for spawn. The result is below.
Creating the Minimap
Before getting started, make sure that you have created a camera that casts as your minimap.
If you don't know how to create a minimap in Unity, you can do it by creating a topdown camera that captures your map, then setting your culling masks to the object layers that you want to minimap to show, and finally creating a render texture then assign it to the minimap camera's texture.
You can now create a raw image in your UI canvas and assign it with the render texture that we just made. This will make the UI image render everything your minimap camera sees.
Getting World Position Through the Minimap Camera
First of all, we create a class called MiniMapController
which implements the IPointerClickHandler which helps us get pointer clicks. So let's split the point conversion into two parts where first we take the local cursor from the click in the minimap and in the second part we cast the minimap's click ray into the world position.
How It Works
As you can see in the script above, on pointer click we use the recttransform
utility to convert our screen point to a local position in recttransform
.
We create a reference to our map's texture and a rect
that takes rect
transform's rect
as a value. Then, we clamp our local cursor X
and Y
values respective to the value 0
, the subtraction of the cursor and rect
, which we later multiply by the texture's width and rect
's width. You can do this similarly by using Y
values, but in that case, we use the Y value instead of X and height instead of width.
Then we create two floats calX
and calY
which is converted to a value between 0
and 1
and then assign our vector2
cursor with the values of calX
and calY
. After doing this we have received the ray that we cast into the minimap as a vector2 value which now needs to be converted into the real-world position of the player.
In order to do that I have created a function called CastRayToWorld
which takes a vector as a parameter. So in this function, we create a Ray MapRay
that converts our minimap camera's screen point to ray with reference to the vector2
we got from our pointer click. Then we create a RaycastHit
called miniMapHit
which is later used with Physics. RayCast
to check the RayCast
hit points which give us our exact converted hit in the miniMapHit
variable. So finally, the miniMapHit
point is the exact point where our player pressed in the minimap.