Home > Software design >  Use Mobile Joystick with Unity 3d RigidBody
Use Mobile Joystick with Unity 3d RigidBody

Time:10-21

I am developing a mobile 3D app. I have a game object that has a rigid body and I move it with a joystick.

I got it to the point that I can move the object forward when I take the vertical input and rotate it when I take horizontal input from the joystick.

The problem is that when I rotate the rigid body 90 deg I would expect to use horizontal input to move the object forward or backward and rotate it with vertical joystick input. Basically I want the object to move forward where joystick is being pulled, but with the current set up I have to pull joystick upwards even if object is facing left or right sides. I hope I explained it well. If not know, please let me know, I will explain it more.

    public Joystick m_Joystick;
    private float m_HorizontalValue;
    private float m_VerticalValue;

    void Update()
    {
        m_VerticalValue = m_Joystick.Vertical;
        m_HorizontalValue = m_Joystick.Horizontal;
    }

    // Same as update, but is used fo modifying values that are used to manipulate
    // game object's physics
    void FixedUpdate() 
    {
        Move();
        Turn();
    }

    void Move()
    {
        Vector3 movement = transform.forward * m_VerticalValue * m_Speed * Time.deltaTime;

        m_Rigidbody.MovePosition(m_Rigidbody.position   movement);
    }

    void Turn()
    {
        float turn = m_HorizontalValue * m_TurnSpeed * Time.deltaTime;

        Quaternion turnRotation = Quaternion.Euler(0f, turn, 0f);

        m_Rigidbody.MoveRotation(m_Rigidbody.rotation * turnRotation); 
    }

I tried checking the forward vector of my rigid body (x and z values) to inverse the movement of object when joystick is pulled into the desired direction, but it is not working well, as rigid body would stuck when x and z values of forward vector are equal. The code is not complete I was testing only two quaters of x and z coordinate system (first and second quaters).

    float GetVerticalOrHorizaontalValueMovement()
    {
        float xValue = m_Rigidbody.transform.forward.x;
        float zValue = m_Rigidbody.transform.forward.z;

        float auxX = Mathf.Abs(xValue);
        float auxZ = Mathf.Abs(zValue);

        if (xValue > -0.1f && zValue > -0.1f)
        {
            if (auxX <= auxZ)
                return  m_HorizontalValue;
            else if (auxX >= auxZ)
                return m_VerticalValue;
        }
        else if(xValue > -0.1f && zValue < 0.1f)
        {
            if (auxX >= auxZ)
                return m_VerticalValue;
            else if (auxX <= auxZ)
                return m_HorizontalValue;
        }

        return 0f;
    }

    float GetVerticalOrHorizaontalValueRotation()
    {
        float xValue = m_Rigidbody.transform.forward.x;
        float zValue = m_Rigidbody.transform.forward.z;

        float auxX = Mathf.Abs(xValue);
        float auxZ = Mathf.Abs(zValue);

        if (xValue > -0.1f && zValue > -0.1f)
        {
            if(auxX <= auxZ)
                return m_VerticalValue;
            else if(auxX >= auxZ)
                return m_HorizontalValue;
        }
        else if(xValue > -0.1f && zValue < 0.1f)
        {
            if (auxX >= auxZ)
                return m_HorizontalValue;
            else if (auxX <= auxZ)
                return m_VerticalValue;
        }

        return 0f;
    }

The methods will be placed instead of m_VerticalValue and m_HorizontalValue variables in Move() and Turn() methods.

I am open to any solution that would make my game object move as I want with a joystick, but I have to keep it as RigidBody because I want to apply explosive forces on it and other possible forcers. If I did not explain something properly, please let me know.

CodePudding user response:

If someone would need it. Here it is. It is simple movement with mobile joystick. You might want to modify it to your needs if you have complex movements

 using UnityEngine;
 
 public class MovementOfPlayer : MonoBehaviour
 {
     Vector3 movementInput;
     Rigidbody playerRigidbody;
 
     void Start()
     {
         playerRigidbody = GetComponent<Rigidbody>();
         playerRigidbody.freezeRotation = true;
     }
 
     void FixedUpdate()
     {
         movementInput = Input.GetAxisRaw("Horizontal") * Vector3.right  
                         Input.GetAxisRaw("Vertical") * Vector3.forward;
         movementInput.Normalize();
 
         float y = playerRigidbody.velocity.y;
 
         if (movementInput != Vector3.zero)
         {
             if (transform.forward != movementInput)
             {
                 transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.LookRotation(movementInput), Time.deltaTime * 180);
 
                 playerRigidbody.velocity = Vector3.MoveTowards(playerRigidbody.velocity, Vector3.zero, Time.deltaTime * 30);
             }
             else
             {
                 playerRigidbody.velocity = Vector3.MoveTowards(playerRigidbody.velocity, movementInput * 10, Time.deltaTime * 30);
             }
         }
         else
         {
             playerRigidbody.velocity = Vector3.MoveTowards(playerRigidbody.velocity, Vector3.zero, Time.deltaTime * 30);
         }
         Vector3 velocity = playerRigidbody.velocity;
         velocity.y = y;
         playerRigidbody.velocity = velocity;
     }
 }
  • Related