This is what the minimap will look like in the game:
The plan is to have the minimap cover all of the map boundaries, and have a shape depicting as the player’s main camera on the minimap, marking where the player’s camera is currently located. It should be something similar to WarCraft 3 or StarCraft 3 minimap displays.
If the player moves their mouse cursor near the edges, both the player’s camera and the shape in the minimap will move correspondingly in the minimap. I understand that the minimap can filter in/out which game objects will be shown.
That’s something I would like to do. I am thinking of having a mesh or some triangular shaped object show up on the minimap, but I don’t know what to do with the player’s camera.
How would I go about this? Thanks.
I should probably add some more things to this.
Here’s where I got the inspiration from (StarCraft 2 minimap):
Here’s a diagram of what I’m planning to do:
I can obtain the perpendicular position easily (Just the X and Y of the camera’s transform). The angle X is the X-axis rotation of the camera from the Transform component.
Drawing 4 lines is very tricky, and it’s something I am stuck with. I could use OnPostRendering() in the camera so the minimap camera will draw the lines at the position where the minimap camera is going to be located in the player’s main camera. The problem is how I would rotate the rectangle using the angle I got, and change the matrix in the OnPostRendering().
public void Update() {
Ray topLeftCorner = this.minimapCamera.ScreenPointToRay(new Vector3(0f, 0f));
Ray topRightCorner = this.minimapCamera.ScreenPointToRay(new Vector3(Screen.width, 0f));
Ray bottomLeftCorner = this.minimapCamera.ScreenPointToRay(new Vector3(0, Screen.height));
Ray bottomRightCorner = this.minimapCamera.ScreenPointToRay(new Vector3(Screen.width, Screen.height));
this.topLeftPosition = this.minimapCamera.ScreenToViewportPoint(topLeftCorner.GetPoint(25f));
this.topRightPosition = this.minimapCamera.ScreenToViewportPoint(topRightCorner.GetPoint(25f));
this.bottomLeftPosition = this.minimapCamera.ScreenToViewportPoint(bottomLeftCorner.GetPoint(25f));
this.bottomRightPosition = this.minimapCamera.ScreenToViewportPoint(bottomRightCorner.GetPoint(25f));
this.topLeftPosition.x *= 80f;
this.topRightPosition.x *= 80f;
this.bottomLeftPosition.x *= 80f;
this.bottomRightPosition.x *= 80f;
this.topLeftPosition.x += 3.52f;
this.bottomLeftPosition.x += 3.52f;
this.topLeftPosition.y *= 1000f;
this.topRightPosition.y *= 1000f;
this.bottomLeftPosition.y *= 1000f;
this.bottomRightPosition.y *= 1000f;
this.topLeftPosition.z = 0f;
this.topRightPosition.z = 0f;
this.bottomLeftPosition.z = 0f;
this.bottomRightPosition.z = 0f;
}
Felt hacky, but this is the result I got. I can’t move up and down because the values change at 0.0001 scaled.
1 Like
Well, I guess I solved it…
You never need to find the angle of the camera’s frustum to rotate the rectangle in the minimap at all. You just need the viewport points and render the lines to make the box.
Here’s the code for the minimap.
using UnityEngine;
using System.Collections;
public class MinimapStuffs : MonoBehaviour {
public Camera playerCamera;
public Camera minimapCamera;
public Collider floorCollider;
public Vector3 topLeftPosition, topRightPosition, bottomLeftPosition, bottomRightPosition;
public Vector3 mousePosition;
public void Start() {
//this.minimapCamera = this.GetComponent<Camera>();
if (this.playerCamera == null) {
Debug.LogError("Unable to determine where the Player Camera component is at.");
}
if (this.playerCamera == null) {
Debug.LogError("Unable to determine where the Minimap Camera component is at.");
}
if (this.floorCollider == null) {
GameObject floorObject = GameObject.FindGameObjectWithTag("FloorCollider");
this.floorCollider = floorObject.GetComponent<Collider>();
if (this.floorCollider == null) {
Debug.LogError("Cannot set Quad floor collider to this variable. Please check.");
}
}
}
public void Update() {
Ray topLeftCorner = this.playerCamera.ScreenPointToRay(new Vector3(0f, 0f));
Ray topRightCorner = this.playerCamera.ScreenPointToRay(new Vector3(Screen.width, 0f));
Ray bottomLeftCorner = this.playerCamera.ScreenPointToRay(new Vector3(0, Screen.height));
Ray bottomRightCorner = this.playerCamera.ScreenPointToRay(new Vector3(Screen.width, Screen.height));
RaycastHit[] hits = new RaycastHit[4];
if (this.floorCollider.Raycast(topLeftCorner, out hits[0], 40f)) {
this.topLeftPosition = hits[0].point;
}
if (this.floorCollider.Raycast(topRightCorner, out hits[1], 40f)) {
this.topRightPosition = hits[1].point;
}
if (this.floorCollider.Raycast(bottomLeftCorner, out hits[2], 40f)) {
this.bottomLeftPosition = hits[2].point;
}
if (this.floorCollider.Raycast(bottomRightCorner, out hits[3], 40f)) {
this.bottomRightPosition = hits[3].point;
}
this.topLeftPosition = this.minimapCamera.WorldToViewportPoint(this.topLeftPosition);
this.topRightPosition = this.minimapCamera.WorldToViewportPoint(this.topRightPosition);
this.bottomLeftPosition = this.minimapCamera.WorldToViewportPoint(this.bottomLeftPosition);
this.bottomRightPosition = this.minimapCamera.WorldToViewportPoint(this.bottomRightPosition);
this.topLeftPosition.z = -1f;
this.topRightPosition.z = -1f;
this.bottomLeftPosition.z = -1f;
this.bottomRightPosition.z = -1f;
}
public void OnPostRender() {
GL.PushMatrix();
{
GL.LoadOrtho();
GL.Begin(GL.LINES);
{
GL.Color(Color.red);
GL.Vertex(this.topLeftPosition);
GL.Vertex(this.topRightPosition);
GL.Vertex(this.topRightPosition);
GL.Vertex(this.bottomRightPosition);
GL.Vertex(this.bottomRightPosition);
GL.Vertex(this.bottomLeftPosition);
GL.Vertex(this.bottomLeftPosition);
GL.Vertex(this.topLeftPosition);
}
GL.End();
}
GL.PopMatrix();
}
}
3 Likes
I know it’s a super old post, just for people might still need this. I used main camera to cast 4 rays to the 4 corners of screen, then use line renderer to draw the lines between the hit.point, and assign a layer to the game object that is holding the lines so they are only rendered on mini map camera.