Search Unity

Help With Local, Relative Coordinates

Discussion in 'Editor & General Support' started by Marble, Jul 10, 2006.

  1. Marble

    Marble

    Joined:
    Aug 29, 2005
    Posts:
    1,268
    I'm getting confused working between local and world coordinates and was wondering if someone could help me with this:

    I'm raycasting onto an empty object that has 16 planes as children. The children form the squares of a 4x4 grid and are individually named.

    Code (csharp):
    1. function Track() {
    2. var contact : RaycastHit;
    3.  
    4. if (Physics.Raycast (transform.position, Vector3.down, contact)) {
    5.  
    6. Debug.Log("The ray hit a collider belonging to " + contact.transform.gameObject.name); // 1
    7.  
    8. Debug.Log("The collider has a transform at position " + contact.transform.InverseTransformPoint(position)); // 2
    9.  
    10. Debug.Log("With root " + contact.transform.root.gameObject.name); // 3
    11.  
    12. Debug.Log("The ray hit local coordinate " + contact.transform.InverseTransformPoint(contact.point) ); // 4
    13. }
    14. }
    I would like to get the coordinate of the raycast hit relative to the transform of the individual grid member it hits, not its parent and not the world.

    When run, the lines print:
    1. The name of the individual square the ray has hit - so far so good.
    2. Prints 0, 0, 0 no matter where the ray hits - seems right since the local position of each child transform should be 0,0,0 right?
    3. The name of the parent - that's ok.
    4. a Vector3 that is relative to the parent, a.k.a 0,0,0 is at the origin of the parent no matter which child name is printed at line 1. - what? I want it relative to the child!

    I think I must be missing something simple, so hopefully it will be simple to answer. Thanks!
     
  2. yellowlabrador

    yellowlabrador

    Joined:
    Oct 20, 2005
    Posts:
    562
    I'm still a newb so not sure here, but did you try

    Code (csharp):
    1.  
    2. transform.localPosition = Vector3(0,0,0);
    3.  
    from the manual

    Code (csharp):
    1.  
    2. // Move the object to the same position as the parent:
    3. transform.localPosition = Vector3(0, 0, 0);
    4.  
    5. // Get the y component of the position relative to the parent
    6. // and print it to the Console
    7. print(transform.localPosition.y);
    Ray
     
  3. hsparra

    hsparra

    Joined:
    Jul 12, 2005
    Posts:
    750
    I do not quite follow what you are saying. Are you saying it always print 0,0,0, or that it is realative to 0,0,0? Are you sure it is the parent? Have you printed out the parents position in world coordinates, the childs position in world coordinates, and the RaycastHit in world coordinates? If I a not too mistaken, the documentation seem to indicate the line
    Code (csharp):
    1.  
    2. contact.transform.InverseTransformPoint(contact.point)
    3.  
    should print the raycast hit relative to the whatever transform you hit, which should be the child. Does the above line produce a position close to 0,0,0 when you hit near the center of one of the planes? I would be interested in what printing out the RaycastHit position produces.

    Unfortunately I do not have Unity handy at the present time so I can not do a test :(
     
  4. Joachim_Ante

    Joachim_Ante

    Unity Technologies

    Joined:
    Mar 16, 2005
    Posts:
    5,203
    I guess you have a rigidbody as the parent of the planes?

    In that case contact.transform returns you the transform attached to the rigidbody. Not the collider.

    so you can use:
    contact.collider.transform.InverseTransformPoint(contact.point);
     
  5. Marble

    Marble

    Joined:
    Aug 29, 2005
    Posts:
    1,268
    Sorry I took so long to reply. Vue corrupted a bunch of my assets and it took several days to repair the damage!

    I'm not doing so well communicating my problem, let's try simplifying the scenario:

    My grid is just four square planes that belong to a parent at (1, 1, 1). Each quadrant has a collider, but no rigidbody, and are named Q1, Q2, Q3, Q4. The parent is named "Grid." A point above the parent is casting rays against the surface.

    Let's say the raycast hits the surface of Q1.

    contact.transform.gameObject.name returns "Q1"

    contact.transform.parent.name returns "Grid"

    contact.point returns (-.5, 1, .5)

    contact.transform.position returns (1, 1, 1)

    contact.transform.localPosition returns (0, 0, 0)

    The transform returned by contact appears to be the transform of the parent "Grid," but contact is returning the name of the child gameObject. If I could get the position of the child transform I would be set.

    Thanks for sticking with me.
     
  6. Talzor

    Talzor

    Joined:
    May 30, 2006
    Posts:
    197
    The transform returned by the raycast is the transform of whatever object that is hit, in this case the plane.

    contact.transform.InverseTransformPoint(contact.point) will give you the position of the hit relative to the plane. I've tried you simple setup with the script below and it work fine, so something else must be the matter. If you are interested you can send me you test scene (or post it) and I will be happy to take a look at it.

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class RayCast : MonoBehaviour {
    5.  
    6. void Update() {
    7.     RaycastHit hit;
    8.     Physics.Raycast(transform.position, Vector3.down, out hit);
    9.    
    10.     Transform planeTransform = hit.transform;
    11.     Transform gridTransform = hit.transform.parent;
    12.     GameObject plane = planeTransform.gameObject;
    13.     GameObject grid = gridTransform.gameObject;
    14.    
    15.     Debug.Log("Hit: " + plane.name + " at: " +
    16.      hit.point + " (global), " +
    17.      planeTransform.InverseTransformPoint(hit.point) + " (local to " + plane.name + "), " +
    18.      gridTransform.InverseTransformPoint(hit.point) + " (local to " + grid.name + ")");
    19.  
    20.     Debug.Log("Position of " + plane.name + ": " +
    21.      planeTransform.position + "(global), " +
    22.      gridTransform.InverseTransformPoint(planeTransform.position) + " (local to " + grid.name + ")");
    23.     Debug.Log("Position of " + grid.name + ": " +
    24.      gridTransform.position + "(global), " +
    25.      planeTransform.InverseTransformPoint(gridTransform.position) + " (local to " + plane.name + ")");
    26.     }
    27. }
    28.  
     
  7. Marble

    Marble

    Joined:
    Aug 29, 2005
    Posts:
    1,268
    Here's the project (with most textures removed for size). You'll find most of the action in the SatelliteBehavior javascript. The script in your post above still returns that the child and the parent transforms are in the same position.

    EDIT: For easy testing, start the game and click in the margins of the window (even though it's all while right now). The satellite will track a player object across the grid surface, casting rays near its position on the mesh.
     

    Attached Files:

  8. Talzor

    Talzor

    Joined:
    May 30, 2006
    Posts:
    197
    The reason your are getting the same position is that all the planes and the grid ARE at the same position. You can see this in the inspector, notice how all the transforms of the planes say (0, 0, 0). this is their position relative to the parent (the inspector always show coordinates relative to the parent). Your problem lies in your meshes. For some reason they are not centered on themselves. E.g. if you drag one of them into the scene, just as lone object, without a parent, and set it's position to (0, 0, 0) you will notice that it isn't, in fact, in the middle of the world. Exactly why this happens or how you fixes it I don't know (I'm a programmer and know nothing about Cinema 4D), but I'm sure that there is someone else here with that knowledge.
     
  9. Marble

    Marble

    Joined:
    Aug 29, 2005
    Posts:
    1,268
    Oh weird. Thanks for that. And here I was obsessing over the script.