agentleFS
IceMasterTIceMasterT/Unity-6.3_SKILLS/unity-physics/SKILL.md

unity-physics

Skill0 starsChanged 3 months agoMITView on GitHub

Use when working with Unity's physics system — Rigidbody/Collider setup, CharacterController, raycasting, layers and the collision matrix, or choosing between 3D and 2D physics. Grounds answers in the local Unity 6.3 docs over pretrained knowledge.

3 other projects use a version of this.

Adopted by

Most recently taken up by

The file

Files
SKILL.md

Unity Physics

Retrieval Sources

SourcePathUse for
Physics overviewManual/PhysicsSection.html, Manual/PhysicsOverview.htmlLanding pages for the whole 3D physics system; navigation into every subtopic below
RigidbodyManual/class-Rigidbody.html, Manual/rigidbody-physics-section.html, Manual/rigidbody-configure-colliders.htmlRigidbody component fields, mass/drag, attaching colliders to a body
Rigidbody scriptingScriptReference/Rigidbody.html, ScriptReference/Rigidbody.AddForce.html, ScriptReference/Rigidbody.AddForceAtPosition.html, ScriptReference/Rigidbody.AddTorque.html, ScriptReference/Rigidbody.MovePosition.html, ScriptReference/Rigidbody.MoveRotation.htmlExact method signatures and ForceMode semantics for driving a Rigidbody from code
Rigidbody interpolation & sleepScriptReference/Rigidbody-interpolation.html, ScriptReference/Rigidbody-sleepThreshold.html, ScriptReference/Rigidbody.Sleep.html, Manual/physics-optimization-cpu-rigidbody-sleeping.htmlSmoothing visuals across fixed-timestep steps; when/why bodies go to sleep and how to force it
Continuous collision detectionScriptReference/Rigidbody-collisionDetectionMode.html, Manual/physics-optimization-cpu-rigidbody-collision-modes.htmlDiscrete vs Continuous vs ContinuousDynamic vs ContinuousSpeculative, tunneling tradeoffs
Collider overview & typesManual/CollidersOverview.html, Manual/collider-shapes.html, Manual/collider-shapes-introduction.html, Manual/collider-types-introduction.htmlChoosing a collider shape, how colliders relate to Rigidbody and to each other
Primitive collidersManual/primitive-colliders.html, Manual/primitive-colliders-introduction.html, Manual/class-BoxCollider.html, Manual/class-SphereCollider.html, Manual/class-CapsuleCollider.html, ScriptReference/BoxCollider.html, ScriptReference/SphereCollider.html, ScriptReference/CapsuleCollider.htmlBox/Sphere/Capsule collider fields and cheapest-shape guidance
Mesh collidersManual/mesh-colliders.html, Manual/mesh-colliders-introduction.html, Manual/class-MeshCollider.html, Manual/prepare-mesh-for-mesh-collider.html, ScriptReference/MeshCollider.html, ScriptReference/MeshCollider-convex.htmlConvex vs non-convex MeshCollider rules, cooking a mesh for collision use
Wheel collidersManual/wheel-colliders.html, Manual/wheel-colliders-introduction.html, Manual/wheel-colliders-friction.html, Manual/wheel-colliders-suspension.html, Manual/class-WheelCollider.html, Manual/WheelColliderTutorial.html, ScriptReference/WheelCollider.htmlVehicle wheel simulation: suspension, friction curves, motor/brake torque
Terrain colliderManual/terrain-colliders.html, Manual/terrain-colliders-introduction.html, Manual/terrain-Tree-Colliders.html, Manual/class-TerrainCollider.html, ScriptReference/TerrainCollider.htmlHeightmap-based terrain collision and per-tree colliders
Compound collidersManual/compound-colliders.html, Manual/compound-colliders-introduction.html, Manual/create-compound-collider.htmlBuilding complex shapes from multiple primitive colliders on child GameObjects
Collider interaction eventsManual/collider-interactions.html, Manual/collider-interactions-oncollision.html, Manual/collider-interactions-ontrigger.html, Manual/collider-interactions-other-events.html, Manual/collider-interactions-create-trigger.html, Manual/collider-interactions-example-scripts.html, Manual/collider-types-interaction.htmlOnCollisionEnter/Stay/Exit vs OnTriggerEnter/Stay/Exit, what Rigidbody/isTrigger combination each needs
CharacterControllerManual/CharacterControllers.html, Manual/class-CharacterController.html, Manual/com.unity.charactercontroller.html, ScriptReference/CharacterController.html, ScriptReference/CharacterController.Move.html, ScriptReference/CharacterController.SimpleMove.htmlKinematic character movement API, step offset, slope limit, isGrounded, collision flags
Physics.Raycast & queriesScriptReference/Physics.Raycast.html, ScriptReference/Physics.RaycastAll.html, ScriptReference/Physics.Linecast.html, ScriptReference/Physics.SphereCast.html, ScriptReference/Physics.BoxCast.html, ScriptReference/Physics.CapsuleCast.html, ScriptReference/Physics.OverlapSphere.html, ScriptReference/Physics.OverlapBox.html, ScriptReference/Physics.OverlapCapsule.html, ScriptReference/RaycastHit.html, Manual/physics-optimization-raycasts-queries.htmlEvery non-2D query overload, LayerMask/QueryTriggerInteraction args, RaycastHit fields, query cost
PhysicsMaterialManual/class-PhysicsMaterial.html, Manual/create-apply-physics-material.html, Manual/collider-surface-friction.html, Manual/collider-surface-bounce.html, Manual/collider-surfaces-combine.html, Manual/collider-surfaces.html, ScriptReference/PhysicsMaterial.html, ScriptReference/PhysicsMaterialCombine.htmlFriction/bounciness values and the Average/Minimum/Maximum/Multiply combine modes (class is PhysicsMaterial in Unity 6, not the legacy PhysicMaterial name)
Joints (3D)Manual/Joints.html, Manual/joints-section.html, Manual/class-FixedJoint.html, Manual/class-HingeJoint.html, Manual/class-SpringJoint.html, Manual/class-ConfigurableJoint.html, Manual/class-CharacterJoint.html, Manual/create-configurable-joint.html, Manual/configurable-joints-movement-constraint.html, Manual/configurable-joints-driving-forces.htmlFixed/Hinge/Spring/Configurable/Character joint setup and ConfigurableJoint's per-axis motion/drive model
Joints (3D) scriptingScriptReference/Joint.html, ScriptReference/FixedJoint.html, ScriptReference/HingeJoint.html, ScriptReference/SpringJoint.html, ScriptReference/ConfigurableJoint.html, ScriptReference/CharacterJoint.htmlJoint base class members (connectedBody, breakForce) and per-joint scripting fields
Ragdolls & articulationsManual/ragdoll-physics-section.html, Manual/RagdollStability.html, Manual/wizard-RagdollWizard.html, Manual/physics-articulations.htmlRagdoll Wizard workflow, stability tuning, ArticulationBody for robotics-style joint chains (alternative to Joint-based ragdolls)
Layers & collision matrixManual/LayerBasedCollision.html, Manual/layers-and-layermasks.html, Manual/create-layers.html, Manual/use-layers.html, Manual/Layers.html, Manual/physics-optimization-cpu-collision-layers.html, ScriptReference/LayerMask.html, ScriptReference/LayerMask.GetMask.htmlAssigning physics layers, Project Settings collision matrix, building LayerMask bitmasks in code
Physics project settingsManual/class-PhysicsManager.html, Manual/class-TimeManager.htmlProject Settings > Physics panel (solver iterations, default material, bounce/contact thresholds) and Time panel (Fixed Timestep, Maximum Allowed Timestep)
Physics settings scriptingScriptReference/Physics-gravity.html, ScriptReference/Physics-defaultSolverIterations.html, ScriptReference/Physics-defaultSolverVelocityIterations.html, ScriptReference/Physics-bounceThreshold.html, ScriptReference/Physics-sleepThreshold.html, ScriptReference/Physics-defaultContactOffset.html, ScriptReference/Physics-queriesHitTriggers.html, ScriptReference/Physics-queriesHitBackfaces.html, ScriptReference/Physics-simulationMode.html, ScriptReference/Time-fixedDeltaTime.htmlGlobal physics tunables reachable from code, and the Physics.simulationMode enum (FixedUpdate/Update/Script)
Manual physics steppingManual/physics-optimization-cpu-manual-simulation.html, Manual/physics-optimization-cpu-frequency.html, ScriptReference/Physics.Simulate.htmlDriving the physics step yourself with Physics.Simulate when simulationMode is Script
Physics performance/optimizationManual/physics-optimization.html, Manual/physics-optimization-cpu.html, Manual/physics-optimization-cpu-broad-phase.html, Manual/physics-optimization-cpu-collider-types.html, Manual/physics-optimization-cpu-static-colliders.html, Manual/physics-optimization-cpu-transform-sync.html, Manual/physics-optimization-cpu-mesh-cooking-options.html, Manual/physics-optimization-cpu-query-only.html, Manual/physics-optimization-collision-callbacks.html, Manual/physics-optimization-memory.html, Manual/physics-performance-issues.html, Manual/ProfilerPhysics.html, Manual/PhysicsDebugVisualization.htmlCPU cost breakdown by subsystem, static vs dynamic collider cost, transform-sync cost, Physics Debug window, Profiler physics module
Multi-scene & backendManual/physics-multi-scene.html, Manual/physics-integrations.html, Manual/physics-remove-backend.htmlPer-scene physics worlds (PhysicsScene), swapping/removing the physics backend module
2D physics overviewManual/2d-physics/2d-physics.htmlLanding page for the entire 2D physics manual tree (verified correct path — do not use a bare Manual/2d-physics.html)
2D RigidbodyManual/2d-physics/rigidbody/rigidbody-2d-landing.html, Manual/2d-physics/rigidbody/introduction-to-rigidbody-2d.html, Manual/2d-physics/rigidbody/body-types/rigidbody-2d-body-types-landing.html, Manual/2d-physics/rigidbody/body-types/introduction-to-rigidbody-2d-body-types.html, Manual/2d-physics/rigidbody/rigidbody-2d-simulated-property.html, ScriptReference/Rigidbody2D.htmlRigidbody2D body types (Dynamic/Kinematic/Static), the simulated toggle
2D CollidersManual/2d-physics/collider/collider-2d-landing.html, Manual/2d-physics/collider/box-collider-2d-reference.html, Manual/2d-physics/collider/circle-collider-2d-reference.html, Manual/2d-physics/collider/edge-collider-2d-reference.html, Manual/2d-physics/collider/polygon-collider-2d-reference.html, Manual/2d-physics/collider/capsule-collider/capsule-collider-2d-landing.html, Manual/2d-physics/collider/composite-collider/composite-collider-2d-landing.html, Manual/2d-physics/collider/composite-collider/combine-colliders-composite-collider-2d.html, Manual/2d-physics/collider/custom-collider/custom-collider-2d-landing.html, Manual/2d-physics/collider/edit-collider-geometry.html, ScriptReference/Collider2D.htmlBox/Circle/Capsule/Edge/Polygon/Composite/Custom Collider2D types and geometry editing
2D JointsManual/2d-physics/joints/2d-joints-landing.html, Manual/2d-physics/joints/introduction-to-2d-joints.html, Manual/2d-physics/joints/2d-joint-constraints.html, Manual/2d-physics/joints/distance-joint-2d-landing.html, Manual/2d-physics/joints/fixed-joint-2d-landing.html, Manual/2d-physics/joints/hinge-joint-2d-landing.html, Manual/2d-physics/joints/slider-joint-2d-landing.html, Manual/2d-physics/joints/spring-joint-2d-landing.html, Manual/2d-physics/joints/wheel-joint-2d-landing.html, Manual/2d-physics/joints/relative-joint-2d-landing.html, Manual/2d-physics/joints/friction-joint-2d-landing.html, Manual/2d-physics/joints/target-joint-2d-landing.htmlEvery Joint2D type's fundamentals + reference sub-pages
2D EffectorsManual/2d-physics/effectors/effectors-2d-landing.html, Manual/2d-physics/effectors/area-effector-2d-reference.html, Manual/2d-physics/effectors/point-effector-2d-reference.html, Manual/2d-physics/effectors/platform-effector-2d-reference.html, Manual/2d-physics/effectors/surface-effector-2d-reference.html, Manual/2d-physics/effectors/buoyancy-effector-2d-reference.htmlArea/Point/Platform/Surface/Buoyancy effector fields, always paired with a Collider2D flagged Used By Effector
2D Physics Material & profilerManual/2d-physics/physics-material-2d-reference.html, Manual/2d-physics/constant-force-2d-reference.html, Manual/2d-physics/physics-profiler/physics-2d-profiler-landing.html, Manual/2d-physics/physics-profiler/physics-2d-profiler-module-reference.htmlPhysicsMaterial2D friction/bounciness, ConstantForce2D, the dedicated 2D Physics Profiler module
2D Physics API (low-level)Manual/2d-physics-api/2d-physics-api-introduction.html, Manual/2d-physics-api/2d-physics-api-world.html, Manual/2d-physics-api/2d-physics-api-physics-object.html, Manual/2d-physics-api/2d-physics-api-multithreading.html, Manual/2d-physics-api/2d-physics-api-raycasting.html, Manual/2d-physics-api/2d-physics-api-joints.htmlThe newer explicit PhysicsWorld2D/PhysicsBody2D job-friendly API layered under the classic 2D physics components
2D global settingsManual/class-Physics2DSettings.html, Manual/class-PhysicsLowLevelSettings2D.html, ScriptReference/Physics2D.Raycast.html, ScriptReference/Physics2D.OverlapCircle.html, ScriptReference/Physics2D.BoxCast.html, ScriptReference/Physics2D-autoSimulation.htmlProject Settings > Physics 2D panel, Physics2D.* static query/settings API (separate namespace from 3D Physics)
DOTS Unity Physics (alt. stack)Manual/com.unity.physics.html, Manual/com.unity.modules.physics.html, Manual/com.unity.modules.physics2d.html, Manual/com.unity.modules.terrainphysics.htmlPackage landing pages for the DOTS-based Unity.Physics package (ECS/burst-compiled, deterministic) vs the built-in GameObject PhysX-backed system covered by the rest of this table

