Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

(Solved) How would I go about getting a GameObject to face another GameObject?

Discussion in 'Scripting' started by GeekStories, Jan 14, 2019.

  1. GeekStories

    GeekStories

    Joined:
    Jan 22, 2015
    Posts:
    74
    SOLUTION: I ended up centering all the origin/pivot points using ProBuilder and locking the x/z rotation using code.


    I'm making a system where I can dynamically spawn houses next to roads and have the house face the road in the correct orientation.

    I've gotten to the point where I have located and stored the closest (legit) road to the house, all I need to do now is have the house rotate to face the road correctly as it doesn't spawn facing the road. However sometimes it does spawn facing the right way, but its random due to road placement)

    Here is how the map looks when the houses have spawned and found their closest roads (check console)

    As you can see, the left row of houses are all facing the correct way as they spawned facing that way. However the right hand row of houses are all facing the opposite direction. Yes, that row is probably easy to fix, just set the Y to 180 or something.

    But what about the houses that face in the two other directions? How would I get them to face the correct direction.

    Here is my code that spawns the houses and finds their nearest road..

    (This code is wrapped inside a function)
    Code (CSharp):
    1.              
    2. //Grab a random house from the selected type and Instantiate it on to the map.
    3. //Set the parent to the SpawnPoint for proper positioning
    4. house = Instantiate(houseObject[Random.Range(0, houseObject.Length)], spawnPosition.transform.position, Quaternion.identity, spawnPosition.transform);
    5. //Set the position of the house to the position of the SpawnPoint
    6. //This places the house directly in the center of the tile and at an appropriate Y level
    7. house.transform.position = house.transform.parent.position;
    8.            
    9. //Detect the nearest road
    10. //Grab the 4 tiles directly surrounding the house
    11. Vector3[] surroundingTiles = new Vector3[] {
    12.     new Vector3(transform.position.x, 0, transform.position.z-1),
    13.     new Vector3(transform.position.x+1, 0, transform.position.z),
    14.     new Vector3(transform.position.x, 0, transform.position.z+1),
    15.     new Vector3(transform.position.x-1, 0, transform.position.z)
    16. };
    17.  
    18. //Loop through each Vector3
    19. foreach (Vector3 pos in surroundingTiles){
    20.       //MapManager.tiles is a 2D GameObject array used for grabbing a tile at x,z position
    21.       //Set tile to the selected tile
    22.       GameObject tile = MapManager.tiles[(int)pos.x, (int)pos.z];
    23.  
    24.        //Check if the selected tile is tagged a 'Road'. This will be the houses first Road
    25.       if (tile.transform.tag == "Road"){
    26.              //Set the houses rotation to face the road
    27.              //???
    28.              Debug.Log("First road in sight: " + tile.name + ", " + tile.transform.position);
    29.              //Stop looking for a road
    30.              return;
    31.      }
    32. }
    33.  
    One idea I have for this is creating an empty point in the center of each road tile that the house can "LookAt" which is at an appropriate level so that only the Y is changed. However if there is a better way I can do this I would absolutely love to know.

    Any help is appreciated!

    Thank you!
     
    Last edited: Jan 15, 2019
  2. Lurking-Ninja

    Lurking-Ninja

    Joined:
    Jan 20, 2015
    Posts:
    9,931
  3. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,584
    There is many ways of doing such. But lets assume every tile os same regular shape and x/z dimensions.

    You can store these tiles I linear array. Instead having 2d array or list, you have 1d area. And you can calculate neighbour taipes based on index offset in array.

    Now based on that, you can store your tile.class in array, as type. This class will know.type of tile.

    So now you can know types.of surroundings tiles. Which you have kind of as well.
    But based on offset index, you already know, on which side the road is. You can simply store. That information either ax 2d.vector xz, (technically is xy), for which either value can be -1,0,1. Hence x=0,z-1 means facing backwards. Or more convenient for switch statement, store as enumerator values, forward, back, left, right.

    Providing you can have only 4 base rotations, you simply do switch statement check of enumerator, to set appropriate.rotation. Alternatively ifelse check of 2d xz vector.

    Does.that makes sense?
     
  4. GeekStories

    GeekStories

    Joined:
    Jan 22, 2015
    Posts:
    74
    @Lurking-Ninja
    Using LookAt() would take some modification and extra code to ensure only the Y value is rotated, however there must be an easier way. Here is what happens when I simply use LookAt()


    Due to the road tiles origin point being in a weird spot, it looks at the corner. I've already based the map generation off this origin point so changing it would mean re-aligning every single map piece used, and that would take too long.

    @Antypodish

    Sorry, I'm not quite sure what you mean. I don't think I understand.

    First off, every tile does have the same dimensions, every tile looks like this.
    > TILE (this is 0,0,0 rotation and 1,1,1 size)
    >> GRAPHIC (this is rotated and positioned accordingly, dependent on that piece of road that it is)

    From what I'm gathering you're talking about simplifying the block of code that grabs the neighboring tiles?

    I'm not entirely sure how I would use a single array and an index +- offset to grab a tile.
     
  5. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,584
    If you know, that your tile are regular, you can simply add offset, to evaluate center. So if your origin is at 0,0,0, but your boundaries are 1,1,1, then center is 0.5,0.5,0.5. If you move origin by xyz, simply center moves by xyz.

    Yep.
    Lets say you know your map is 20x20 tiles.
    that means 400 tiles in total.
    So now you can have an array of 400 elements.
    Lets say you want to grab tile at 7th column and 5th row and get its neighbors. Btw., GameObject with collider and script can store its index to array, if needed. And of course, you can assign all 4 neighbors of each tile, if you like.
    But with linear array, it would be look like following.
    tile index is 20 * 7 + 5 = 140 + 5 = 145
    You can calculate it back of course, if you know index, to get row and column.
    When you know these, you can easily calculate neighbors indexes.
    • Left 20 * 7 + 5 - 1 = 140 + 5 - 1 = 144
    • Right 20 * 7 + 5 + 1 = 140 + 5 + 1 = 146
    • Up 20 * 7 + 5 - 20 = 140 + 5 - 20 = 145 - 20 = 125
    • Down 20 * 7 + 5 + 20 = 140 + 5 + 20 = 145 + 20 = 165
    Of course, you need take special care at boundaries.

    In smaller case, for board of size 3 x 3 = 9
    • If center is is at index 4;
    • left/right are 3 and 5 index;
    • and up/down are 7 and 1 index;
    And now your collection array, will store 400 elements of type Tile (class).
    And your class Tile, stores references to whatever you need. Is road, is house, is grass, GameObject, collider, etc.
     
  6. GeekStories

    GeekStories

    Joined:
    Jan 22, 2015
    Posts:
    74
    @Antypodish

    I appreciate your input with a different way of grabbing the neighboring tiles, however I already have that working just fine with whats written at the moment. What I'm needing to do is to get the house to face the road when it spawns. I need the house to spin on the y rotation axis to face the road so it looks genuine. However I don't know how to dynamically do that so when the house spawns facing in a random direction (left right forwards or backwards relative to the road) it can be spun to the correct direction regardless.

    Cheers :)
     
  7. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,584
    If you can get relative position of road to house, then you know, on which side the road is. Then simply set rotation using Eulers. In particular case, just Y axis. Don't even need look at.
    For simplicity, ensure that every tile has origin at center position of tile. Not in corner of tile.
    You can achieve this with simple Game Object parenting.