// GDnD wiki example (2 of 2: SimplePlayerController.cs, ControllerRigidbodyPusher.cs) // Demonstrates: reacting to CharacterController collisions with OnControllerColliderHit. // A CharacterController does not push Rigidbodies by itself and is not moved by // physics. Unity sends OnControllerColliderHit to scripts on the controller's // GameObject whenever a Move call touches a collider; this script uses it to give // non-kinematic Rigidbodies (crates, balls) a horizontal shove. // Heavier bodies move less, because the push is divided by mass. // Related pages: [[unity-character-controller]], [[3d-blocking-and-greyboxing]] // Unity 6 (6000.x). Put it on the same GameObject as the CharacterController. using UnityEngine; namespace GDnD.ThreeD { [RequireComponent(typeof(CharacterController))] public class ControllerRigidbodyPusher : MonoBehaviour { [SerializeField] private float pushStrength = 2f; // target push speed (m/s) for a 1 kg body [SerializeField] private LayerMask pushableLayers = ~0; private void OnControllerColliderHit(ControllerColliderHit hit) { Rigidbody body = hit.collider.attachedRigidbody; if (body == null || body.isKinematic) return; if ((pushableLayers.value & (1 << body.gameObject.layer)) == 0) return; // Ignore things we are standing on: only push sideways. if (hit.moveDirection.y < -0.3f) return; Vector3 pushDirection = new Vector3(hit.moveDirection.x, 0f, hit.moveDirection.z); Vector3 targetVelocity = pushDirection * (pushStrength / Mathf.Max(body.mass, 0.01f)); // Keep the body's own vertical velocity so it can still fall. body.linearVelocity = new Vector3(targetVelocity.x, body.linearVelocity.y, targetVelocity.z); } } }