Minimaps are very common in video games these days, you can find them in almost every video game genre like RPG, MOBAs to FPS. 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 where he places some marks in the map and when pressing the right mouse button it drops the 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, the set 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. Then you can 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.
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 as a value. Then we clamp our local cursor coordinates
Y values respective to the values
0 and subtraction of the cursor and
rect which is later multiplied by the texture's width and
rect's width (similar to Y but in that case we use the Y value instead of X and height instead of width). Then we create two floats
calY which is converted to a value between
0 and 1 and then assign our vector2 cursor with the values of
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
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.