Search Unity

Object moving along Z axis instead of Y

Discussion in 'Physics' started by kalisclark, Jan 12, 2015.

  1. kalisclark

    kalisclark

    Joined:
    Sep 29, 2014
    Posts:
    33
    Hi guys,

    Not sure if this is the correct place for this but I have a cube and I have added the FPS controls to it. I changed the input settings but I can't seem to get the box to move up and down.

    Does anyone know what I am doing wrong here?

    I basically want the cube to go up when I press up arrow.(currently moves along the Z axis) and go left and right on arrow press horizontally (which it currently does)

    Am I missing something with unity that it doesn't let you move along the Y axis unless you implement gravity for a jump motion?

    Any clues would really help.

    P.s I haven't provided code because it is just the standard FPS code I am using with no modifications except changing the getaxis("") to match any new inputs I have tried.
     
  2. skusku

    skusku

    Joined:
    Jan 4, 2015
    Posts:
    17
    First of all: If you use the FPS controller, it is bound to move you along the z and the x axes as those are the horizontal planes. That's just how the FPS controller works.

    I haven't used it yet though so I'm asking this:
    Is your character rigidbody kinematic or non kinematic ? In the first case, there is no problem. You can move your character wherever you want. In c# it should be along the lines:

    Code (CSharp):
    1. void Update()
    2. {
    3.  
    4. if(Input.GetAxis("Vertical") != 0)
    5. {
    6.       player.transform.Translate(Vector3.up * Input.GetAxis("Vertical") * Time.deltaTime);
    7. }
    8.  
    9. }
    You can switch "Vector3.up" to the desired axis you want to translate about (Vector3.up being positive Y, Vector3.forward positive Z, Vector3.right positive X)

    Be aware that those axis are always in global space. If you want to, for example, translate in the positive X direction of your character after he rotated (around his Y axis), you want to use the players right direction instead of Vector3.right, making it (yeah i switched to horizontal here, i'm sorry) :

    Code (CSharp):
    1. void Update()
    2. {
    3.  
    4. if(Input.GetAxis("Horizontal") != 0)
    5. {
    6.       player.transform.Translate(player.transform.right * Input.GetAxis("Horizontal") * Time.deltaTime);
    7. }
    8.  
    9. }
    you can also use the cameras right direction!

    Code (CSharp):
    1. void Update()
    2. {
    3.  
    4. if(Input.GetAxis("Horizontal") != 0)
    5. {
    6.       player.transform.Translate(Camera.main.transform.right * Input.GetAxis("Horizontal") * Time.deltaTime);
    7. }
    8.  
    9. }
    If your character is not kinematic, you basically do the same things, but instead of using .Translate, you can set the velocity directly with:

    Code (CSharp):
    1. player.rigidbody.velocity = Vector3.up * Input.GetAxis("Vertical") * Time.deltaTime);
    If you want to use the useGravity feature is up to what you want to make out of your game.

    Hope this helped.
     
    Last edited: Jan 13, 2015
    kalisclark likes this.
  3. kalisclark

    kalisclark

    Joined:
    Sep 29, 2014
    Posts:
    33
    Wow thanks Skusku! I really appreciate you taking the time to write this.

    I did try your first method after I wrote the post and it worked however I realise now that I want this effect while the object is tethered to another object. Let me break it down.

    I have a cube which moves around and rotates like the FPS controller. I have a plane attached to that cube and I move it likes so....


    Code (CSharp):
    1.  transform.Translate(Vector3.right * Input.GetAxis("Horizontal"));
    2.   transform.Translate(Vector3.up * Input.GetAxis("Vertical"));
    The problem is that when I rotate the cube, the plane is no longer on the same axis and can no longer move in the desired way. So if the cube is facing the Z axis it all works well but as soon as the cube turns, the plane's axis immediately become wrong.
     
  4. skusku

    skusku

    Joined:
    Jan 4, 2015
    Posts:
    17
    I would love to help you with this too but I don't really understand your cube / plane analogy. Maybe add a screenshot or two?

    :)

    I guess you don't want to rotate the plane simultaneously with the cube, however you want the plane to move in the same direction as the cube ... right ?

    Code (CSharp):
    1. public Transform cube;
    2.  
    3. void Update()
    4. {
    5.   transform.Translate(cube.right * Input.GetAxis("Horizontal")
    6.   transform.Translate(cube.up * Input.GetAxis("Vertical")
    7. }
    If this is the case, this could work.
    You just have to drag and drop the cube into the Transform variable in your Inspector.

    One more thing to consider : Are your objects somehow parented to each other?
    Please consider that I may not have completely understood what you want to do, it may be possible I solved a totaly different problem :p
     
  5. kalisclark

    kalisclark

    Joined:
    Sep 29, 2014
    Posts:
    33
    AH! you beat me!

    I was literally just about to post this. I managed to get it to work and I think I was perhaps putting too much thought into it and making it more complicated than it needed to be.

    Code (CSharp):
    1.  transform.Translate(Vector3.right * Input.GetAxis("Horizontal"));
    2.         transform.Translate(Vector3.up * Input.GetAxis("Vertical"));
    So now, because the Plane is a child of the Cube, it rotates with the cube which is fine, but it also keeps it's intended movement!

    Thank you for helping with this Skusku, I usually don't get a response on the forum due to my problem being too crazy or my analogies suck haha.

    Anyway. Thank you and I hope others will find this useful.
     
    skusku likes this.
  6. skusku

    skusku

    Joined:
    Jan 4, 2015
    Posts:
    17
    Good job on solving it :)

    btw, you may want to multiply your translations by Time.deltaTime and some arbitrary speed value so it is Framerate independant. Currently your movement is faster on systems with higher FPS (it gets moved every frame by the same amount). If you multiply it by Time.deltaTime (It's the time since the last frame : this is shorter with faster PCs, as they take less time to compute a frame, and longer for slower systems), it will be the same on all systems.
     
    kalisclark likes this.
  7. kalisclark

    kalisclark

    Joined:
    Sep 29, 2014
    Posts:
    33
    OH :eek:
    I didn't know that, thanks for pointing that out. that will come in handy!
    :D:D:D
     
  8. kalisclark

    kalisclark

    Joined:
    Sep 29, 2014
    Posts:
    33
    Ok so I have another problem. multiplying the Translate worked for the Plane, however I need it to work on a grid.

    Using the GridMove script how can I apply the same motion? The problem I am having is that it seems to set the position but it doesn't set it based on it's current position.

    Code (CSharp):
    1. using System.Collections;
    2. using UnityEngine;
    3. class GridMove : MonoBehaviour {
    4.     private float moveSpeed = 3f;
    5.     private float gridSize = 1f;
    6.     private enum Orientation {
    7.         Horizontal,
    8.         Vertical
    9.     };
    10.     private Orientation gridOrientation = Orientation.Horizontal;
    11.     private bool allowDiagonals = false;
    12.     private bool correctDiagonalSpeed = true;
    13.     private Vector2 input;
    14.     private bool isMoving = false;
    15.     private Vector3 startPosition;
    16.     private Vector3 endPosition;
    17.     private float t;
    18.     private float factor;
    19.     public void Update() {
    20.         if (!isMoving) {
    21.             input = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
    22.             if (!allowDiagonals) {
    23.                 if (Mathf.Abs(input.x) > Mathf.Abs(input.y)) {
    24.                     input.y = 0;
    25.                 } else {
    26.                     input.x = 0;
    27.                 }
    28.             }
    29.             if (input != Vector2.zero) {
    30.                 StartCoroutine(move(transform));
    31.             }
    32.         }
    33.     }
    34.     public IEnumerator move(Transform transform) {
    35.         isMoving = true;
    36.         startPosition = transform.position;
    37.         t = 0;
    38.         if(gridOrientation == Orientation.Horizontal) {
    39.             endPosition = new Vector3(startPosition.x + System.Math.Sign(input.x) * gridSize,
    40.                 startPosition.y, startPosition.z + System.Math.Sign(input.y) * gridSize);
    41.         } else {
    42.             endPosition = new Vector3(startPosition.x + System.Math.Sign(input.x) * gridSize,
    43.                 startPosition.y + System.Math.Sign(input.y) * gridSize, startPosition.z);
    44.         }
    45.         if(allowDiagonals && correctDiagonalSpeed && input.x != 0 && input.y != 0) {
    46.             factor = 0.7071f;
    47.         } else {
    48.             factor = 1f;
    49.         }
    50.         while (t < 1f) {
    51.             t += Time.deltaTime * (moveSpeed/gridSize) * factor;
    52.             transform.position = Vector3.Lerp(startPosition, endPosition, t);
    53.             yield return null;
    54.         }
    55.         isMoving = false;
    56.         yield return 0;
    57.     }
    58. }
    Is this even possible? I feel it's something simple but I can't figure out what position I need to be multiplying by the axis.

    Any help would be greatly appreciated
     
  9. skusku

    skusku

    Joined:
    Jan 4, 2015
    Posts:
    17
    I again have troubles understanding what you actually want to do :D

    Do you want to move the cube and the plane simultaneously ? If yes, just parent them together and attach the script to the parent.

    Did you write this script ? Do you know what everything does ?

    Also, you can just use Mathf.Sign instead of System.Math.Sign

    Some Screenshots go a long way btw
     
  10. kalisclark

    kalisclark

    Joined:
    Sep 29, 2014
    Posts:
    33
    Hi Skusku,

    Apologies for the lack of information. Ok so the answer is no, I do not want them to move simultaneously. A screenshot would pretty much show a cube with a plane as a child object as that is all I have. The cube moves like the FPS controller and I want the plane to move as if it was on a chessboard in front of the cube on its own axis. I am working on various approaches to movement in unity so it isn't one big project but rather, little prototypes to test what can and can't be done.

    So the cube moves as desired but the script above when attached to the plain is fine when on the x axis but when the cube turns this script moves the plane on the same axis and therefore it doesn't change. The above script is not my own, its on the Unity wiki. It gives an object a step movement on a grid.

    Ideally, what I want to achieve is the ability to have chess movements but have them the same no matter where the parent is. I hope this makes sense and if you let me know what you would need to see in a screenshot I can clean up my window to show it?

    Thank you for your help.