Physics Material
Physics Material là asset điều khiển bề mặt vật lý — mức ma sát (friction) và độ nảy (bounciness) khi hai Collider chạm nhau, từ băng trơn đến bóng cao su.
Hãy tưởng tượng...
Physics Material giống như loại vật liệu bề mặt sân chơi. Sân bê tông thô ráp → bóng dừng lại nhanh (ma sát cao). Sàn đá đánh bóng → bóng trượt xa (ma sát thấp). Bề mặt cao su → bóng nảy lên cao (bounciness cao). Đệm cát → bóng thụp ngay (bounciness thấp). Trong Unity, bạn tạo Physics Material như một asset riêng, rồi gán vào bất kỳ Collider nào để thay đổi cách nó tương tác với thế giới vật lý.
Khái niệm chi tiết
Physics Material (file .physicMaterial trong 3D, .physicsMaterial2D
trong 2D) là ScriptableObject-like asset với 4 thuộc tính chính:
Dynamic Friction (ma sát khi đang trượt, 0–1),
Static Friction (ma sát khi bắt đầu từ đứng yên, thường
cao hơn Dynamic), Bounciness (0 = không nảy, 1 = nảy
hoàn toàn), và hai chế độ kết hợp Friction Combine và
Bounce Combine (Average/Min/Max/Multiply).
Khi hai Collider có Physics Material khác nhau va chạm, Unity kết hợp giá trị của chúng theo Combine Mode. Ví dụ với Average: friction = (frictionA
- frictionB) / 2. Với Minimum: friction = min(frictionA, frictionB) — hữu ích cho bề mặt băng (1 bên = 0 luôn thắng). Thứ tự ưu tiên kết hợp: Average < Minimum < Maximum < Multiply.
Một lưu ý quan trọng: Bounciness = 1 trong Unity
không phải nảy hoàn toàn không mất năng lượng. Unity
vẫn áp dụng damping và gravity giữa các bounce. Để có bouncing gần hoàn hảo, cần kết hợp
Bounciness = 1 với Bounce Combine = Maximum và giảm Rigidbody drag về 0.
Bạn có thể thay đổi Physics Material tại runtime bằng cách gán vào
collider.material hoặc collider.sharedMaterial. Dùng
sharedMaterial khi muốn thay đổi ảnh hưởng đến toàn bộ instance dùng cùng material
(tiết kiệm bộ nhớ).
Preset vật liệu thực tế
🧱 Gạch
Dynamic Friction: 0.6
Static Friction: 0.6
Bounciness: 0.0
🧊 Băng
Dynamic Friction: 0.02
Static Friction: 0.02
Bounciness: 0.0
🏀 Cao su
Dynamic Friction: 0.8
Static Friction: 0.8
Bounciness: 0.8
🪵 Gỗ
Dynamic Friction: 0.48
Static Friction: 0.48
Bounciness: 0.0
| Combine Mode | Công thức | Dùng khi |
|---|---|---|
| Average | (A + B) / 2 | Mặc định, trung bình |
| Minimum | min(A, B) | Băng (1 bên = 0 thắng) |
| Maximum | max(A, B) | Cao su (bounce cực đại) |
| Multiply | A × B | Mặt dính, nhân bội |
Hướng dẫn thực hành
Tạo Physics Material
Project Panel → chuột phải → Create → Physics Material (3D) hoặc Physics Material 2D. Đặt tên theo vật liệu (Rubber, Ice...).
Thiết lập giá trị Friction và Bounciness
Dynamic Friction (0–1), Static Friction (0–1), Bounciness (0–1). Tham khảo bảng preset hoặc tự thử nghiệm.
Chọn Combine Mode phù hợp
Friction/Bounce Combine: Average là mặc định. Dùng Minimum cho băng, Maximum cho cao su nảy.
Gán vào Collider
Chọn GameObject → Collider component → slot "Material" → kéo thả Physics Material từ Project vào.
Play và tinh chỉnh
Chạy game, quan sát cách vật thể di chuyển và điều chỉnh giá trị. Có thể edit Physics Material ngay khi đang play.
Trình mô phỏng tương tác
Điều chỉnh Friction và Bounciness rồi thả bóng để xem hiệu ứng thực tế.
Thiết lập thông số và nhấn "Thả bóng"
Ví dụ Code
Cơ bảnThay đổi Physics Material tại runtime khi nhân vật đứng trên bề mặt khác nhau.
using UnityEngine;
public class SurfaceMaterialSwapper : MonoBehaviour
{
public PhysicMaterial normalMat, iceMat, rubberMat;
Collider col;
void Start() => col = GetComponent<Collider>();
void OnCollisionStay(Collision collision)
{
// Đọc surface tag từ mặt đất đang đứng
string tag = collision.gameObject.tag;
col.material = tag switch
{
"Ice" => iceMat,
"Rubber" => rubberMat,
_ => normalMat,
};
}
void OnCollisionExit(Collision _)
{
col.material = normalMat; // Phục hồi khi rời mặt đất
}
}Ví dụ Code
Nâng caoTạo Physics Material động tại runtime và điều chỉnh theo trạng thái game.
using UnityEngine;
// Tạo và quản lý PhysicMaterial động — không cần asset file
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>();
// Tạo PhysicMaterial lúc runtime, không cần Project asset
dynMat = new PhysicMaterial("Dynamic")
{
dynamicFriction = friction,
staticFriction = friction * 1.2f,
bounciness = bounciness,
frictionCombine = PhysicMaterialCombine.Average,
bounceCombine = PhysicMaterialCombine.Maximum
};
col.material = dynMat;
}
// Gọi từ nơi khác để thay đổi realtime (ví dụ: khi nhân vật bị đóng băng)
public void SetIce()
{
dynMat.dynamicFriction = 0.01f;
dynMat.staticFriction = 0.01f;
col.material = dynMat; // Gán lại để Unity nhận giá trị mới
}
}📌 Ghi nhớ nhanh
- ▸0 = không ma sát / không nảy, 1 = tối đa
- ▸Static Friction > Dynamic Friction (thực tế vật lý)
- ▸Minimum Combine: 1 bên = 0 → tổng = 0 (băng lý tưởng)
- ▸col.material tạo bản sao riêng; sharedMaterial dùng chung
- ▸Cần gán lại col.material sau khi chỉnh PhysicMaterial runtime
⚠️ Lỗi thường gặp
❌ Chỉnh collider.material.bounciness = X mà không gán lại
Unity không detect thay đổi nội bộ — giá trị không update
✅ Tạo giá trị mới và gán lại: col.material = updatedMat;
❌ Đặt Bounciness = 1 nhưng bóng vẫn mất năng lượng
Rigidbody.drag > 0 và gravity tiêu thụ năng lượng
✅ Đặt drag = 0 và Bounce Combine = Maximum