Key Guidelines

Rigidbody & Movement

A Rigidbody hands a GameObject over to the physics solver: once attached (and not isKinematic), gravity, drag, and collision response act on it automatically, and the solver — not your script — is the source of truth for transform.position/rotation after each physics step. All physics-driven writes (AddForce, AddTorque, MovePosition, MoveRotation, reading/writing linearVelocity) belong in FixedUpdate, because the solver advances on a fixed timestep (Time.fixedDeltaTime, default 0.02s / 50Hz) that is decoupled from the variable per-frame Update rate — doing force math in Update makes motion framerate-dependent and non-reproducible across machines. Never assign transform.position directly to a non-kinematic Rigidbody; that snaps the body without going through the solver's velocity integration, causing jitter, tunneling, and missed collision events on the next step. If a Rigidbody must be positioned by external logic (e.g. an animation or a moving platform script) rather than by forces, mark it isKinematic = true and drive it with MovePosition/MoveRotation, which still generates correct collision/trigger events against non-kinematic bodies. Rigidbody.interpolation (None/Interpolate/Extrapolate) smooths the visual transform between fixed-timestep steps for cameras/rendering without affecting the simulation itself — use Interpolate on the player-controlled or camera-followed body and leave everything else None to save cost.

public class ForceMover : MonoBehaviour
{
    [SerializeField] private float thrust = 10f;
    private Rigidbody rb;

