Search Unity

Finding sprites at coordinates

Discussion in '2D' started by BoomSukka, Aug 23, 2016.

  1. BoomSukka

    BoomSukka

    Joined:
    Aug 23, 2016
    Posts:
    3
    Hi all,

    Is there a simple way to find what sprite(s) are rendered at a particular location? I'm trying to see what tile my player sprite is on and the tiles do not have box colliders. I know that if I must I can store a list of all tiles and search this programmatically, but it would be nice if I could just ask unity.

    Thanks!
     
  2. PeaceLaced

    PeaceLaced

    Joined:
    Jun 2, 2015
    Posts:
    53
  3. BoomSukka

    BoomSukka

    Joined:
    Aug 23, 2016
    Posts:
    3
    Thanks for the help.

    Imagine a tile map and the player moving around on it. Since the map is drawn in the editor, I don't have the tiles in an array so I can't just search through them using the player's current position.

    If I could ask unity what was rendered at certain coordinates I could write the game logic without storing all tile locations internally. I thought of something like 2d ray cast, but apparently this requires box colliders.

    So, does anyone know if unity can be asked what tile (sprite) is at a specific location, or will I just have to either code that tiles into an array or search through all tiles by tag?

    Thanks!
     
    Last edited: Aug 23, 2016
  4. Pagi

    Pagi

    Joined:
    Dec 18, 2015
    Posts:
    132
    I guess you will gave to code it into array, but can you share a screenshot of how you put the tiles in editor? Are they in grid?
     
  5. BoomSukka

    BoomSukka

    Joined:
    Aug 23, 2016
    Posts:
    3
    All I've done is draw my tile map in the editor aligning them to the grid. I suppose I could tag every tile and ask unity for every one and create an array that way but I was thinking the renderer might be able to tell me what it already drew at a given set of coordinates.

    I appreciate your time!
     
  6. takatok

    takatok

    Joined:
    Aug 18, 2016
    Posts:
    1,496
    Unfortunately it can't The standard flow for graphics engine is this: Each object has its own local space (x,y,z axis). Usually the object is located at 0,0,0 in its own local space. They have no knowledge or any interactions with any other object. Then the following things happen:

    1. We use matrices to take every object and place it in a world based on positions we assign the object. (its at 0,0,-60 for example 60 feet away from us on the floor . .or a light might be at 0,10,0 10 feet above us). all the objects are converted to this world space so they have relative position.
    2. We convert them to a camera space based on where the camera is positioned in the world and what its looking at (its angle). You can think of this as spinning the world around and moving it so it lines up with the camera. This is Camera Space
    3. We then take this Camera space and squish all the objects into a 2D rectangle called Screen Space. Various algorithms determines which pixels on a 3d object will be drawn onto the screen (if an object is behind another object, how to project the 3d object onto flat surface given perpective, etc). This final screen space is whats drawn onto your screen.
    At that point unity doesn't really know that the reason tile 27 isn't drawn is because Player Sprite is in front of it. It just has the final Rectangle of pixels. However, it still does have all your objects in memory in world space. So you have 2 options. You create some internal data structures that keep track of where your tiles are and where your player is. You must have some of this already to move the player around. then you would always know which tile he was over. Or you can use the Raycasting functions to shoot a Ray from the camera through your player to see what objects are behind him. Unity Tutorials has some good videos on raycasting.

    Personally I suspect for a 2D game, its probably easier to keep internal data on where you player is and lookup what tile is behind him.
     
  7. Zaflis

    Zaflis

    Joined:
    May 26, 2014
    Posts:
    438
    So you have a 2D array of tiles? If you have tile coordinates evenly spaced, so first tile starts from 0, 0 and next one at 1, 0 it becomes simple math. Take cursor position with for example raycast towards the game scene, intersecting at Z 0. Now if the intersect point is 3.4, 7.8 for example, you can use Mathf.Floor() on both x and y coordinates, to get Int of tile coordinates. Doing so is way way faster than trying to raycast match every single object in existence to find hits. Also instead of raycast there might be some other simpler conversion from screen to world coordinates.
     
  8. imaginaryhuman

    imaginaryhuman

    Joined:
    Mar 21, 2010
    Posts:
    5,834
    I run into this issue from time to time where I have a bunch of stuff in the scene and really need it to be stored in an array or something so I can search through it. Not much way to do it other than literally cycling through all objects and putting them into an array in a script.

    Are your tiles all a certain rectangular size and shape? i.e. in a grid? Because with a 2D array or a wrapped-around 1D array you can easily jump straight to a tile at a given location. But if all your objects are haphazardly placed/sized/rotated etc then its more difficult.
     
    GarBenjamin likes this.
  9. MisterSkitz

    MisterSkitz

    Joined:
    Sep 2, 2015
    Posts:
    833
    Create a palette and apply a 2D tilemmap collider on it. Make the collider an IsTrigger. Place a script on that palette that grabs the player's Transform through either OnTriggerEnter2D or OnTriggerStay2D. If you already know which tiles you want specific events to take place, create an EmptyGameObject, add a 2Dcollider to it, set it to IsTrigger, and add the script to the Empty Object. To make these Empty Objects visible to you for testing, add a Gizmo to it. Yeah, you could tag each of your palettes and use FindObjectsOfType (or is it FindObjectsWithTag ?) and toss them into an array, then test to see if their GameObject's transform matches the player's every frame by use of foreach and then apply an event. However, the approach would depend on what you're trying to accomplish.

    If you give me more details, I can probably help you with some code.