0
\$\begingroup\$

In a 3D Scene, I have a table asset on which sits a game board asset, displaying a map with countries. My map is quite large- 7776 × 3456 pixels. The Main Camera looks down at an angle, can be moved via WASD controls, and be zoomed in/out by moving along its local Y axis (relative to the "look down" angle). This is all working well.

Next, I want to identify, and highlight, the "region" on the map (country, ocean, etc.) under the mouse cursor. Region borders are irregular (like a world map). The region count will be under 255, so I could use a single byte index to identify each region. I have a strategy that I believe should work:

  1. Create another copy of my map image, painting each region in a different color (call this the "country mask"). If I can save this as a "palletized" image, or a single-channel greyscale image, I can just use the pixel value (0-255) as the index of the map region. Load this into memory without displaying it.
  2. Trace a ray from the camera, through the mouse, onto the game board map, getting the coordinates on the map (texture) where the ray hits.
  3. Use those coordinates to get the color of the same location on the Country mask, and read the pixel value to get the map region index. This solves the Identification requirement.
  4. To solve the highlighting requirement, use the country mask in some fashion to highlight the hovered country. For example, if map region 29 is selected, I should be able to identify all pixels in the country mask with pixel value 29, then use that as a mask to apply some sort of effect on the actual map for just those pixels.

This leads me to the following questions:

  1. What's the most efficient way to load the country mask as a 2D array of index values? Ideally, 1 byte per pixel as opposed to 3 or 4 color channels.
  2. Is there a particular image format that I should use for the mask texture asset to facilitate this (e.g., storing only 1 byte per pixel).
  3. What's the right way to implement step 4? I'm sure that iterating all the pixels in both images via x/y loops would be very slow.
\$\endgroup\$
2
  • \$\begingroup\$ I'm not familiar with masks but if I wanted to achieve a similar result to yours, I would: separate the regions of the map, give each a trigger collider, and once the cursor is inside the collider I would use another script - that is attached to every region - and "highlight" the region attached to the script \$\endgroup\$
    – Arian_ki
    Mar 14 at 7:26
  • \$\begingroup\$ With a collider, you can just use OnMouseOver() and OnMouseExit(). \$\endgroup\$
    – Zibelas
    Mar 14 at 7:59

1 Answer 1

1
\$\begingroup\$

I solved this problem once by creating my map in Blender and then slicing it into separate objects for each region. The map doesn't even need to be 3d for that. You can just create a plane, put your 2d map texture on it, and then slice it.

Or alternatively, if you want to do this completely within Unity, you can do that with ProBuilder. Create a plane with your map texture, and then use the "Cut" and "Detach faces" tools to slice it into countries.

That way each country is now a separate gameObject with a separate mesh and an own MeshCollider. This also allows to change the material properties of each country individually. You can use that to color countries depending on who controls them or highlight the country under the mouse cursor.

\$\endgroup\$
3
  • \$\begingroup\$ Sorry, I've not used Blender before, but I'll try to figure it out. When you say to "put your 2d map texture" on the plane, do you mean this process? blender.stackexchange.com/questions/81042/… \$\endgroup\$ Mar 14 at 15:39
  • \$\begingroup\$ @JasonClark Yes. I recommend everyone who wants to make 3d games to acquire at least a cursory knowledge of Blender (or a similar 3d modeling program). That way you don't need to ask an artist or comb the asset store for even the most simplest of 3d models. \$\endgroup\$
    – Philipp
    Mar 14 at 15:44
  • \$\begingroup\$ @JasonClark Although if you want to do this completely within Unity, you could also do this with ProBuilder. \$\endgroup\$
    – Philipp
    Mar 14 at 16:02

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .