Search Unity

Question Twitching when colliding with a wall

Discussion in 'Physics' started by Whiskas009, Nov 13, 2022.

  1. Whiskas009

    Whiskas009

    Joined:
    Aug 21, 2022
    Posts:
    27
    Hello everyone. When my object is pressed and moves along it, then there is such a twitch, as on a gif. Can you tell me how to fix it? 3.gif

    upload_2022-11-13_21-37-55.png

    Вот мой код движения:
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.InputSystem;
    3.  
    4. [RequireComponent(typeof(Rigidbody))]
    5. public class MovementRigidbody : MonoBehaviour
    6. {
    7.     [SerializeField] private float _moveSpeed;
    8.     [SerializeField] private float _rotationSpeed;
    9.  
    10.     private Vector3 _targetDirection;
    11.     private float _inputAngle;
    12.     private float _rotationSmoothVelocity;
    13.     private float _lockAngleValue = 0.0f;
    14.     private Rigidbody _rigidbody;
    15.  
    16.     private void Start()
    17.     {
    18.         _rigidbody = GetComponent<Rigidbody>();
    19.     }
    20.  
    21.     private void FixedUpdate()
    22.     {
    23.         Move();
    24.     }
    25.  
    26.     public void OnMove(InputAction.CallbackContext context)
    27.     {
    28.         CreateTargetDirection(context.ReadValue<Vector2>());
    29.     }
    30.  
    31.     private void Move()
    32.     {
    33.         if (_targetDirection.magnitude > 0.01f)
    34.         {
    35.             _rigidbody.velocity = _targetDirection * _moveSpeed;
    36.             Rotate();
    37.         }      
    38.     }
    39.  
    40.     private void CreateTargetDirection(Vector2 inputDirection)
    41.     {
    42.         _targetDirection = new Vector3(inputDirection.x, 0.0f, inputDirection.y).normalized;
    43.     }
    44.  
    45.     private void Rotate()
    46.     {
    47.         _inputAngle = Mathf.Atan2(_targetDirection.x, _targetDirection.z) * Mathf.Rad2Deg;
    48.         float targetAngle = Mathf.SmoothDampAngle(transform.eulerAngles.y,
    49.                 _inputAngle, ref _rotationSmoothVelocity, _rotationSpeed);
    50.  
    51.         _rigidbody.MoveRotation(Quaternion.Euler(_lockAngleValue, targetAngle, _lockAngleValue));
    52.     }
    53. }
    54.  
     
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,473
    AFAIK in 3D when using MovePosition or MoveRotation on a Dynamic body-type, it simply sets the pose instantly which can cause an overlap (as above) that the solver will then try to solve. In 3D it's really meant to be used with Kinematic bodies.

    This isn't the case in 2D where it works by moving the body via its velocity so it correctly contacts.

    For 3D, you'd need to manipulate the angular velocity to rotate it.

    NOTE: I'm not in the 3D physics team.
     
    Whiskas009 likes this.
  3. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,510
    Don't modify rigidbody.velocity directly nor call rigidbody.MoveRotation. Doing any of these overrides the results of the internal physics calculations, so the next step the physics engine has to "resolve" the new situation somehow - hence that "twitch".

    Instead, use rigidbody.AddForce and rigidbody.AddTorque only (or their variants). These methods allow not only to apply forces, but also instant changes in velocity (check out the ForceMode parameter). For example, for imposing a velocity to the rigidbody you can do this:
    Code (CSharp):
    1. rigidbody.AddForce(targetVelocity - rigidbody.velocity, ForceMode.VelocityChange)
    This will set the rigidbody velocity to targetVelocity while the physics engine also resolves collisions and friction properly. Same for angular velocity with AddTorque.
     
    Whiskas009 likes this.
  4. Whiskas009

    Whiskas009

    Joined:
    Aug 21, 2022
    Posts:
    27
    Tnx)