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.
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;
}
}