Quick answer: Friction is combined between both colliding surfaces using the Friction Combine mode — Average, Min, Max, or Multiply. A high-friction material touching a zero-friction one may produce zero friction if either side uses Min. Set Combine mode on both colliders and assign the material to the Collider component, not the Rigidbody.
Here is how to fix Unity physics material friction not working. You create a PhysicMaterial called “Ice” with friction 0 and assign it to your ice platform. The player slides on it perfectly. You create “Rubber” with friction 1 for rubber surfaces — the player still slides. You raise friction to 10 — no change. PhysX takes the friction from both colliding surfaces and combines them, and the combine rules are where most bugs happen.
The Symptom
Setting PhysicMaterial friction or bounciness values produces no apparent effect at runtime. Objects slide when they should grip, or fall flat when they should bounce. The editor shows the material assigned correctly; the Rigidbody is awake and simulating; forces apply normally — but surface properties do not behave as expected.
What Causes This
Combine mode resolution. When two surfaces contact, PhysX combines their friction values according to the “Friction Combine” mode on the material. Options: Average (both values averaged), Minimum (smallest wins), Maximum (largest wins), Multiply (multiplied). The resolution uses the maximum of the two modes’ enum values — one material set to Minimum pulls the result toward the lowest friction.
Default floor has no material. An unadorned cube with a default Collider has no PhysicMaterial assigned — Unity uses defaults (friction 0.6, bounce 0, Combine Average). If your player’s material is set to Minimum with friction 0 and the floor has Average, you get minimum(0, 0.6) = 0. Slippery floor despite a “grippy” setting on the floor.
Material on wrong component. PhysicMaterial goes on the Collider’s Material slot, not the Rigidbody. Assigning to a GameObject field has no effect. Unity does not error on this, just ignores it.
2D vs 3D mismatch. 2D physics uses PhysicsMaterial2D; 3D uses PhysicMaterial. They are different asset types. Assigning a 3D material to a 2D collider does not work and vice versa.
High velocity skids. At very high relative velocities, PhysX uses dynamic friction (not static friction) for contact resolution. Dynamic friction is typically lower. A “high friction” material may still feel slippery at speed because the dynamic coefficient is different from the static one you set.
The Fix
Step 1: Set both static and dynamic friction. Open the PhysicMaterial asset:
- Dynamic Friction: friction when surfaces slide relative to each other
- Static Friction: friction when surfaces are at rest
- Bounciness: 0 = no bounce, 1 = perfect bounce
- Friction Combine: Average (default), Minimum, Maximum, Multiply
- Bounce Combine: same options
For grippy surfaces, set both Static and Dynamic Friction to 1.0. Combine = Maximum ensures grippy wins over less grippy.
// Alternative: set at runtime
using UnityEngine;
public class MaterialSwap : MonoBehaviour
{
[SerializeField] private PhysicMaterial iceMaterial;
[SerializeField] private PhysicMaterial groundMaterial;
public void EnterIceZone()
{
GetComponent<Collider>().material = iceMaterial;
}
public void ExitIceZone()
{
GetComponent<Collider>().material = groundMaterial;
}
}
Step 2: Use Maximum Combine for definitive behavior. If you want “the high-friction surface wins,” set Friction Combine = Maximum on the high-friction material. Regardless of what the other side has, friction will be at least your material’s value.
For ice “the low-friction wins”, set Ice’s Combine = Minimum. Anything touching ice becomes slippery.
Be careful combining both intents. Rubber = Maximum, Ice = Minimum, Rubber touches Ice: Unity picks the MAX of the two enum values, applying whichever is “louder.”
Step 3: Assign on Collider, not elsewhere. Double-click your prefab. Select the GameObject with the Collider component. In the Inspector, find the Collider’s Material field (below the collider’s size/offset). Drag your PhysicMaterial there.
If the GameObject has multiple colliders (common for complex shapes), each needs its own material assignment.
Step 4: Verify at runtime. Log the effective friction during a contact to confirm what physics is using:
void OnCollisionStay(Collision col)
{
var myMat = GetComponent<Collider>().material;
var otherMat = col.collider.material;
Debug.Log($"Mine: {myMat.dynamicFriction} ({myMat.frictionCombine}), " +
$"Other: {otherMat.dynamicFriction} ({otherMat.frictionCombine})");
}
If you see unexpected values, the material assignment is wrong somewhere. If values look right but behavior is off, try changing Combine modes to see the effect.
2D Equivalent
For 2D, create PhysicsMaterial2D (different asset type). Assign to Collider2D components. Properties: Friction (one value) and Bounciness. No separate Combine modes in 2D — values are averaged. Set both colliding sides to the desired value for predictable behavior.
Character Controllers vs Rigidbody
CharacterController does not use PhysicMaterial at all. Friction on a CharacterController-driven character is simulated in your script (usually reducing velocity in FixedUpdate). Assigning a material to the collider on a CharacterController does nothing.
Switch to Rigidbody + Capsule Collider if you want physics materials to affect your character’s movement.
“Friction is a contract between two surfaces. If you want one to dictate, use Maximum. If you want the other to, use Minimum on its material. Always set both sides deliberately.”
Related Issues
For rigidbody sleep behavior, see Unity Rigidbody Sleeping Too Early. For collision detection, OnCollisionEnter Not Called covers related physics interaction bugs.
Material on Collider. Friction Combine = Maximum for grippy wins. Both sides matter.