    void Awake()
    {
        rb = GetComponent<Rigidbody>();
        rb.interpolation = RigidbodyInterpolation.Interpolate; // smooth visuals only
        rb.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic; // fast mover vs fast/slow others
    }

    void FixedUpdate()
    {
        Vector3 input = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical"));
        rb.AddForce(input * thrust, ForceMode.Force); // continuous force, mass-dependent
        // rb.MovePosition(rb.position + input * speed * Time.fixedDeltaTime); // alternative: kinematic-style displacement
    }
}

Colliders & Triggers

A Collider defines the shape used for both physical collision response and trigger detection; it can exist with or without a Rigidbody, but at least one of the two colliding GameObjects in a pair must have a non-kinematic (or kinematic) Rigidbody for Unity to generate any callback at all — two static colliders (no Rigidbody on either) never fire OnCollisionEnter/OnTriggerEnter. isTrigger decides the behavior: with it on, the collider raises OnTriggerEnter/Stay/Exit and never generates a physical response (objects pass through it); with it off, the collider is solid, blocks motion, and raises OnCollisionEnter/Stay/Exit with contact-point/impulse data available via the Collision parameter. Prefer primitive colliders (Box/Sphere/Capsule) for anything that moves — they use analytic collision math and are far cheaper than Mesh Colliders. A MeshCollider is non-convex by default, which means it can only collide with primitive colliders and other convex mesh colliders, never with another non-convex mesh collider, and non-convex mesh colliders cannot be attached to a non-kinematic Rigidbody at all — check convex = true (capped at 255 triangles) if the shape must move or must collide with other meshes. Build complex static or moving shapes out of several primitive colliders on child GameObjects (compound colliders) rather than reaching for a Mesh Collider by default.

public class HazardTrigger : MonoBehaviour
{
    void Awake()
    {
        GetComponent<Collider>().isTrigger = true; // must be true to get OnTrigger* callbacks
    }

    void OnTriggerEnter(Collider other)
    {
        if (other.attachedRigidbody != null && other.CompareTag("Player"))
            Debug.Log("Player entered hazard zone");
    }

    void OnCollisionEnter(Collision collision) // only fires on a non-trigger collider pair
    {
        ContactPoint contact = collision.GetContact(0);
        Debug.Log($"Hit {collision.collider.name} at {contact.point} with impulse {collision.impulse}");
    }
}

Raycasting & Queries

Physics.Raycast and its siblings (RaycastAll, Linecast, SphereCast, BoxCast, CapsuleCast, OverlapSphere, OverlapBox, OverlapCapsule) are the query API for asking "what's out there" without waiting for a collision callback — used for ground checks, line-of-sight, weapon hit detection, and proximity checks. Every overload accepts an optional LayerMask and QueryTriggerInteraction; always pass an explicit LayerMask on any query run every frame (e.g. a ground check) to skip irrelevant colliders (UI hitboxes, VFX-only triggers, etc.) and cut query cost — an unfiltered raycast walks every collider layer in the scene's broad phase. Physics.Raycast returns a bool and fills a RaycastHit only on hit; RaycastAll allocates an array every call and is more expensive, so prefer the non-allocating Physics.RaycastNonAlloc variant in hot loops. Shape casts (SphereCast/BoxCast/CapsuleCast) sweep a volume instead of an infinitely thin line and are the right tool for fast-moving projectiles or characters where a thin raycast could miss thin geometry between frames — they cost more than a plain raycast, so reserve them for cases where tunneling is a real risk. OverlapSphere/OverlapBox test a static volume for overlapping colliders (no direction/distance), useful for "what's near me right now" checks like an explosion radius.

