Reputation: 1
I'm starting to make my game and ran into a problem with movement. My movement is based on the new input system and .AddForce()
. The problem is that when I jump, the character's speed drops after landing and then starts picking up again.
A Physic Material with a Dynamic Friction of 2 hangs on the player's Capsule Collider (if it affects the problem)
How to make the character move without slowing down?
Video demonstration (I hope you can see what the problem is). Rigidbody and Player Mover settings.
Code (there is no more associated code):
using System;
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(CapsuleCollider))]
public class PlayerMover : MonoBehaviour
{
[SerializeField] private LayerMask _groundLayer = 6;
[SerializeField] private float _moveForce;
[SerializeField] private float _maxForce;
[SerializeField] private float _jumpForce;
[SerializeField] private float _mouseSensitivity;
private PlayerInput _input;
private Rigidbody _rb;
private CapsuleCollider _collider;
private Camera _camera;
private float _rotationX;
private const float MinAngle = -90f;
private const float MaxAngle = 90f;
private void Awake()
{
_input = new PlayerInput();
_rb = GetComponent<Rigidbody>();
_collider = GetComponent<CapsuleCollider>();
_camera = GetComponentInChildren<Camera>();
_rb.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ;
if (_groundLayer == gameObject.layer)
{
Debug.LogError("Сортувальний рівень гравця повинен відрізнятися від сортувального рівня землі!");
}
_input.Player.Jump.performed += context => Jump();
}
private void OnEnable()
{
_input.Enable();
}
private void OnDisable()
{
_input.Disable();
}
private void FixedUpdate()
{
Move();
}
private void LateUpdate()
{
Look();
}
private bool IsGrounded
{
get
{
var bottomCenterPoint = new Vector3(_collider.bounds.center.x, _collider.bounds.center.y,
_collider.bounds.center.z);
return Physics.CheckCapsule(_collider.bounds.center, bottomCenterPoint, _collider.bounds.size.x * 1.1f,
_groundLayer);
}
}
private Vector3 MovementVector
{
get
{
var cameraDirectionF = _camera.transform.forward;
var cameraDirectionR = _camera.transform.right;
cameraDirectionF.y = 0;
cameraDirectionR.y = 0;
cameraDirectionF = cameraDirectionF.normalized;
cameraDirectionR = cameraDirectionR.normalized;
var direction = _input.Player.Move.ReadValue<Vector2>();
return cameraDirectionF * direction.y + cameraDirectionR * direction.x;
}
}
private Vector2 MouseVector => _input.Player.Look.ReadValue<Vector2>() * _mouseSensitivity * Time.deltaTime;
private void Jump()
{
if (IsGrounded == false) return;
_rb.AddForce(new Vector3(0, _jumpForce, 0), ForceMode.Impulse);
}
private void Move()
{
_rb.AddForce(MovementVector * _moveForce, ForceMode.Impulse);
if (Math.Sqrt(Math.Pow(_rb.velocity.x, 2) + Math.Pow(_rb.velocity.z, 2)) < _maxForce) return;
var maxVelocity = _rb.velocity.normalized * _maxForce;
_rb.velocity = new Vector3(maxVelocity.x, _rb.velocity.y, maxVelocity.z);
}
private void Look()
{
_rotationX -= MouseVector.y;
_rotationX = Math.Clamp(_rotationX, MinAngle, MaxAngle);
_camera.transform.localEulerAngles = new Vector3(_rotationX, MouseVector.y, 0);
transform.Rotate(Vector3.up * MouseVector.x);
}
}
I tried changing the different .AddForce()
values in the .Move()
and .Jump()
methods. Changed the value when assigning Vector3
to _rb.velocity
in the .Move()
method, where there is a check for the maximum allowable speed (without this check, .AddForce()
will constantly increase the speed of movement).
I also thought that the problem was in the MovementVector
property, but it is not so, it gives the correct values.
(The following statement is most likely incorrect)
In my opinion, after the jump, at the lowest point of the jump (almost near the ground), the character falls perpendicularly down and thus the speed is completely extinguished, so it needs to be regained.
Edit: I just modified the code to see the lowest velocity values in the console. Added the following: two variables and .Update()
, one check in the MovementVector
property, and changing the _flag
in the .Jump()
method.
private bool _flag;
private double _min = double.MaxValue;
private void Update()
{
if (!_flag) return;
var current = Math.Sqrt(Math.Pow(_rb.velocity.x, 2) + Math.Pow(_rb.velocity.z, 2));
if (current < _min) _min = current;
Debug.Log(_min);
}
ㅤ
private Vector3 MovementVector
{
get
{
....
var direction = _input.Player.Move.ReadValue<Vector2>();
if (direction.magnitude == 0)
{
_flag = false;
}
return cameraDirectionF * direction.y + cameraDirectionR * direction.x;
}
}
ㅤ
private void Jump()
{
_flag = true;
if (IsGrounded == false) return;
//_rb.AddForce(new Vector3(0, _jumpForce, 0), ForceMode.Impulse);
_rb.AddForce(transform.up * _jumpForce, ForceMode.Impulse);
}
Now, on landing, I will get accurate velocity values. With this, I noticed something, when changing _maxForce to a higher side, the landing velocity also changes. If for _maxForce equal to five the velocity dropped to zero, for _maxForce equal to 10 it drops already to 4, for _maxForce equal to 15 - to 9.
Upvotes: 0
Views: 274
Reputation: 59
In Jump() Method you are adding the force of (0,_jumpforce,0) so this zeroes out the current movement. instead of zero you should addforce with the vector direction multiplied by jumpForce Example:
_rb.AddForce(transform.up * _jumpForce, ForceMode.Impulse);
I hope this is fix works fine as per your requirement.
Upvotes: 0