I have created a demo scene in order to demonstrate my issue. As you can see in the images below I have 2 rings inside each other. I have added a script to the one on the right so that it will move at a medium speed when i press the WASD buttons. Each ring has a chain of sphere colliders as seen here:
Both spheres are identical (I prepared the 1st ring and duplicated it, then added the script to one of them). The problem is that when i move the ring on the right the rings almost immediately get separated, without any regard for the colliders:
As you can see in the image below the collision detection on both objects is Continuous Speculative. I understand that this is better for detecting angular forces than the Continuous detection.
Any ideas what I may be doing wrong and how I can fix this?
The main issue is that you are moving in Update but collisions are tested in Fixed Update. Fixed updates happen 20 time a second by default. If your game is running 100fps then there might be 5 Updates for every 1 Fixed Update. In each update, you’ve moved the ring a little. By the time the Fixed Update runs, the rings are separated and no collision is detected.
The only 100% reliable solution I have found is to set RigidBody.velocity. Here is a very cut down version of the code I use:
public class RB_Set_Velocity : MonoBehaviour
[SerializeField] float playerMoveSpeed = 5;
rb = GetComponent<Rigidbody>();
float x = Input.GetAxisRaw("Horizontal");
float z = Input.GetAxisRaw("Vertical");
move = new Vector3(x, 0, z).normalized;
rb.velocity = move * playerMoveSpeed;
You may find recommendations not to set rb.velocity every frame and I understand why, though I have never found it to be a problem, either doing it in Update or FIxedUpdate.
For what it’s worth, I believe that the Unity Character Controller doesn’t use physics at all and manages collisions using Raycasts. Tells us something, I believe…