Source file unity-csharp/3d/ControllerRigidbodyPusher.cs from the GDnD code examples. Download raw file
// 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);
}
}
}