How to properly use CharacterController.Move() to move the character
Solution 1
The solution is to use a normalized vector for the direction of the movement.
// Get Horizontal and Vertical Input
float horizontalInput = Input.GetAxis ("Horizontal");
float verticalInput = Input.GetAxis ("Vertical");
// Calculate the Direction to Move based on the tranform of the Player
Vector3 moveDirectionForward = transform.forward * verticalInput;
Vector3 moveDirectionSide = transform.right * horizontalInput;
//find the direction
Vector3 direction = (moveDirectionForward + moveDirectionSide).normalized;
//find the distance
Vector3 distance = direction * walkSpeed * Time.deltaTime;
// Apply Movement to Player
myCharacterController.Move (distance);
Performance note:
vector.normalized
is obtained fromvector/vector.magnitude
andvector.magnitude
is obtained fromsqrt(vector.sqrMagnitude)
which is heavy to process. To reduce the processing weight you can usevector/vector.sqrMagnitude
instead ofvector.normalized
but be ware the result is not exactly the same, but still is in the same direction.
now i just need to apply gravity
Subtract moveDirection.y
by the gravity multiplied by Time.deltaTime
.
You can also simplify and reduce the code in the MovePlayer
function by using Vector3
and TransformDirection
.
public float walkSpeed = 10.0f;
private Vector3 moveDirection = Vector3.zero;
public float gravity = 20.0F;
CharacterController myCharacterController = null;
void Start()
{
myCharacterController = GetComponent<CharacterController>();
}
void MovePlayer()
{
moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
moveDirection = transform.TransformDirection(moveDirection);
moveDirection *= walkSpeed;
moveDirection.y -= gravity * Time.deltaTime;
myCharacterController.Move(moveDirection * Time.deltaTime);
}
Solution 2
You will want to use the normalized vector of the two axes when you multiply by your walkSpeed
. The reason being is this will ensure that you always move in any direction with the same magnitude (1) no matter the angle. Whereas your current setup has non-orthogonal movement being being calculated at >1 magnitude. So something like this should work in your situation.
void MovePlayer()
{
// Get Horizontal and Vertical Input
float horizontalInput = Input.GetAxis("Horizontal");
float verticalInput = Input.GetAxis("Vertical");
// Calculate the Direction to Move based on the tranform of the Player
Vector3 moveDirectionForward = transform.forward * verticalInput * Time.deltaTime;
Vector3 moveDirectionSide = transform.right * horizontalInput * Time.deltaTime;
// Apply Movement to Player
myCharacterController.SimpleMove((moveDirectionForward + moveDirectionSide).normalized * walkspeed);
Simply move the walkSpeed multiplication to the SimpleMove call against the normalized vector. The image below should help to visualize the problem you're having. By normalizing the vector before applying the walk speed, you're making sure that the direction vector is the same magnitude (effectively distance in this case) no matter what direction before you apply the walk speed.
Gerte
Updated on June 05, 2022Comments
-
Gerte almost 2 years
I created a basic First Person Controller but my problem is when i move both forward and sideways i move faster.
How can i add
moveDirectionForward
andmoveDirectionSide
in 1 Vector3 to be able to useCharacterController.Move()
instead ofCharacterController.SimpleMove()
?void MovePlayer() { // Get Horizontal and Vertical Input float horizontalInput = Input.GetAxis ("Horizontal"); float verticalInput = Input.GetAxis ("Vertical"); // Calculate the Direction to Move based on the tranform of the Player Vector3 moveDirectionForward = transform.forward * verticalInput * walkSpeed * Time.deltaTime; Vector3 moveDirectionSide = transform.right * horizontalInput * walkSpeed * Time.deltaTime; // Apply Movement to Player myCharacterController.SimpleMove (moveDirectionForward + moveDirectionSide);
-
Programmer almost 6 yearsI think you missed the
CharacterController.Move
part. Op wants to use that instead ofSimpleMove
. -
Gerte almost 6 yearsI can use .Move now i just need to apply gravity. Thanks for help!
-
Gerte almost 6 yearsby reducing the code i get the same problem i move faster
-
PassetCronUs almost 6 yearsI think you have to normalize the direction like Bijan did
transform.TransformDirection(moveDirection.normalized);
instead oftransform.TransformDirection(moveDirection)
. If that doesn't work, undo what you just did and just replacemoveDirection *= walkSpeed;
withmoveDirection = moveDirection.normalized * walkSpeed;
. -
Gerte almost 6 yearsYeah adding .normalized to the reduced code version works. Thanks everyone for the help. I got some studying to do now, i learned a lot from this problem.