Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Resolved Need an alternative for Calculating the PlayerMovement

Discussion in 'Physics' started by Deleted User, Apr 18, 2021.

  1. Deleted User

    Deleted User

    Guest

    Hello!
    I can't figure out an alternative way to calculate the movement of my Player Object.
    Currently if you press W+D both the Vertical and Horizontal Speed Vectors add to each other resulting in a Vector double the length it has been intended to be. I can't figure out hwo to calculate it differently, even tho it should be as simple as calculating the length of the vector and dividing it by 2.
    I am using the 2D engine.

    Code (CSharp):
    1. {
    2.     public float speedModifier = 8f;
    3.     public Transform player;
    4.    
    5.     void Update()
    6.     {
    7.         float x = Input.GetAxis("Horizontal");
    8.         float y = Input.GetAxis("Vertical");
    9.        
    10.         float xSpeed = x * speedModifier * Time.deltaTime;
    11.         float ySpeed = y * speedModifier * Time.deltaTime;
    12.         player.Translate(ySpeed, -xSpeed, 0);//- has to be due to the player orentation
    13.        
    14.     }
    15.  
    16. }
     
  2. Deleted User

    Deleted User

    Guest

    Best would be a way to do it without having to depend on the rotation of the body's transform. But finding out how to do that is beyond my capabilities.
     
  3. tjmaul

    tjmaul

    Joined:
    Aug 29, 2018
    Posts:
    464
    I don’t wanna be harsh but I assume you did not go through the physics tutorials. They’re really useful and informative, so that’s a recommendation.

    So first of all, they’re not twice the magnitude, but times sqrt(2). See the diagonal of a square.

    Next, I’d go like this:

    Code (CSharp):
    1. Vector3 v = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical", 0);
    2. Vector3 vClamped = Vector3.ClampMagnitude(v, 1);
    3.  
    4. player.Translate(v * speedModifier * Time.deltaTime)
    https://docs.unity3d.com/ScriptReference/Vector3.ClampMagnitude.html (there's something like you're doing in there as an example)

    I didn't really get what you're saying there, because right now your movement code does not depend on the player transform already. But in case you want it react to the players rotation, then use
    transform.up/.right/.forward
    as follows:

    Code (CSharp):
    1. Vector3 movement = Input.GetAxis("Vertical") * transform.up + Input.GetAxis("Horizontal") * transform.right
     
    Deleted User likes this.
  4. AlTheSlacker

    AlTheSlacker

    Joined:
    Jun 12, 2017
    Posts:
    326
    Deleted User likes this.
  5. Deleted User

    Deleted User

    Guest

    Thanks! My problem was that the "Input" changed the velocity depending on the relative Rotation of the Transform, meaning that when my player was tilted 90 Degrees it would go in the wrong direction. Even tho the code doesn't say so, the hierarchy of the GameObject does.

    And with that Vector Addition, it has been quite a while since I had to calculate anything using Vectors, which is why I wasn't sure whether it was *2 or sqrt(2)
     
    Last edited by a moderator: Apr 18, 2021
  6. Deleted User

    Deleted User

    Guest

    Gonna try it out tomorrow!
     
  7. Deleted User

    Deleted User

    Guest

  8. Deleted User

    Deleted User

    Guest

  9. Deleted User

    Deleted User

    Guest

    And indeed, I didn't read them, as I thought with my understanding of physics, both normal and relativistic, I would be intelligent enough to figure out how to calculate it using code without forgetting Vector Addition
     
  10. Deleted User

    Deleted User

    Guest

    That method is kinda worse actually, as it only allows one input at a time
     
  11. Deleted User

    Deleted User

    Guest

  12. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    10,343
    Please try not to use the forum like a chat room but instead simply edit your existing posts.

    Thanks.
     
  13. Deleted User

    Deleted User

    Guest

    Sorry, but his solution seemed very interesting and I wanted to know more about it.
    But I'll try not to post comments as excessively in the future
     
    MelvMay likes this.
  14. AlTheSlacker

    AlTheSlacker

    Joined:
    Jun 12, 2017
    Posts:
    326
    OK this is my bad, I thought it gave some insight into why you were going faster diagonally and would also show quite a nice way of using analogue input sticks. If it is adding to the confusion then best to just ignore it.

    To implement @tjmaul 's suggestion in your 2D code, it will look something like this:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class MoveSprite : MonoBehaviour
    6. {
    7.     public float speedModifier = 8f;
    8.     public Transform player;
    9.  
    10.     void Update()
    11.     {
    12.         float x = Input.GetAxis("Horizontal");
    13.         float y = Input.GetAxis("Vertical");
    14.  
    15.         float xSpeed = x * speedModifier * Time.deltaTime;
    16.         float ySpeed = y * speedModifier * Time.deltaTime;
    17.         Vector2 playerMoveInput = new Vector2(-ySpeed, xSpeed);//- has to be due to the player orentation
    18.         Vector2 playerMoveClamped = Vector2.ClampMagnitude(playerMoveInput, speedModifier * Time.deltaTime);
    19.         player.Translate(playerMoveClamped, 0);
    20.  
    21.     }
    22.  
    23. }
    I have attempted to leave the code in the same style as you supplied for readability for you. What tjmaul was saying is use the Vector2[or 3].Clamped to control the magnitude of the movement vector. This is the simplest way to prevent the over-speed in the diagonal.
     
    tjmaul likes this.
  15. tjmaul

    tjmaul

    Joined:
    Aug 29, 2018
    Posts:
    464
    What do you mean by "one input at a time"? Can't you go diagonally?

    To be honest, I didn't test the code I gave you and so for completeness sake, here's the code for the player controller:
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class PlayerController : MonoBehaviour
    4. {
    5.     public float speedModifier = 1;
    6.  
    7.     // Update is called once per frame
    8.     void Update()
    9.     {
    10.         Vector3 v = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"), 0);
    11.         Vector3 vClamped = Vector3.ClampMagnitude(v, 1);
    12.  
    13.         transform.Translate(vClamped * (speedModifier * Time.deltaTime));
    14.     }
    15. }
    16.  
    and there's a package (appended to this post) you can import. Just create a new 2D project and import this package.
     

    Attached Files:

    Deleted User and AlTheSlacker like this.
  16. Deleted User

    Deleted User

    Guest

    This solution works perfectly, apart from having flipped th input, but that should be fixable with just a few -. Thanks!