May 262017
 
K Hi there, time for a new Unity tutorial.

Now you might remember my old image map tutorial, well I remade it in video for your viewing pleasure.

This is basically usuable for raycasting an object and get the color of the pixel on the texture you hit. This can be used to create a color picker or an image map, where you have a texture with different hot spots.

 

If you like this post, then please consider retweeting it or sharing it on Facebook.

 Tagged with: , ,
Oct 252015
 

Hello Friends of Carlotta (<- Movie reference).

I just had a long day accompanied by a headache so intense that my day felt slightly askew, so what better remedy than working with Unity?

Not really having any direct train of thought I stumbled upon this in the Unity documentation describing how to get the pixel of the texture on the material where you clicked with the help of the texture coordinate.

Thinking back this is what I used to do when doing 2D games for point & click adventure games or top down games where I could bake in information in the level and react on it, for example if a car drove over a yellow field in the map it would get a speed boost.

First we need the image we want to display in the game, that is easy enough and I chose this one here from when we were visiting a conference that Swedish Game Awards were hosting back in April, then we also need the hot spot image, you basically copy the original image painting over any hot spots with a unique color leaving everything else white, transparent or whatever is to your liking, just remember to so you do not accidentally use it as a hot spot color later on.

KJ and S visiting SGA Conference

KJ and S visiting SGA Conference

 

 

 

 

 

 

 

 

 

 

Hot spot map

Hot spot map

 

 

 

 

 

 

 

 

 

Texture Settings

Texture Settings

Importing these assets into Unity you need to apply some settings to the map texture. You need to make it read/write enabled, I also changed compression type to RGB 16 bit so that my colors did not get compressed and modified (this reduces the amount of colors you can use but still should be more than enough).

After creating the material you put it on your mesh and you need to add a collider to that object so we can use raycast on it, that collider MUST be a mesh collider otherwise we will not be able to get the texture coordinate, something we must be able to do to get this to work.

On to the code, the way I set it up was that when you press the left mouse button it will make a raycast if it hits a mesh collider with the selected layer it will take the texture coordinate and translate that into a pixel which you use to check on your map texture and retrieve the color.

Create a script that you will later place on your mesh object.

using UnityEngine;
using UnityEngine.UI;

public class ImageMap : MonoBehaviour
{
   public Text textbox;
   public float rayDistance = 50f;
   public LayerMask layer;
   public Texture2D clickTexture;

   public Color[] colors;
   public string[] texts;
}

So I will get the color the user clicked, find the corresponding string connected to that color and set the text of my textbox to that value. I will start by implementing the method that finds the index of the color in my colors array so I can use that in my string array to find the correct text.

private int FindIndexFromColor(Color color)
{
   for (int i = 0; i &amp;amp;lt; colors.Length; i++)
   {
      if (colors[i] == color)
      {
         return i;
      }
   }
  return -1;
}

Now we are ready to get to the part where we get the color from the image map from where we clicked.

void Update()
{
   RaycastHit hit;
   if (Input.GetMouseButtonDown(0) && Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit, rayDistance, layer))
      {
         Renderer renderer = hit.transform.GetComponent<MeshRenderer>();
         Texture2D texture = renderer.material.mainTexture as Texture2D;
         Vector2 pixelUV = hit.textureCoord;
         pixelUV.x *= texture.width;
         pixelUV.y *= texture.height;
         Vector2 tiling = renderer.material.mainTextureScale;
         Color color = clickTexture.GetPixel(Mathf.FloorToInt(pixelUV.x * tiling.x), Mathf.FloorToInt(pixelUV.y * tiling.y));
 
         int index = FindIndexFromColor(color);
         if (index >= 0)
         {
            textbox.text = texts[index];
         }
      }
}

So I basically check to see if the user just pressed down the left mouse button and if the raycast hit anything of interest, I placed all my Image Map objects into a special layer just for them in this example.
If I did click a valid object I find the texture on it and check what texture coordinate the user pressed, calculate that into a pixel on the texture and check tha corresponding pixel on my texture map “clickTexture” taking into account the scale of the material (that way it will still work if you have tiled it).

The result

Hotspots result

Hotspots result

And that is it, my headache is gone, my energy is up so good luck and I might see you after my refreshing stroll in our refreshing autumn weather we are having here in Sweden today.

// Krister

 Tagged with: , ,