Search Unity

A really stupid issue with rotate

Discussion in 'Scripting' started by count23, Nov 21, 2013.

  1. count23

    count23

    Joined:
    Apr 13, 2012
    Posts:
    30
    Ok, I'm building a really simple project.

    I want to have my game read an XML file and populate a "solar system" based on the details from the XML, I'm not going for anything fancy with physics or the like, rotational axes, periods, etc, are loaded from the XML file. But for the life of me, the one problem I'm having is figuring out how to have an object rotate around a central point. The best I've been able to pull off is having objects rotate around themselves.

    Now what I had proposed was that I'd use rotateAround(<central pivot>, <rotation amount>) as I've found in many tutorials, but now it seems rotate around is deprecated and rotate doesn't seem to accept a centralized pivot.

    How do I use rotate to make an object rotate around a pivot, as well as rotating itself, such as you'd find with a moon orbiting a planet, or a planet orbiting a star.

    The one approach I was looking at was having my moons parented to my planet, my planet parented to my star and so on, but I want ot get the basics down of the various functions before I start looking into parenting, as such, I just want to find out how to make an object rotate around a pivot, preferably without a parented game object to go with it.

    Is this even possible now or do I have to use parenting? The only reason I'm not using parenting yet is I'm still getting the data parsing from XML working properly, so my script is not reading the parent -> child relationships from XML nodes... yet. Plus, I want to be able to set different orbital periods for objects and everything I've read implies that the rotation amounts of child objects is set by the parent's rotation rate.
     
  2. PJRM

    PJRM

    Joined:
    Mar 4, 2013
    Posts:
    303
    Yeah... I had this issue in the past. Unfortunately you have to use parenting. I tried to know how to change the GameObject Pivot position to work exactly how you need, but unity doesn't provide this feature.

    Your issue looks similar to the Uhmari's topic.
     
  3. count23

    count23

    Joined:
    Apr 13, 2012
    Posts:
    30
    Won't parenting cause issues with the rotation effects on children? ie: wont the planets rotation be pushed onto the child object at the same time? That's a lot of math needed to "decelerate" the child objects if that is the case...
     
  4. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    http://docs.unity3d.com/Documentation/ScriptReference/Transform.RotateAround.html

    This will rotate an object around a pivot, as you want, but it will also affect the rotation of that object, EXACTLY as if it was parented to an object at that pivot.

    For getting around rotation inheritance, I would have everything in a hierarchy, but instead, have 'children' follow their 'parents' in script
    myTransform.position = myParentTransform.position
    This lets a 'child' move with it's parent, and then you can handle the rotation seperately
     
  5. count23

    count23

    Joined:
    Apr 13, 2012
    Posts:
    30
    hpjohn, I'm aware of rotatearound, in fact I mentioned it in my opening post. The problem I had was finding a replacement function since it was deprecated which means you can't expect it to be around forever in future releases :)

    I don't want my child objects to be rotated based on the parent rotation, ie: If a planet has some moons, I don't want the moons to rotate at the same day-period that the planet has. That's the problem I have with inheriting via parents. The rotation would be translated to the children.
     
  6. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    yeah, and:
    but typo fail
    I would not have
     
  7. All_American

    All_American

    Joined:
    Oct 14, 2011
    Posts:
    1,528
    Then parent it to a empty gameobject in the same position of the center of whatever...
     
  8. PJRM

    PJRM

    Joined:
    Mar 4, 2013
    Posts:
    303
    Exactly what i meant. I did explain it with pictures in Uhmari's topic (Link to the post above).
     
  9. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    RotateAround is deprecated?
     
  10. DanielQuick

    DanielQuick

    Joined:
    Dec 31, 2010
    Posts:
    3,137
    The 4.3 patch notes say nothing about deprecating RotateAround, and when placing it in a script I get no warnings about it.
     
  11. count23

    count23

    Joined:
    Apr 13, 2012
    Posts:
    30
    I got a message in the monodevelop tool saying it was deprecated and to use "rotate" instead, when I tried to build with it last night.
     
  12. DanW

    DanW

    Joined:
    Nov 4, 2013
    Posts:
    7
    The way I've handled this in the past is
    Find the distance to the center point you want to rotate around,
    Move your object to the center point,
    Do a simple rotation around your axis of choice,
    Translate your position by the previous distance along you objects back vector.

    Tada... This is basically stolen from many an orbit camera implementation.
     
  13. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Or - ya know - just use RotateAround because that's what it was designed to do. :)
     
  14. count23

    count23

    Joined:
    Apr 13, 2012
    Posts:
    30
    Thanks everyone, rotatearound worked eventually, I don't know what I did to get the deprecated command but I've not seen it since.

    Here's a new question, how do I get a child object to rotate around a parent without being affected by the parent's rotation? (Code attached for reference).

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class CO : MonoBehaviour {
    5.  
    6.     string COName;
    7.     int COOffset;           //Distance from Parent object, relative of course
    8.     int COdegrees;          //How many degrees per second will the object rotate
    9.  
    10.     // Use this for initialization
    11.     void Start () {
    12.     }
    13.    
    14.     // Update is called once per frame
    15.     void Update () {
    16.         if (transform.parent != null) { //If the parent is null, we're dealing with the Star, so we don't need to rotate it around it's parent.
    17.                         transform.RotateAround (transform.parent.position, Vector3.up, 50 * Time.deltaTime);
    18.                 }
    19.             transform.Rotate (Vector3.up, COdegrees * Time.deltaTime);  //Rotate clockwise around the parent
    20.     }
    21.  
    22.     public void positionObject(int tCOOffset, int tCOdegrees)   //Set the initial position on creation, will be updated later.
    23.     {
    24.         COdegrees = tCOdegrees;
    25.         COOffset = tCOOffset;
    26.         transform.position = new Vector3(0,0,COOffset);
    27.     }
    28.  
    29.     public void nameObject(string tName)
    30.     {
    31.         COName = tName;
    32.     }
    33.  
    34.     public Transform getSelf()
    35.     {
    36.                 return this.transform;
    37.     }
    38.     void OnMouseDown ()
    39.     {
    40.         print (COName);
    41.         print (transform.position);
    42.         print (transform.parent);
    43.     }
    44. }
    45.  
     
  15. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    I thought that was the point of his thread

    Like i said before:

    code:
    Code (csharp):
    1.     public Transform follow;
    2.     void Update () {
    3.         transform.position = follow.position;
    4.     }
    5.  
     
  16. count23

    count23

    Joined:
    Apr 13, 2012
    Posts:
    30
    The original need of the threat was to figure out how to get rotate around to work because I was getting weird deprecation errors that haven't appeared again. I may have missed your original response suggesting this, i'll try it.

    How would I organize and manage the information then if I'm not using parenting to create a navigable hierarchy? Should I be creating a gameobject reference in my tree-data structure that'd contain a reference to the gameobject at each level? Or is there a better method?
     
  17. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    It's probably a good idea to keep a navigable structure in a centralised location, instead of relying on navigating across gameObjects via transform.parent.xxx and transform.GetChild(x).xxx

    You could still navigate the structure using this non-parenting method by:
    (instead of transform.parent.xxx)
    transform.getComponent<FollowScript>().follow.xxx
    though you cant navigate back down to 'children' without also adding a list of Transforms to the 'parent' object.
     
  18. count23

    count23

    Joined:
    Apr 13, 2012
    Posts:
    30
    That makes sense. Currently my data structure is a simple one:

    Code (csharp):
    1.  
    2. class CODataType {
    3.  
    4.     public string Name;     //Object Name
    5.     public int CODegrees;
    6.     public int COOffset;
    7.     public IEnumerable<CODataType> Children;    //Typed list of all children objects
    8.  
    9.     public CODataType(string name, int codegrees, int cooffset) //Constructor requiring name and spawning empty Child array.
    10.     {
    11.         Name = name;
    12.         CODegrees = codegrees;
    13.         COOffset = cooffset;
    14.         Children = new CODataType[0];
    15.     }
    16. }
    so it contains a reference to all it's children, at least in the terms of the data itself, it shouldn't be too hard to add a gameobject type to this data class so each child can contain a reference to it's child object.
     
  19. count23

    count23

    Joined:
    Apr 13, 2012
    Posts:
    30
    I was just thinking, on the CODataType script, which is essentially just a self rotator the primitive it's attached to (ie: planet/moon/star), can i create a transform variable? or is transform merely a function of gameobject?

    If that's the case, rather then parenting, if i added the "parent's" transform value as a variable in that function and assigned it to a public transform, would it constantly be updated with the movement of the parent? Or do i need to keep passing the parent's position to the child each update?
     
  20. count23

    count23

    Joined:
    Apr 13, 2012
    Posts:
    30
    Ok, I've done this, and it's half working. The first iteration seems to get the 0,0,0 orbit like you'd expect, but the child objects are not circling around the already rotating parents properly, I think something's wrong with the offset math.

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class CO : MonoBehaviour {
    5.  
    6.     string COName;
    7.     int COOffset;           //Distance from Parent object, relative of course
    8.     int COdegrees;          //How many degrees per second will the object rotate
    9.     Transform targetTransform;    //This is the location of the "parent" object to use for local coordinate settings
    10.  
    11.     // Use this for initialization
    12.     void Start () {
    13.     }
    14.    
    15.     // Update is called once per frame
    16.     void Update () {
    17.         if (targetTransform != null) {  //If the parent is null, we're dealing with the Star, so we don't need to rotate it around it's parent.
    18.                         transform.RotateAround (targetTransform.position, Vector3.up, 50 * Time.deltaTime);
    19.                 }
    20.             transform.Rotate (Vector3.up, COdegrees * Time.deltaTime);  //Rotate clockwise around the parent
    21.     }
    22.  
    23.     public void positionObject(int tCOOffset, int tCOdegrees, Transform tTransform) //Set the initial position on creation, will be updated later.
    24.     {
    25.         COdegrees = tCOdegrees;
    26.         COOffset = tCOOffset;
    27.         targetTransform = tTransform;
    28.         transform.position = new Vector3(0,0,COOffset);  //Set initial position of child object
    29.     }
    30.  
    31.     public void nameObject(string tName)
    32.     {
    33.         COName = tName;
    34.     }
    35.  
    36.     public Transform getSelf()
    37.     {
    38.                 return this.transform;
    39.     }
    40.     void OnMouseDown ()
    41.     {
    42.         print (COName);
    43.         print (transform.position);
    44.         print (transform.parent);
    45.     }
    46. }
    I tried setting the starting position of the object as tTransform.position.x + COOffset but it didn't seem to work, the child objects appear to randomly flutter off elsewhere.

    I know the script is getting the transform from each "parent" iteration properly, I checked that running debugs, so tTransform in positionObject should be the parent object that needs to have it's position translated to the child, but I just can't seem to figure out why the child is not positioned correctly. I'm also convinced that if I move the central parent object (the one that's at 0,0,0) the first level children will have a weird position as well.

    I just can't figure out what in this script is throwing the "moons" into such strange orbits. What am I missing in the "update" or the "position" calculations that could account for this?