GUITexture Map with clickable areas?

Hello everybody,

I’ve been working on a project lately and have now reached the point where clicking a button this will trigger a “Map_Behaviour” script which will fade in a map ( a whole 1000x1000 2D image, GUITexture) with various red marks on an island, clicking on one of these (named) marks will send a message to Map_Behaviour, which will then do accordingly ( moving stuff etc)

My question is rather simple really, which would be the best method to approach what I want to achieve?

By the tip of my head I can think of the following:

  • Using the Mark textures ( different mark design for mission difficulty) and just do all of the positioning manually, this is the easier approach but I’m worried about the fact that it may be not so much resource friendly
  • Checking for the pixels in which the Mouse clicked and then return to see if they match with a registered location, then do accordingly; While this solution seems less resource intensive texture-wise, I fear it could be coding wise, And I’m not sure if Unity has a way to register an “area of collision” ( for example from pixel x1 to x10, from x10 to y10 to y1 to x1, doing a square area around the mark;

So, to recap, here’s my question, what do you think it’s the bend way to handle what I want to do? and can you think of any other methods?

In order to advise a particular approach, more would need to be know about your particular situation. But let me assume a reasonable number of hotspots (40 or less) of the same size. If this is the case, you could go into Photoshop (or modify the code I have below) to get the pixel offset of each hot spot relative to the lower left corner of the texture. At runtime, you would need to calculate the screen position of the lower left pixel of the GUITexture. Subtracting that from the mouse position will give you the local position in the texture…the same positions that you defined the hotspots.

As for the hit test, assuming you can live all the hotspots the same size, you can either 1) use a distance measure creating circular hotspots or 2) define a rectangle of some size, and use that for a hit test. The code below uses a fixed-size rectangle. If you need various sized hotspots, you’d need to change the code below to an array of Rects rather than an array of Vector2s…and authoring would be more of a challenge.

To use the code below, attach it to some object in the scene, drag and drop the GUITexture on the guitexture variable, open up the hotspots array by clicking on the triangle, set the size of the array, and enter the pixel coordinates relative to the lower left corner of the texture into the slots in the array:

#pragma strict

public var hotSpots : Vector2[];
public var guitexture : GUITexture;

private var leftBottom : Vector3;  // Screen position of the bottom left corner
private var hitRect : Rect = Rect(0,0,35,35);

function Start() {
	leftBottom = Camera.main.ViewportToScreenPoint(transform.position);
	Debug.Log(leftBottom);
	leftBottom.x += guitexture.pixelInset.x;
	leftBottom.y += guitexture.pixelInset.y;
}

function Update() {
	if (Input.GetMouseButtonDown(0) && guitexture.HitTest(Input.mousePosition)) {
	    var localPos = Input.mousePosition - leftBottom;
		Debug.Log(localPos);
		var i = HitTest(localPos);
		if (i == -1) {
			Debug.Log("No hotspot hit");
		}
		else {
			Debug.Log("Hit hotspot #" + i);
		}
	}
}

function HitTest(localPos : Vector3) : int{
	for (var i = 0; i < hotSpots.Length; i++) {
		hitRect.center = hotSpots*;*
  •  if (hitRect.Contains(localPos))*
    
  •  	return i;*
    
  • }*
  • return -1;*
    }
    ‘HitTest()’ returns the index of the hotspot hit. You will need to create some sort of map between the index and the behaviors you want. A value of -1 means no hit.