Picking up all tiles/cells/objects from isometric tilemap under mouse selection area.

So I’ve a bit of an interesting problem with isometric tilemaps in Unity.
I have a two dimensional array of gameobjects. The position of the objects in this array determines where their associated sprites are rendered on an isometric tilemap.

I can then currently click on a position on the tilemap and get an associated gameobject in two ways.
Use

var worldPos = Camera.main.ScreenToWorldPoint(Input.MousePosition);
var tilePos = sampleTilemap.WorldToCell(worldPos);

To get the tile/cell position, then use that position to get the object from the array.

Give the object a Collider2d in world space and use

var worldPos = Camera.main.ScreenToWorldPoint(Input.MousePosition);
var hit = Physics2D.OverlapPoint(worldPos);

to get the collider that has reference to the associated gameobject.

But the question now comes is what to do if I want to mouse select an area to get multiple objects at once?
First solution is to give every gameObject an associated Collider2D shape and then use

var hits = Physics2D.OverlapArea(startPos, endPos);

But as the scene has over 10,000 trees that’s a lot of colliders to instantiate on scene load and should I be worried about memory usage?

Secondly I could get the tile/cell positions that lie under the selection area using the following and some algebra.

if (Input.GetMouseButtonDown(0))
{
    _startPos = InputController.MousePosition;
}

if (Input.GetMouseButton(0))
{
   _endPos = InputController.MousePosition;

   var startWorldPos = Camera.main.ScreenToWorldPoint(_startPos);
   var endWorldPos = Camera.main.ScreenToWorldPoint(_endPos);

//get corner tiles
//algebra to get all included tiles in selection area

To get the below image.
8629143--1159797--tilemap selection.png
But is that a lot of work to be doing during one update frame?

If anyone has a more elegant solution or more widely used solution I would gladly appreciate it.

Your solution is probably fine and may not be worth optimizing. There’s no Unity API to do those tests for you.

You’re probably already doing this roughly:

  1. Get the red RectInt of min/max cells.
    2. Test every cell whether it’s in the blue box.

8640579--1162125--d - Copy.png

I’ll describe an alternative testing for #2 that you can compare against your current solution:

  1. Convert corners of blue box into grid/cellspace. This skips worldspace conversions later.
  2. With those 4 points (ABCD), create two triangles: ABC, BCD.
  3. Iterate your RectInt (red box) to test the centerpoint (+.5, +.5) of each cell against those two triangles. Compare the center point of each red box cell against two triangles.

How to cheaply test whether a point is in triangle? This is a simple way.

    public static bool PointInTriangle_Fast(Vector2 pt, // tested point
   Vector2 v1, Vector2 v2, Vector2 v3) // triangle points
    {
        static float GetSign(Vector2 p1, Vector2 p2, Vector2 p3)
        {
            return (p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y);
        }

        float s1 = GetSign(pt, v1, v2);
        float s2 = GetSign(pt, v2, v3);
        float s3 = GetSign(pt, v3, v1);

        bool neg = (s1 < 0) || (s2 < 0) || (s3 < 0);
        bool pos = (s1 > 0) || (s2 > 0) || (s3 > 0);

        return !(neg && pos);
    }

If the triangle test looks like less work than what you’re currently doing algebraically then maybe it’s better.