Search Unity

Moving an object with a tilt moves the object up in the Y direction

Discussion in 'Scripting' started by jnbbender, Feb 15, 2018.

  1. jnbbender

    jnbbender

    Joined:
    May 25, 2017
    Posts:
    487
    This forum has been a great help; I have my drone tilting when I move side to side and simply moving forward and backward. But my problem comes in when I move side-to-side. If I move to the left I want the drone to tilt to the right and move left (and vice-versa). This works, sort of. My problem is I get movement in the Y direction. I don't want my drone to move Up. Any help would be great. Here's what I have. I can't get either Version of the transform position movements to work.


    float dirX = Input.GetAxis ("Horizontal");
    float dirY = Input.GetAxis ("Vertical");
    Debug.Log ("dirX " + dirX + ", dirY " + dirY + " Transform.rotation "+ transform.rotation);

    // Tilt
    float z = dirX * maxTilt;
    Vector3 euler = transform.localEulerAngles;
    euler.z = Mathf.LerpAngle(euler.z, z, tiltSpeed * Time.deltaTime);
    transform.localEulerAngles = euler;

    // Version 1
    transform.position = Vector3.Lerp (transform.position, transform.TransformPoint (dirX, 0f, dirY), moveSpeed * Time.deltaTime);


    // Version 2
    transform.Translate (dirX * moveSpeed * Time.deltaTime, 0f, dirY * moveSpeed * Time.deltaTime);
     
  2. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Both your Tilt code and your Version 1 position code are abusing Lerp. Please stop.

    Version 1 gets some Y movement mixed in because you're using transform.TransformPoint, which finds some point relative to the transform — that of course takes into account rotation. And Version 2 has basically the same problem, because since you haven't specified otherwise, the default relativeTo parameter is Space.Self, so it takes the direction you give it and translates it by the rotation. In both cases, if your object is tilted, this results in some movement in Y.

    A simple fix for this is to just set the Y back to what it should be. E.g.:

    Code (csharp):
    1.  
    2. Vector2 pos = transform.position;
    3. pos += transform.TransformDirection(new Vector3(dirX * moveSpeed * Time.deltaTime, 0, dirY * moveSpeed * Time.deltaTime);
    4. pos.y = transform.position.y;     // don't allow movement in Y
    5. transform.position = pos;
    There are other solutions too, but this one seems simplest to me.
     
  3. jnbbender

    jnbbender

    Joined:
    May 25, 2017
    Posts:
    487
    Thanks. I'll have to give it a shot later. I took the tilt code from suggestions on this site. Would you have better options for tilting?
     
  4. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Sure. There are two basic points to be made here. First, you should never extract angles out of eulerAngles and do anything with them, except in the special case where you're only ever rotating around one axis (such as in a 2D game). You're rotating in all 3 axes, so eventually your use of eulerAngles.z here will cause you grief.

    ...Or are you? Now that I look at it, I'm not so sure that you ever rotate around Y. If you don't, then your translation code is more complex than it needs to be — if your movement is always straight +/- X (for horizontal) and +/- Z (for vertical), then there would have been a much simpler answer to your first question. :) You could just be adding those directly to your position, without having to bother with transform.TransformDirection.

    But anyway, because you never know what your sneaky future-self might do, I would just go ahead and keep your Z rotation (tilt) in a property on the class.

    Then the second basic point is, if you want to move smoothly towards something, usually you want to use Mathf.MoveTowards, Mathf.MoveTowardsAngle, or one of the related methods in Vector2, Vector3, and Quaternion. These work the way that beginners always think Lerp works: they take the current value, and move it smoothly towards some target, but not more than some amount you specify.

    Code (CSharp):
    1. float tilt = 0f;     // current Z rotation
    2.  
    3. ...
    4.  
    5. // Tilt
    6. float targetTilt = dirX * maxTilt;
    7. tilt = Mathf.MoveTowards(tilt, targetTilt, tiltSpeed * Time.deltaTime);
    8. transform.rotation = Quaternion.Euler(0, 0, tilt);
    HTH,
    - Joe
     
  5. jnbbender

    jnbbender

    Joined:
    May 25, 2017
    Posts:
    487
    Thanks for all your help. I'll look into MoveTowards.
     
    JoeStrout likes this.