public class GroundCheck : MonoBehaviour
{
    [SerializeField] private LayerMask groundMask; // set in Inspector to only the "Ground" layer
    [SerializeField] private float checkDistance = 0.2f;

    bool IsGrounded()
    {
        Ray ray = new Ray(transform.position, Vector3.down);
        return Physics.Raycast(ray, out RaycastHit hit, checkDistance, groundMask, QueryTriggerInteraction.Ignore);
    }

    void FireHitscanWeapon(Vector3 origin, Vector3 direction, float range)
    {
        if (Physics.SphereCast(origin, 0.1f, direction, out RaycastHit hit, range, groundMask))
            Debug.Log($"Hit {hit.collider.name} at distance {hit.distance}");
    }
}

Layers & Collision Matrix

Physics layers (Project Settings > Tags and Layers) combined with the collision matrix (Project Settings > Physics, the "Layer Collision Matrix" grid) let Unity skip broad-phase collision checks entirely between layer pairs that are unchecked — this is cheaper and more centralized than filtering collisions in OnCollisionEnter/OnTriggerEnter code, because the excluded pairs never even reach the narrow phase. Leaving everything on the Default layer means the matrix can't selectively exclude anything, so assign meaningful layers (Player, Enemy, Ground, Projectile, Trigger-only, etc.) early in a project rather than retrofitting them later. LayerMask values used in scripts are bitmasks, not layer indices — build them with LayerMask.GetMask("Ground", "Wall") rather than hardcoding an index, since layer indices can be reordered by whoever edits the Tags and Layers list. Physics.IgnoreLayerCollision(layerA, layerB, ignore) and Physics.IgnoreCollision(colliderA, colliderB, ignore) can flip collision ignoring at runtime for cases the static matrix can't express (per-instance rather than per-layer), such as temporarily letting a player fall through a specific platform.

public class LayerSetup : MonoBehaviour
{
    [SerializeField] private LayerMask groundAndWallMask;

    void Start()
    {
        // equivalent runtime construction if the mask isn't set in the Inspector
        int mask = LayerMask.GetMask("Ground", "Wall");

        // runtime override of the static collision matrix for one specific pair of colliders
        Collider player = GetComponent<Collider>();
        Collider oneWayPlatform = GameObject.Find("OneWayPlatform").GetComponent<Collider>();
        Physics.IgnoreCollision(player, oneWayPlatform, true);
    }
}

Joints

Joints connect two Rigidbodies (or one Rigidbody to a fixed point in world space when connectedBody is left None) and constrain their relative motion instead of letting collision response do it. FixedJoint welds two bodies together but still lets both react individually to breakForce/breakTorque thresholds — useful for objects that should detach when hit hard enough. HingeJoint constrains motion to rotation about a single axis (doors, wheels, pendulums) and exposes a JointMotor for driving that rotation with a target velocity/force, plus optional JointLimits. SpringJoint pulls two bodies toward a target distance with spring/damper forces rather than a hard constraint — good for tethers and soft connections. ConfigurableJoint is the general case: every one of the 6 degrees of freedom (3 linear, 3 angular) is independently set to Free/Limited/Locked, with drive forces (xDrive/angularXDrive/etc.) able to actively motor an axis toward a target — this is how to build anything from a rigid weld (all locked) up to a custom vehicle suspension or a ragdoll limb, and it subsumes what the other joint types do as special cases. CharacterJoint is a ConfigurableJoint preset specialized for ragdoll limbs (twist + swing1/swing2 limits). Use the Ragdoll Wizard for a quick humanoid ragdoll rig; tune RagdollStability guidance (higher solver iterations, mass distribution) if limbs jitter. ArticulationBody/physics-articulations.html is a separate, more numerically stable alternative to Joint-chains for kinematic chains like robot arms or multi-segment ragdolls, and is generally preferred over stacked Joints for long chains because it doesn't accumulate the same soft-constraint drift.

public class DoorHinge : MonoBehaviour
{
    void Awake()
    {
        HingeJoint hinge = gameObject.AddComponent<HingeJoint>();
        hinge.connectedBody = null; // hinges to world space at this GameObject's anchor
        hinge.axis = Vector3.up;
        hinge.useLimits = true;
        hinge.limits = new JointLimits { min = 0f, max = 90f };
        hinge.useMotor = true;
        hinge.motor = new JointMotor { targetVelocity = 90f, force = 50f };
    }
}

2D Physics

2D physics is a separate simulation engine from 3D physics — Rigidbody2D/Collider2D run on Box2D-derived solver, have their own Project Settings > Physics 2D panel and their own collision matrix, and do not interact with Rigidbody/Collider at all. Decide 3D vs 2D per project, not per object. Rigidbody2D.bodyType (Dynamic/Kinematic/Static) replaces the 3D isKinematic bool with an explicit enum. Collider2D shapes cover Box/Circle/Capsule/Edge/Polygon, plus a CompositeCollider2D that merges multiple child colliders (each flagged usedByComposite) into one optimized outline — the standard pattern for tilemap collision. Joint2D types (Distance/Fixed/Hinge/Slider/Spring/Wheel/Relative/Friction/Target) mirror the 3D joint concepts but each ships as its own component rather than one configurable joint. 2D-only effectors (AreaEffector2D, PointEffector2D, PlatformEffector2D, SurfaceEffector2D, BuoyancyEffector2D) apply forces to any Rigidbody2D whose Collider2D has usedByEffector checked — no 3D equivalent exists; PlatformEffector2D in particular implements one-way platforms without runtime layer-ignoring tricks. A lower-level PhysicsWorld2D/PhysicsBody2D job-friendly API sits underneath the classic components for performance-critical, multithreaded 2D physics work (Manual/2d-physics-api/).

public class OneWayPlatform : MonoBehaviour
{
    void Awake()
    {
        var collider = GetComponent<Collider2D>();
        collider.usedByEffector = true;
        var effector = gameObject.AddComponent<PlatformEffector2D>();
        effector.useOneWay = true;
        effector.surfaceArc = 180f; // only collide from above
    }
}

CharacterController vs Rigidbody

CharacterController is a kinematic capsule moved explicitly via Move(Vector3) or SimpleMove(Vector3); it applies its own built-in step-offset and slope-limit handling, reports isGrounded and per-call CollisionFlags, and is not affected by incoming physics forces or pushed by other Rigidbodies — you get precise, jitter-free control at the cost of having to hand-code any push/knockback/platform-riding behavior yourself (typically inside OnControllerColliderHit). A Rigidbody-driven capsule (non-kinematic Rigidbody + CapsuleCollider, moved with AddForce/MovePosition in FixedUpdate) fully integrates with the solver — it can be pushed by explosions, can push other Rigidbodies, and interacts naturally with joints — but is harder to tune for the snappy, deterministic feel players expect from platformer/FPS controllers, since gravity, friction, and drag all fight the intended input. Choose CharacterController for traditional first/third-person controllers where precise, predictable movement matters most; choose a Rigidbody capsule when the character must be part of the physics simulation (rammed by vehicles, knocked back by explosions, ragdolls on death).

public class KinematicPlayer : MonoBehaviour
{
    private CharacterController controller;
    [SerializeField] private float speed = 5f;
    [SerializeField] private float gravity = -9.81f;
    private Vector3 velocity;

    void Awake() => controller = GetComponent<CharacterController>();

    void Update()
    {
        if (controller.isGrounded && velocity.y < 0) velocity.y = -2f; // small stick-to-ground bias
        Vector3 input = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
        controller.Move(input * speed * Time.deltaTime);
        velocity.y += gravity * Time.deltaTime;
        controller.Move(velocity * Time.deltaTime);
    }

    void OnControllerColliderHit(ControllerColliderHit hit)
    {
        if (hit.rigidbody != null && !hit.rigidbody.isKinematic)
            hit.rigidbody.AddForceAtPosition(controller.velocity * 0.1f, hit.point, ForceMode.Impulse); // manual push
    }
}

Common Mistakes

