Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

How to position obj1 over obj2 without obj1 being child of obj2?

Discussion in 'Scripting' started by Rusoski, Aug 3, 2017.

  1. Rusoski

    Rusoski

    Joined:
    Nov 6, 2013
    Posts:
    63
    Untitled-2.png

    Looking at the image I am trying to place some packages and books over a bookshelf.

    For this purpose I am using the shelf's position and rotation to spawn books in the worlds, also I can choose how many books spawn and in what positions whit this piece of code:

    Code (CSharp):
    1. public void CalculatePosition() {
    2.         float surfaceSize = 1.4f;
    3.         int totalSection = int.Parse(sectionsCount);
    4.         int section = int.Parse(asociatedSection);
    5.         float sectionSize = surfaceSize / totalSection;
    6.         float halfOfASection = sectionSize / 2.0f;
    7.         float r = 0;
    8.  
    9.         r = halfOfASection + (sectionSize * (section - 1));
    10.         r = r * 2 - surfaceSize;
    11.  
    12.         float x = cube.transform.position.x;
    13.         float z = cube.transform.position.z;
    14.         Vector3 vec = new Vector3(r, 0.2f + int.Parse(asociatedLevel), 0.0f);
    15.         Vector3 vec2 = new Vector3(x, 0.0f, z);
    16.         Vector3 vec3 = vec + vec2;
    17.  
    18.         this.cube.transform.position = vec3;
    19.     }
    20.  
    21.     public void CalculateSize() {
    22.         float surfaceSize = 1.4f;
    23.         int totalSection = int.Parse(sectionsCount);
    24.         int section = int.Parse(asociatedSection);
    25.         float sectionSize = surfaceSize / totalSection;
    26.         float halfOfASection = sectionSize / 2.0f;
    27.         float r = 0;
    28.  
    29.         r = sectionSize - (sectionSize / 100);
    30.  
    31.         this.cube.transform.localScale = new Vector3(r, 0.75f, 1.0f);
    32.     }
    This works perfect while shelf's rotation over y axis is 0°, but I am not doing with the z axis. I think if the "surfaceSize", it should not be just for x, but most likely be the radius.

    Set a book as child of the book shelf is not an option.

    I need help with the equation to make this work. I have acess to the bookshelf object from the book object.

    It's more about trigonometry, I need a function that give the next result:

    Given the angle of y axis:

    1)
    - If angle = 0° o 360°, then value = 0
    - If angle = 90°, then value = 1
    - If angle = 180, then value = 0
    - If angle = 270, then value = -1

    2)
    - If angle = 0° o 360°, then value = 1
    - If angle = 90°, then value = 0
    - If angle = 180, then value = -1
    - If angle = 270, then value = 0

    But I need a constant change, for example at 45° value to be 0.5, not 0.7~
     
    Last edited: Aug 3, 2017
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,369
    If you can't parent something, you can always manually copy the transform.rotation component from one object to another, generally AFTER the first object is rotated.

    But in the case above you also have to "back out" the relative offset position (what WOULD be the local position if you could parent the objects), then rotate that around the axis of original object, and add that new offset to to the new "pseudo child" position.

    Order of operation is important. Imagine if I was trying to follow a rotating object on the ground: if it was to rotate, I would have to "swing through" an arc. I could do this by first walking to the center of the rotating object to find how far I am from it (backing out my local position), then rotating in place with it (copying the object's new rotation to my transform), then "walking back" the same distance in the new direction (re-adding the rotated local position along my new "backwards" vector).

    You can rotate a Vector3 around an arbitrary rotation with multiplication:

    Code (csharp):
    1. Vector3 foo = Vector3.up;
    2. Quaternion rotation = Quaternion.Euler( 0, 0, 90);
    3. foo = rotation * foo; // now foo will be rotated 90 degrees along the Z
     
    Rusoski likes this.
  3. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,353
    You don't have to have an object as a child of a different object in order to position it relatively. Just use transform.TransformPoint to get the position in local space. So instead of:

    Code (csharp):
    1. this.cube.transform.position = vec3;
    do

    Code (csharp):
    1. this.cube.transform.position = shelfTransform.TransformPoint(vec3);
    That assumes that your shelf isn't scaled.
     
    Rusoski likes this.
  4. Rusoski

    Rusoski

    Joined:
    Nov 6, 2013
    Posts:
    63
    Thank you for your support.

    May be you are not fully understand me or I not fully understand you. My intentions are more like to play with transform.position rather than with transform.rotation, because I already got the rotation going on, the problem is that I can not get the books in the right place.

    I was wondering if Unity has support for something like Blender, I mean, in Blender when you move an object using 'Global Transform Orientation', you move the object over world's x, y, x, no matter if the object is rotated and if you chose to move the object using 'Normal Transform Orientation', the object moves over x, y, z depending on the angles of each axis.

    Iam getting close, but not done yet with this:

    Code (CSharp):
    1. Vector3 vec = new Vector3(r * Mathf.Cos(angleY), 0.2f + int.Parse(asociatedLevel), r * Mathf.Sin(angleY));
    Lets say this, I got obj1 and obj2. Obj1 is the shelf and obj2 is a book is inside a List. My question is if I set obj2 as child of obj1, will obj1 and obj2 become a whole object and obj2 will be removed from to list to somewhere else?

    This, because I need to control all the books from a list. But if I can set the relation and still access the child from the list, then it will do it.
     
    Last edited: Aug 3, 2017
  5. Rusoski

    Rusoski

    Joined:
    Nov 6, 2013
    Posts:
    63
    This is what it looks like,when the shelf's Y axis angle is 0°, but when I rotate it the books are placed only over X axis, I am not considering Z axis the formula, that is why it looks lweird.
     

    Attached Files:

  6. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    If I haven't misunderstood the problem completely, you should be able to solve that much more easily with the information that you can already retreive from the bookshelf's transform component.

    That is, you can retreive relative directions in world space, such as right, left, forward etc.

    Note that I assume the model itself wasn't created or exported in a weird way, so the shelf aligns properly.

    Have a look at this simplified example, which basically only relies on the bookshelf's rotation and the transform's right-direction and the sake of brevity starts to place objects at the bookshelf's pivot point:

    Code (CSharp):
    1. public class Placement : MonoBehaviour
    2. {
    3.     [SerializeField]
    4.     private Transform _bookshelf;
    5.     [SerializeField]
    6.     private Transform _bookPrefab;
    7.  
    8.     [SerializeField]
    9.     private float _spacing = 0.2f;
    10.  
    11.     private void Start ()
    12.     {
    13.         var placementPosition = _bookshelf.position;
    14.         var placementRotation = _bookshelf.rotation;
    15.         var placementDirection = _bookshelf.right;
    16.  
    17.         for (int i = 0; i < 10; ++i)
    18.         {
    19.             var book = Instantiate(_bookPrefab, placementPosition, placementRotation);
    20.             placementPosition = placementPosition + (placementDirection * _spacing);
    21.         }
    22.     }
    23. }
    Unless I'm completely wrong and missed the point of the thread, this should be everything needed to align your books with the shelf.
    Of course you have to apply your own spacing (algorithm) and provide the different placement positions & heights, but that shouldn't be much of a problem.

    *Edit

    Here's how they're placed / aligned (ignore the offsets, that's up to you :p):
     
    Last edited: Aug 3, 2017
    Rusoski likes this.
  7. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,353
    Nope! They're still independent objects.

    This isn't blender python scripting, where your data changes under you because you changed something unrelated.
     
    Rusoski likes this.
  8. Rusoski

    Rusoski

    Joined:
    Nov 6, 2013
    Posts:
    63
    Problem solved with the next ecuation:


    Code (CSharp):
    1. public void CalculatePosition(GameObject Rack) {
    2.  
    3.         float x = cube.transform.position.x;
    4.         float z = cube.transform.position.z;
    5.         float angleY = Rack.transform.eulerAngles.y;
    6.  
    7.         float surfaceSize = 1.4f;
    8.  
    9.         int totalSection = int.Parse(sectionsCount);
    10.         int section = int.Parse(asociatedSection);
    11.  
    12.         float xSize = surfaceSize * Mathf.Cos(Mathf.PI * -angleY / 180);
    13.         float zSize = surfaceSize * Mathf.Sin(Mathf.PI * -angleY / 180);
    14.  
    15.         float sectionSizeX = xSize / totalSection;
    16.         float halfOfASectionX = sectionSizeX / 2.0f;
    17.  
    18.         float sectionSizeZ = zSize / totalSection;
    19.         float halfOfASectionZ = sectionSizeZ / 2.0f;
    20.  
    21.         float r1 = halfOfASectionX + (sectionSizeX * (section - 1));
    22.         r1 = r1 * 2 - xSize;
    23.  
    24.         float r2 = halfOfASectionZ + (sectionSizeZ * (section - 1));
    25.         r2 = r2 * 2 - zSize;
    26.  
    27.         Vector3 vec = new Vector3(r1, 0.2f + int.Parse(asociatedLevel), r2);
    28.         Vector3 vec2 = new Vector3(x, 0.0f, z);
    29.         Vector3 vec3 = vec + vec2;
    30.  
    31.         this.cube.transform.position = vec3;
     
    Last edited: Aug 3, 2017
  9. Rusoski

    Rusoski

    Joined:
    Nov 6, 2013
    Posts:
    63
    Thank you! But I can't use a for loop to place the books because they are in a Dictionary made of Lists and they are not sorted. Also because the amoun of books is not always the same it dynamicaly changes.
     
  10. MadeFromPolygons

    MadeFromPolygons

    Joined:
    Oct 5, 2013
    Posts:
    4,002
    you can do a foreach which will work on dictionaries. foreach(KeyValuePair<KeyType, ValueType> item in dictionaryCollection)
    {
    something = item.etc // this is where you do stuff with item
    }

    EDIT: this will take into account dynamically sized collections too. Have fun!

    EDIT2: We have many dictionaries made up of lists and we do this kind of iterative structue to go through them. We actually have dictionary with dicitonaries inside that have lists inside that, and we can still do a foreach within a foreach etc...

    Hope this helps.
     
    Rusoski likes this.
  11. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    That's just meant to be a working example which uses the loop to demonstrate the result. It doesn't really matter where you get the books from. It's all about the part within the loop. That's how you can easily determine positions aligned to the shelf.
     
    Rusoski likes this.