Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice

Questions about Isometric WASD Movement

Discussion in 'Scripting' started by neroziros, May 13, 2013.

  1. neroziros

    neroziros

    Joined:
    Aug 25, 2012
    Posts:
    129
    Hi all!

    I'm trying to implement an isometric WASD movement system. The problem is that I don't know how to match the "Up" , "Right" , "Left" and "Down" orientation of the character to the ones that camera have. Here is an image describing the issue:

    $Unity.jpg

    Blue is what I want.
    Red is what I have (Using character controller and its Move() function).

    Any help is appreciated, thanks in advance!
     
    Last edited: May 13, 2013
  2. GBCFraser

    GBCFraser

    Joined:
    Apr 11, 2013
    Posts:
    94
    Your image doesn't show up. I solved this problem before though. very simple solution.

    I created blank game object, just the transform inside and had the camera transfer the y.rotation to the transform of this widget.

    Code (csharp):
    1.  
    2. // Credit: AngryFoxGames
    3. using UnityEngine;
    4. using System.Collections;
    5.  
    6. public class CopyCamera : MonoBehaviour {
    7.     public GameObject GameCamera;
    8.     // Use this for initialization
    9.     void Start () {
    10.    
    11.     }
    12.    
    13.     // Update is called once per frame
    14.     void Update () {
    15.         gameObject.transform.position = GameCamera.transform.position;
    16.         gameObject.transform.rotation = GameCamera.transform.rotation;
    17.         transform.eulerAngles = new Vector3 (0,transform.eulerAngles.y,0);
    18.     }
    19. }
    Then you can use the copycamera transform the find the forward direction. Z pos of the transform that has copy camera will be forward. And X pos will be right. So you can grab this transform by this pseudocode.
    Code (csharp):
    1.  
    2. if (input == W)
    3. {
    4.      MyCharacterPos += CopyCamera.transform. forward * Time.deltatime;
    5. }
    6. if (input == D)
    7. {
    8.      MyCharacterPos += CopyCamera.transform.right * Time.deltatime;
    9. }
    10.  

    This solved the issue nicely, an easy hack.
     
  3. neroziros

    neroziros

    Joined:
    Aug 25, 2012
    Posts:
    129
    Thank you!

    Indeed your solution worked! but now I'm having a problem with the speed of the diagonal movements (it is faster than the vertical and horizontal movements).

    Here is my code:

    Code (csharp):
    1.     public void UpdatePlayerPosition(float xMagnitude, float zMagnitude)
    2.     {
    3.         /* My "CopyCamera" */
    4.         GameObject movementCamera = playerStatusController.movementCamera;
    5.        
    6.  
    7.         /* Direction calculations */
    8.         Vector3 newMovement = new Vector3(movementCamera.transform.forward.x,0,movementCamera.transform.forward.z) * -zMagnitude +
    9.                               new Vector3(movementCamera.transform.right.x,0,movementCamera.transform.right.z) * xMagnitude;
    10.        
    11.          /* Character controller movement (factored with time and the character speed) */
    12.         charController.Move(newMovement * Time.deltaTime * playerStatusController.currentMovementSpeed);
    13.  
    14.     }
    I'll try clamping the value of the movement's direction vector, but if any of you know an elegant solution for this I'll use it!

    Thanks in advance for your help!
     
    Last edited: May 16, 2013
  4. neroziros

    neroziros

    Joined:
    Aug 25, 2012
    Posts:
    129
    Lol it worked just by changing

    Code (csharp):
    1.          /* Character controller movement (factored with time and the character spee) */
    2.         charController.Move(newMovement * Time.deltaTime * playerStatusController.currentMovementSpeed);
    for

    Code (csharp):
    1.          /* Character controller movement (factored with time and the character spee) */
    2.         charController.Move(newMovement.normalized * Time.deltaTime * playerStatusController.currentMovementSpeed);
    This solution is specially useful if you're using smooth input like the one of a gamepad joystick
     
    Last edited: May 16, 2013
  5. GBCFraser

    GBCFraser

    Joined:
    Apr 11, 2013
    Posts:
    94
    Thanks for the code update, when I created mine I didn't normalize, I did not have that problem as much because mine was used for camera scrolling.
     
  6. neroziros

    neroziros

    Joined:
    Aug 25, 2012
    Posts:
    129
    Hmm it seems that this solution have another problem: if you normalize the direction vector ( in my case newMovement) you'll lose the magnitude of your input, in this case, causing that the player moves at the same speed no matter how higher or lower is the movement input's value . This only happens if you use analog input which sadly is my case ::(

    I'll start experimenting with solutions. Any help is appreciated!

    --
    UPDATE:

    Here you have the fixed version. The magnitude clamp's values were obtained by trial and error. I suspect that this have a trigonometric background and I really don't like making code without knowing exactly why it works but until I find out it'll suffice. Thank you all for your help! (still, any insight on this problem or a more elegant solution are welcome)

    Player Controller
    Code (csharp):
    1. public void UpdateTargetDirection(float xMagnitude, float zMagnitude)
    2. {
    3.     // The new movement vector is calculated
    4.     Vector3 newMovement = movementCamera.transform.forward * -zMagnitude +
    5.                           movementCamera.transform.right * xMagnitude;
    6.  
    7.     // Magnitude fix
    8.     newMovement = Vector3.ClampMagnitude(newMovement,1/Mathf.Sqrt(2)) * Mathf.Sqrt(2);
    9.    
    10.     // The player is moved according to his speed
    11.     charController.Move(newMovement * Time.deltaTime * playerStatusController.currentMovementSpeed);
    12.            
    13. }
    "Movement" Camera
    Code (csharp):
    1. public GameObject GameCamera;
    2. void Update () {
    3.     // Copy the rotation and position of the main camera
    4.     gameObject.transform.position = GameCamera.transform.position;
    5.     gameObject.transform.rotation = GameCamera.transform.rotation;
    6.    
    7.     // Zero the axis in which the player will move
    8.     transform.eulerAngles = new Vector3 (0,transform.eulerAngles.y,0);
    9. }
     
    Last edited: May 17, 2013
    Pabi likes this.
  7. GBCFraser

    GBCFraser

    Joined:
    Apr 11, 2013
    Posts:
    94
    I was using this as a camera controller, so what I did it it applied additional force when the button was pressed, the camera had a collider and rigid body, with a layer mask applied so it didn't hit the objects around the camera. so of course it you have to adapt it.

    I noticed you're applying a transform to the character. Why don't you use the physic's engine, or the character controller? The character controller isn't a rigid body and can handle movement and jumping.


    If you want your keys to work like a gas peddle, so the longer or harder you press the more power it gives. Check out the race car demo at the asset store for its controls. The keypress gave off values between 0.0 and 1.0. What you can do is create a singleton which gets a value for each input button, add a time value for each frame is pressed down to a maximum of a second/half-second or whatever.

    So:

    Code (csharp):
    1. Char.transform.position += DirectionMagnetude * Time.deltatime * speed * yourinput.keystrength
    And we can do this quick example
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class CharacterInput : MonoBehaviour {
    5.     /// <summary>
    6.     /// This will Make the Cube move into the distance based on a speed of how long the button is held down
    7.     /// </summary>
    8.     public GameObject ACube;
    9.     public float keystrength = 0.0f;
    10.     public float speed = 5;
    11.    
    12.     // Use this for initialization
    13.     void Start () {
    14.    
    15.     }
    16.    
    17.     // Update is called once per frame
    18.     void Update () {
    19.         if (Input.GetKey("space") == true)
    20.         {
    21.             //Detects how long the key is held down and creates a magnetude.
    22.             if ((keystrength + (1.0f/60.0f)) <= 1.0f)
    23.             {
    24.                 keystrength = keystrength + (1.0f/60.0f);
    25.                 print ("KeyStrength: " + keystrength);
    26.             }
    27.             else
    28.             {
    29.                 //This is fixing the floating point error.
    30.                 keystrength = 1.0f;
    31.             }
    32.         }
    33.         else
    34.         {
    35.             //Resets the key to zero.
    36.             keystrength = 0;
    37.         }
    38.         ACube.transform.position += ACube.transform.up * keystrength * speed * Time.deltaTime;  
    39.        
    40.     }
    41. }
    42.  
     
  8. bubzy

    bubzy

    Joined:
    May 7, 2013
    Posts:
    3
    Hi, new here. just a thought
    Code (csharp):
    1.     if (Input.GetKey("space") == true)
    could be better written as
    Code (csharp):
    1.     if (Input.GetKey("space"))
    just my 2 pence.
     
  9. Pabi

    Pabi

    Joined:
    Feb 13, 2016
    Posts:
    48
    Thanks mate! It fixed my problem