MistakeWhy it happens / fix
Moving a Rigidbody via transform.positionBypasses the solver's velocity integration, causing jitter and missed collisions; use Rigidbody.MovePosition/AddForce in FixedUpdate instead
Physics code in Update instead of FixedUpdateForces/velocity changes applied at a variable frame rate produce inconsistent, framerate-dependent motion; move all force/velocity/MovePosition calls into FixedUpdate
No Rigidbody on either side of a moving trigger/collider pairTwo static colliders (neither has a Rigidbody) never generate OnTriggerEnter/OnCollisionEnter; add a (often kinematic) Rigidbody to the moving object
Confusing OnTriggerEnter and OnCollisionEnterisTrigger=true gives callbacks but no physical response; isTrigger=false blocks motion and fires collision callbacks; using the wrong flag means either no blocking or no event ever fires
Everything left on the Default layerThe collision matrix can't selectively ignore pairs when nothing is differentiated; assign meaningful physics layers (Player/Enemy/Ground/Projectile) early
Non-convex Mesh Collider on a moving/non-kinematic RigidbodyNon-convex MeshCollider can't be attached to a non-kinematic body and can't collide with another non-convex mesh; set convex = true (255-tri cap) or swap to primitive colliders
Reading Rigidbody.linearVelocity/position mid-Update and expecting it reflects the latest physics stepThe solver only advances during FixedUpdate; values read in Update are from the last completed physics step, not "now" — this is usually fine but surprises people expecting sub-step precision
Fast/small objects tunneling through thin colliders (bullets, tiny balls)Default CollisionDetectionMode.Discrete only checks positions at each fixed step, missing objects that fully cross a thin collider between steps; set CollisionDetectionMode.Continuous (against static geometry) or ContinuousDynamic/ContinuousSpeculative (against other moving bodies) on the fast object
Unfiltered Physics.Raycast called every frame with no LayerMaskWalks every collider layer in the broad phase, wasting CPU on irrelevant hits (UI colliders, VFX triggers); always pass an explicit LayerMask built via LayerMask.GetMask for per-frame queries like ground checks
Using Physics.RaycastAll in a hot loopAllocates a new array on every call, creating GC pressure; use Physics.RaycastNonAlloc with a reusable buffer for anything called repeatedly
Pushing a CharacterController player with a Rigidbody explosion and expecting it to just workCharacterController ignores incoming physics forces entirely by design; apply knockback manually (e.g. add to a velocity field consumed by your own Move call) instead of AddForce
Two Rigidbodies welded with FixedJoint snapping apart unexpectedlybreakForce/breakTorque default to Mathf.Infinity only if left alone, but many templates set finite values; check both fields if a joint is breaking under normal gameplay forces
Ragdoll limbs jittering or explodingUsually too few solver iterations for the mass ratio between connected bodies, or colliders overlapping at rest; increase Physics.defaultSolverIterations/defaultSolverVelocityIterations or the Rigidbody's own solverIterations, and check RagdollStability guidance for mass/collider sizing
Mixing 3D and 2D physics components on the same object expecting them to interactRigidbody/Collider and Rigidbody2D/Collider2D are entirely separate simulations with separate collision matrices; a Rigidbody2D never collides with a 3D Collider, and vice versa
Assuming PhysicMaterial is the Unity 6 class nameThe physics material class was renamed to PhysicsMaterial (and PhysicsMaterial2D for 2D) in current Unity versions; scripts/tutorials referencing PhysicMaterial are targeting an older API surface

Quick Reference

