0
\$\begingroup\$

I tried to implement a simple movement to my object. My object moves perfectly fine but I'm having issues with its collision. When I keep on moving object towards the obstacle/ground, collision are jittery.

Here the code for what I've written.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TempScript : MonoBehaviour
{
    [SerializeField] float walk_speed = 5f;
    [SerializeField] float jump_speed = 10f;
    [SerializeField] float max_up = 7f;
    [SerializeField] float max_low = -1.5f;
    
    void Update()
    {

        PlayerMovement();

    }
    void PlayerMovement()
    {
 
        if (Input.GetKey(KeyCode.W) && transform.position.y <= max_up)
            transform.position = transform.position + Vector3.up * jump_speed * Time.deltaTime;

        if (Input.GetKey(KeyCode.S) && transform.position.y >= max_low)
            transform.position = transform.position + Vector3.down * jump_speed * Time.deltaTime;

        if (Input.GetKey(KeyCode.D))
            transform.position = transform.position + Vector3.right * walk_speed * Time.deltaTime;

        if (Input.GetKey(KeyCode.A))
            transform.position = transform.position + Vector3.left * walk_speed * Time.deltaTime;
    }
   
}

The cube goes below the ground and bounces right back up.

The cube goes below the ground and bounces right back up. making it look like its jittering. what i want is movement should stop when its colliding with object. just like it happens with addForce method.

for now you can ignore max_up and max_down variable, it was just to make sure its in the camera.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ transform.position movement is ignoring collisions by design, if you need them to work, don't directly place the object with transform.position - it is more like teleporting it \$\endgroup\$
    – Zibelas
    Sep 3 '20 at 6:28
  • \$\begingroup\$ @Zibelas so what do you suggest i should do? i want same snappy movement. just better collisions \$\endgroup\$ Sep 3 '20 at 6:32
  • \$\begingroup\$ Have you considered using Rigidbody2D.MovePosition instead, or validating your new position is unobstructed with a physics shape cast before teleporting there? \$\endgroup\$
    – DMGregory
    Sep 3 '20 at 11:21
0
\$\begingroup\$

I think the problem is that you are changing the position of the body by directly changing the coordinates, thus you are putting your object beyond the border of a collider (over the wall). At the next physics step (which is not executed every frame) the collider system resets your rigidbody to the correct position).

It is usually not recommended to change the position of a physics-simulated object directly. Instead, use "AddForce" or "Transform", or other physics-related methods to manipulate your objects. You can limit the maximum speed of your object as well, so you can make sure that your character moves at the correct speed when you are applying force.

You may have to set also your surface properties so it won't "bounce" of the wall.

\$\endgroup\$
3
  • \$\begingroup\$ well i did implement the code Zibelas gave me but it just kinda glides and not snappy. i want snappy movement \$\endgroup\$ Sep 3 '20 at 8:07
  • \$\begingroup\$ You can try increasing your drag of your physics material, and at the same time increasing the force applied. You can also try to clamp your maximum velocity, so you can apply a lot of force, and you will have more control over the desired speed. To do that, add this to your fixed update: rb2d.velocity = Vector2.ClampMagnitude(rb2d.velocity.magnitude, maxVelocity); where maxVelocity is your desired speed. \$\endgroup\$
    – Gábor
    Sep 3 '20 at 10:37
  • \$\begingroup\$ Thanks, i'll try it out and tell you in a bit if it worked for me. \$\endgroup\$ Sep 4 '20 at 3:38
0
\$\begingroup\$

A simple movement script usually looks similar to this.

void FixedUpdate(){
   float moveHorizontal = Input.GetAxis("Horizontal");
   float moveVertical = Input.GetAxis("Vertical");
   Vector2 movement = new Vector2 (moveHorizontal, moveVertical);
   rb2d.AddForce (movement * walk_speed);
}

Don't use hard coded keys, use the input manager. Physic based movement should be handled in fixed update (independent of frame rate).

\$\endgroup\$
2
0
\$\begingroup\$

This effect is explained very well in one of the Unity official beginner tutorials (Ruby's Adventure: 2D Beginner), in particular in the World Interaction Chapter

Jittering happens because the Physics System uses a simplified copy of the Scene that only contains the Colliders. This Physics Scene make computations simpler for the Physics System, but the Physics System needs to:

  • Move its copy of the GameObject in the physics Scene whenever the GameObject with the Rigidbody moves in your Scene.
  • Apply forces and compute collision.
  • Move the GameObject in your Scene to the new position calculated in the physics Scene.

In this case, that leads to the following events:

  • You move the character during the frame update.
  • The Physics System moves its copy to that new position.
  • The Physics System finds that the character Collider is now inside another Collider (here the box) and moves it back, so that it is no longer inside the box. -The Physics System synchronizes the Ruby GameObject with that new position.

You are constantly moving Ruby inside the box and the Physics System is moving her back. The fighting between what you tell your code to do and what the Physics System does causes the jittering.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .