Search Unity

Noob question about physics...?

Discussion in 'Physics' started by jessechunn, Mar 14, 2018.

  1. jessechunn

    jessechunn

    Joined:
    Jun 10, 2015
    Posts:
    18
    Simple scene, 2 cubes, both with box colliders, white one with rigidbody, orange one below it acting as "rotating floor" with no rigidbody. Why doesn't white one rotate with orange one (see video at


    Here is the script on the orange one:
    Code (csharp):
    1. public class RotateCube : MonoBehaviour {
    2.     public float speed = 9f;
    3.     // Use this for initialization
    4.     void Start()
    5.     {
    6.     }
    7.     // Update is called once per frame
    8.     void Update()
    9.     {
    10.         transform.Rotate(Vector3.up, speed * Time.deltaTime);
    11.     }
    12. }
     
    Last edited: Mar 14, 2018
  2. jessechunn

    jessechunn

    Joined:
    Jun 10, 2015
    Posts:
    18
    I would appreciate any feedback on my thoughts here...
    I "think" the answer is to child everything I want to rotate with the orange cube under the orange cube (or an empty "ground" gameobject that holds both cubes has the rotation script). Right? This appears to apply centrifugal force to the children (at least at first glance) which I suppose is to be expected. Right?
     
  3. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,195
    For those object to interact, I believe you'll need to place a Rigidbody on the "floor" object, set it to Kinematic, and then rotate it using rigidbody methods, like Rigidbody.MoveRotation.

    In general, be careful about moving rigidbody objects using "transform". That tends not to play nicely with the physics system.
     
    jessechunn likes this.
  4. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,195
    Yeah, that should work. You'd do something like this in your update method:

    Code (CSharp):
    1.  
    2. rb.MoveRotation(Quaternion.Euler(rb.rotation.eulerAngles + Vector3.up * Time.deltaTime * 300));
    Note that the object could slide off the spinning platform if the platform spins too quickly, just like a cube would fall off a merry-go-round if it were going fast enough. No need to parent anything. (You could parent things, if you wanted to bypass using physics to keep the objects together. That's up to you depending on how you want your game to work.)
     
    jessechunn likes this.
  5. jessechunn

    jessechunn

    Joined:
    Jun 10, 2015
    Posts:
    18
    THANKS!!!
    Before reading your second reply, I did this:
    Code (CSharp):
    1.  
    2.         //transform.Rotate(Vector3.up, speed * Time.deltaTime);
    3.         Vector3 v = new Vector3(0, speed * Time.deltaTime, 0);
    4.         Quaternion deltaRotation = Quaternion.Euler(v);
    5.         GetComponent<Rigidbody>().MoveRotation(transform.rotation * deltaRotation);
    ...which works exactly as intended... and yes, it will sling the white cube off like a merrygoround if the orange cube is spinning too fast :)
    Thank you so much for your help!
     
  6. jessechunn

    jessechunn

    Joined:
    Jun 10, 2015
    Posts:
    18
    One minor change that I think I need to make:
    Code (CSharp):
    1.         //transform.Rotate(Vector3.up, speed * Time.deltaTime);
    2.         Vector3 v = new Vector3(0, speed * Time.deltaTime, 0);
    3.         Quaternion deltaRotation = Quaternion.Euler(v);
    4.         //GetComponent<Rigidbody>().MoveRotation(transform.rotation * deltaRotation);
    5.         GetComponent<Rigidbody>().MoveRotation(GetComponent<Rigidbody>().rotation * deltaRotation);
    I will need to play with it more, but I think I need to use the rigidbody.rotation instead of the transform.rotation. It doesn't make any difference in this simple example, but I assume that there are situations where using transform.rotation might throw things out of whack.
     
    Last edited: Mar 14, 2018
  7. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,195
    Yeah, stick with the Rigidbody's rotation.

    A couple of other things to mention:
    • I should have said that the MoveRotation should ideally be called in the FixedUpdate method, not the Update method. In that case, you wouldn't use Time.deltaTime anymore, and you'd just increase the speed accordingly. Generally, calling physics-based methods within Update is not advised, as framerate will impact the physics simulation in ways you don't want.
    • To avoid general performance issues, try not to call GetComponent, or GameObject.Find* methods in Update/FixedUpdate. Instead, cache the object in the Start method, and refer to it later. Those Get/Find methods are expensive. So, instead, you'd do something like this:
    Code (CSharp):
    1. private Rigidbody _rb;
    2.  
    3. void Start() {
    4.     _rb = GetComponent<Rigidbody>();
    5. }
    Then you can refer to _rb within your FixedUpdate method.
     
  8. jessechunn

    jessechunn

    Joined:
    Jun 10, 2015
    Posts:
    18
    Your point about using the FixedUpdate method begins to explain an issue I am seeing where the movement of the platform is occasionally "jerky", and I suspected as much.
    What I didn't understand is what you mean about not using the time.deltatime and instead just increasing the speed accordingly. Any chance you could elaborate on that a bit?
    PS: Your point about calling getcomponent repeatedly is something I already knew (I am a long-time c# programmer). I was just keeping it simple for the sake of testing/discussing, but I do appreciate you pointing it out.
     
  9. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,195
    Update gets called at uneven/unpredictable intervals. If the game gets bogged down, the framerate will drop, and Update will be called less frequently. However, in those cases, deltaTime will have a higher value, because more time passed between the last frame and the current frame. This lets you largely ignore framerate issues, because you can always scale things relative to deltaTime. For example, if you animate a door opening, you might change its rotation by a by `_speed * Time.deltaTime` in each Update call. If the framerate is lower, that's fine, because deltaTime will be higher on each frame, so the door will open the same speed regardless of framerate.

    FixedUpdate is different. The physics system has to run at a set speed, regardless of framerate. How often FixedUpdate gets called is configurable in the Time settings (Fixed Timestep). Even if framerate suffers, FixedUpdate will still be called at regular intervals. Because of this, deltaTime should not be used in FixedUpdate, since deltaTime isn't meaningful here, and you don't need to worry about variable time intervals between FixedUpdate calls.
     
    jessechunn likes this.
  10. jessechunn

    jessechunn

    Joined:
    Jun 10, 2015
    Posts:
    18
    Got it. Thank you so much for taking the time to help me out with this. After our explanation I now realize that the entire point of fixedupdate is that it executes at fixed time intervals regardless of framerate. And it did indeed solve my stuttering issue.