ItemPurpose
Rigidbody / Rigidbody2DAdds mass, gravity, and solver-driven motion to a GameObject; isKinematic (3D) / bodyType (2D) switches between physics-driven and script-driven
Collider / Collider2DDefines the physical shape used for collision/trigger detection; isTrigger switches between physical blocking and trigger-only callbacks
BoxCollider / SphereCollider / CapsuleColliderCheapest, analytic-math primitive collider shapes; prefer these over Mesh Colliders for anything that moves
MeshColliderArbitrary-mesh collision shape; non-convex by default (static-only, can't collide with other non-convex meshes), or convex = true (255-tri cap, works on moving bodies)
WheelColliderVehicle wheel simulation with suspension, friction curves, motor/brake torque — not a physical shape by itself
TerrainColliderHeightmap-based collision matching a Terrain object, plus separate colliders for individual trees
CharacterControllerKinematic capsule movement via Move/SimpleMove, with built-in step offset, slope limit, isGrounded, and CollisionFlags
PhysicsMaterial / PhysicsMaterial2DPer-collider friction and bounciness, with PhysicsMaterialCombine modes (Average/Minimum/Maximum/Multiply) controlling how two materials combine on contact
Physics.Raycast / RaycastAll / RaycastNonAllocCast a thin ray against colliders, optionally filtered by LayerMask and QueryTriggerInteraction
Physics.SphereCast / BoxCast / CapsuleCastSweep a volume rather than a line — catches thin geometry a raycast could miss between frames
Physics.OverlapSphere / OverlapBox / OverlapCapsuleTest a static volume for currently-overlapping colliders (no direction/distance)
Physics.IgnoreCollision / IgnoreLayerCollisionRuntime override of collision ignoring for a specific collider pair or layer pair
Rigidbody.MovePosition / MoveRotationPhysics-safe ways to move/rotate a kinematic Rigidbody, generating correct collision events
Rigidbody.AddForce / AddForceAtPosition / AddTorquePhysics-safe ways to accelerate a non-kinematic Rigidbody; ForceMode (Force/Impulse/VelocityChange/Acceleration) controls mass-dependence and instant vs continuous application
Rigidbody.interpolationSmooths rendered transform between fixed-timestep steps (Interpolate/Extrapolate) without affecting simulation
Rigidbody.collisionDetectionModeDiscrete (cheap, default) vs Continuous/ContinuousDynamic/ContinuousSpeculative (costlier, prevents tunneling)
FixedJoint / HingeJoint / SpringJoint / ConfigurableJoint / CharacterJointConstrain relative motion between two Rigidbodies; ConfigurableJoint is the general 6-DOF case the others specialize
ArticulationBodyAlternative to Joint chains for kinematic chains (robot arms, long ragdoll chains); more numerically stable than stacked Joints
LayerMask / Project Settings collision matrixAssign physics layers and precompute which layer pairs the broad phase should even test, cheaper than per-callback filtering in code
Physics.simulationMode / Physics.SimulateSwitch between automatic FixedUpdate-driven stepping and manually stepping the solver with Physics.Simulate(deltaTime)
Time.fixedDeltaTime / Project Settings > TimeControls the physics solver's fixed timestep (default 0.02s / 50Hz)
AreaEffector2D / PointEffector2D / PlatformEffector2D / SurfaceEffector2D / BuoyancyEffector2D2D-only force fields that act on any Rigidbody2D whose Collider2D has usedByEffector checked
CompositeCollider2DMerges multiple child Collider2D shapes (flagged usedByComposite) into one optimized outline, the standard pattern for tilemap collision

Advanced Notes

Fixed timestep tuning. Time.fixedDeltaTime (Project Settings > Time > Fixed Timestep) sets how often the solver steps; smaller values give a more accurate simulation at higher CPU cost, larger values are cheaper but coarser (visible as choppier physics motion, especially under interpolation = None). Maximum Allowed Timestep caps how much simulated time a single frame is allowed to catch up on a slow frame — if a frame takes longer than this, Unity runs multiple FixedUpdate steps in a row (a "physics spiral of death" risk if the cap is too high and steps can't keep up); lowering the cap instead skips catching up fully and lets visible time slip. Physics.defaultSolverIterations/Physics-defaultSolverVelocityIterations (or per-Rigidbody solverIterations/solverVelocityIterations) trade CPU for constraint accuracy — raise them for stacks of joints/ragdolls that jitter, lower them for scenes with many simple non-interacting bodies. Set Physics.simulationMode to Script and drive stepping yourself with Physics.Simulate(step) for deterministic lockstep simulation (networked physics, replay systems) instead of relying on Unity's automatic FixedUpdate cadence — see Manual/physics-optimization-cpu-manual-simulation.html.

Static vs dynamic collider cost. Colliders on GameObjects with no Rigidbody are treated as static by the broad phase and are cheap to have many of, but moving a "static" collider's transform at runtime forces an expensive broad-phase rebuild — if a wall or platform needs to move, give it a kinematic Rigidbody rather than just moving its transform, so Unity treats it as dynamic and updates it cheaply instead of re-baking static state every frame (Manual/physics-optimization-cpu-static-colliders.html, Manual/physics-optimization-cpu-transform-sync.html).

Unity Physics / DOTS (alternative stack). Alongside the built-in GameObject/PhysX-backed system this skill otherwise documents, Unity ships a separate Unity.Physics package (Manual/com.unity.physics.html) built for the Entity Component System — burst-compiled, job-safe, and deterministic, aimed at large-scale simulations (thousands of bodies) and DOTS-based projects. It does not share components with Rigidbody/Collider (uses PhysicsVelocity, PhysicsCollider, etc. as ECS components instead) and is a project-level architecture choice, not a drop-in swap — reach for it only if the project is already ECS/DOTS-based or physics performance at GameObject scale has been profiled and found wanting.

Physics Debug window & Profiler. Manual/PhysicsDebugVisualization.html exposes a Physics Debug window (Window > Analysis > Physics Debug) to visualize colliders, contacts, and queries directly in-editor, independent of Gizmos code. The Profiler's dedicated Physics module (Manual/ProfilerPhysics.html) and the 2D-specific Physics 2D Profiler module (Manual/2d-physics/physics-profiler/physics-2d-profiler-module-reference.html) break down solver cost by phase (broad phase, narrow phase, solve, sync-transforms) — use these before guessing which optimization (layer matrix, collider type, solver iterations, sleep thresholds) will actually move the needle.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.