Unity Term Book
物理

Physics Material

Physics Material は表面の物理を制御するアセットです——二つの Collider が触れたときの摩擦と弾みを、氷の滑りからゴムボールまで表現します。Friction Combine と実行時の差し替え方を実践的に整理できます。図解とシミュレーターで摩擦と弾みを試し、自学にも使えます。

想像してみてください...

Physics Material は遊び場の地面です。ざらざらしたコンクリート → 球はすぐ止まる(高摩擦)。 磨いた石 → 遠くまで滑る(低摩擦)。ゴム → 高く跳ねる(高弾み)。砂 → 鈍く落ちる(低弾み)。 Unity では Physics Material を独立アセットとして作り、任意の Collider に割り当てて世界との関わり方を変えます。

概念の詳細

Physics Material(3D では .physicMaterial、2D では .physicsMaterial2D )は ScriptableObject 風のアセットで、主な四つのフィールドがあります: Dynamic Friction(滑走中、0–1)、 Static Friction(静止から動き出す、通常 Dynamic より高い)、 Bounciness(0 = 弾まない、1 = 最大弾み)、および二つの Combine —— Friction Combine と Bounce Combine(Average/Min/Max/Multiply)。

異なる Physics Material の Collider が触れると、Unity が値を合成します。 Average:friction = (frictionA + frictionB) / 2。 Minimum:friction = min(frictionA, frictionB) — 氷に便利(片方が 0 なら常に勝つ)。Combine の優先度:Average < Minimum < Maximum < Multiply。

重要:Unity で Bounciness = 1 は完全な無損失跳ねではありません。 減衰と重力は跳ねの間も効きます。ほぼ完全な跳ねには Bounciness = 1、 Bounce Combine = Maximum、Rigidbody drag = 0 を使います。

実行時に collider.material または collider.sharedMaterial で差し替えできます。同じアセットを共有する全インスタンスに 効かせたいときは sharedMaterial(メモリ節約)。

実世界のマテリアルプリセット

🧱 レンガ

Dynamic Friction: 0.6

Static Friction: 0.6

Bounciness: 0.0

🧊 氷

Dynamic Friction: 0.02

Static Friction: 0.02

Bounciness: 0.0

🏀 ゴム

Dynamic Friction: 0.8

Static Friction: 0.8

Bounciness: 0.8

🪵 木材

Dynamic Friction: 0.48

Static Friction: 0.48

Bounciness: 0.0

Combine Mode計算式使うとき
Average(A + B) / 2デフォルト、平均
Minimummin(A, B)氷(片方が 0 ならそちらが勝つ)
Maximummax(A, B)ゴム(最大バウンス)
MultiplyA × B粘着面、乗算

ハンズオン手順

1

Physics Material を作成

Project Panel → 右クリック → Create → Physics Material(3D)または Physics Material 2D。表面名で命名(Rubber、Ice…)。

2

Friction と Bounciness を設定

Dynamic Friction(0–1)、Static Friction(0–1)、Bounciness(0–1)。プリセット表を使うか実験。

3

Combine Mode を選ぶ

Friction/Bounce Combine:デフォルトは Average。氷は Minimum、弾むゴムは Maximum。

4

Collider に割り当て

GameObject を選択 → Collider → "Material" スロット → Project から Physics Material をドラッグ。

5

Play して調整

Play Mode に入り動きを見て値を調整。再生中も Physics Material を編集できます。

インタラクティブシミュレーター

Friction と Bounciness を調整し、球を落として効果を確認しましょう。

パラメータを設定して「ボールを落とす」

コード例

基本

キャラが異なる表面に立つとき、実行時に Physics Material を差し替える。

using UnityEngine;

public class SurfaceMaterialSwapper : MonoBehaviour
{
  public PhysicMaterial normalMat, iceMat, rubberMat;
  Collider col;

  void Start() => col = GetComponent<Collider>();

  void OnCollisionStay(Collision collision)
  {
      // Read the ground tag
      string tag = collision.gameObject.tag;

      col.material = tag switch
      {
          "Ice"    => iceMat,
          "Rubber" => rubberMat,
          _        => normalMat,
      };
  }

  void OnCollisionExit(Collision _)
  {
      col.material = normalMat; // Restore when leaving the ground
  }
}

コード例

上級

実行時に Physics Material を作りゲーム状態から調整——アセットファイル不要。

using UnityEngine;

// Create and own a PhysicMaterial at runtime — no Project asset
public class DynamicPhysicsMaterial : MonoBehaviour
{
  Collider col;
  PhysicMaterial dynMat;

  [Range(0f, 1f)] public float friction = 0.4f;
  [Range(0f, 1f)] public float bounciness = 0f;

  void Awake()
  {
      col = GetComponent<Collider>();

      // Runtime PhysicMaterial, no Project asset needed
      dynMat = new PhysicMaterial("Dynamic")
      {
          dynamicFriction  = friction,
          staticFriction   = friction * 1.2f,
          bounciness       = bounciness,
          frictionCombine  = PhysicMaterialCombine.Average,
          bounceCombine    = PhysicMaterialCombine.Maximum
      };

      col.material = dynMat;
  }

  // Call from elsewhere to change live (e.g. character frozen)
  public void SetIce()
  {
      dynMat.dynamicFriction = 0.01f;
      dynMat.staticFriction  = 0.01f;
      col.material = dynMat; // Re-assign so Unity picks up the new values
  }
}

📌 要点

  • ▸0 = 摩擦なし / 弾みなし、1 = 最大
  • ▸Static Friction > Dynamic Friction(実物理)
  • ▸Minimum Combine:片方が 0 → 結果も 0(理想の氷)
  • ▸col.material は私有コピー;sharedMaterial は共有
  • ▸実行時に PhysicMaterial を編集したら col.material を再代入

⚠️ よくあるミス

  • ❌ 再代入せず collider.material.bounciness = X

    Unity が内側の変更を検知せず——値が古いまま

    ✅ 新値を作って代入:col.material = updatedMat;

  • ❌ Bounciness = 1 なのに球がエネルギーを失う

    Rigidbody.drag > 0 と重力がエネルギーを食う

    ✅ drag = 0 と Bounce Combine = Maximum