Unity物理演算とは
Physicsは、現実世界の物理法則をシミュレートする機能です。重力、衝突、力などを自動計算します。
物理演算でできること
- 🎾 重力による落下
- 💥 リアルな衝突反応
- 🚗 車や物体の動き
- ⚽ ボールの跳ね返り
- 🎯 弾道計算
Rigidbody - 物理挙動の基本
Rigidbodyの追加
1. GameObjectを選択
2. Add Component > Physics > Rigidbody
3. Inspector で設定を調整主要なプロパティ
- Mass(質量): 物体の重さ(デフォルト: 1)
- Drag(空気抵抗): 移動の抵抗(0-∞)
- Angular Drag: 回転の抵抗
- Use Gravity: 重力の有効/無効
- Is Kinematic: 物理演算を無効化(スクリプトで制御)
Constraints(制約)
// 位置の固定
Freeze Position: X, Y, Z
// 回転の固定
Freeze Rotation: X, Y, Z例: 2DゲームではFreeze Rotation Z以外をチェック。
力の加え方
AddForce(力を加える)
public class ForceExample : MonoBehaviour
{
private Rigidbody rb;
public float forcePower = 10.0f;
void Start()
{
rb = GetComponent();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
// 継続的な力
rb.AddForce(Vector3.up * forcePower, ForceMode.Force);
// 瞬間的な力(ジャンプなど)
rb.AddForce(Vector3.up * forcePower, ForceMode.Impulse);
}
}
} ForceModeの種類
- Force: 継続的な力(質量を考慮)
- Impulse: 瞬間的な力(ジャンプ、爆発)
- Acceleration: 継続的な加速度(質量無視)
- VelocityChange: 瞬間的な速度変化(質量無視)
速度の直接設定
void FixedUpdate()
{
// 速度を直接設定
rb.velocity = new Vector3(5, 0, 0);
// Y軸速度はそのまま、XZ軸のみ設定
rb.velocity = new Vector3(5, rb.velocity.y, 0);
// 角速度
rb.angularVelocity = new Vector3(0, 2, 0);
}Collider - 当たり判定
主要なColliderの種類
- Box Collider: 箱型(壁、床、立方体)
- Sphere Collider: 球型(ボール、爆弾)
- Capsule Collider: カプセル型(キャラクター)
- Mesh Collider: メッシュ形状(複雑な地形)
Colliderの設定
// Inspectorで設定
Is Trigger: チェックなし = 物理衝突あり
チェックあり = すり抜ける(イベントのみ)
Material: 物理マテリアル(摩擦、弾性)
Center: 中心位置のオフセット
Size/Radius: サイズTrigger vs Collision
// Trigger(すり抜ける)
void OnTriggerEnter(Collider other) { }
void OnTriggerStay(Collider other) { }
void OnTriggerExit(Collider other) { }
// Collision(物理衝突)
void OnCollisionEnter(Collision collision) { }
void OnCollisionStay(Collision collision) { }
void OnCollisionExit(Collision collision) { }Physical Material - 物理マテリアル
作成と設定
1. Project > 右クリック > Create > Physic Material
2. 名前を付ける(例: Bouncy)
3. Colliderの Material に設定主要なプロパティ
- Dynamic Friction(動摩擦): 0-1(0=滑る、1=止まる)
- Static Friction(静止摩擦): 0-1
- Bounciness(弾性): 0-1(0=弾まない、1=完全弾性)
- Friction Combine: 摩擦の合成方法
- Bounce Combine: 弾性の合成方法
例: ボールの設定
Dynamic Friction: 0.3
Static Friction: 0.3
Bounciness: 0.8
Bounce Combine: Maximum実用的な物理演算例
例1: ジャンプ
public class Jump : MonoBehaviour
{
private Rigidbody rb;
public float jumpForce = 5.0f;
private bool isGrounded = true;
void Start()
{
rb = GetComponent();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space) && isGrounded)
{
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
isGrounded = false;
}
}
void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Ground"))
{
isGrounded = true;
}
}
} 例2: 車の移動
public class CarController : MonoBehaviour
{
private Rigidbody rb;
public float acceleration = 10.0f;
public float turnSpeed = 50.0f;
void Start()
{
rb = GetComponent();
rb.centerOfMass = new Vector3(0, -0.5f, 0); // 重心を下げる
}
void FixedUpdate()
{
float moveInput = Input.GetAxis("Vertical");
float turnInput = Input.GetAxis("Horizontal");
// 前進
rb.AddForce(transform.forward * moveInput * acceleration);
// 回転
if (Mathf.Abs(moveInput) > 0.1f)
{
transform.Rotate(0, turnInput * turnSpeed * Time.fixedDeltaTime, 0);
}
}
} 例3: 爆発エフェクト
public class Explosion : MonoBehaviour
{
public float explosionForce = 500.0f;
public float explosionRadius = 5.0f;
void Explode()
{
Collider[] colliders = Physics.OverlapSphere(transform.position, explosionRadius);
foreach (Collider hit in colliders)
{
Rigidbody rb = hit.GetComponent();
if (rb != null)
{
rb.AddExplosionForce(explosionForce, transform.position, explosionRadius);
}
}
}
} 例4: プレイヤーの移動(滑らか)
public class SmoothMovement : MonoBehaviour
{
private Rigidbody rb;
public float moveSpeed = 5.0f;
public float maxSpeed = 10.0f;
void Start()
{
rb = GetComponent();
}
void FixedUpdate()
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(h, 0, v).normalized * moveSpeed;
// 速度制限
if (rb.velocity.magnitude < maxSpeed)
{
rb.AddForce(movement);
}
}
} Raycast - レイキャスト
基本的な使い方
void Update()
{
Ray ray = new Ray(transform.position, transform.forward);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 10.0f))
{
Debug.Log("Hit: " + hit.collider.gameObject.name);
Debug.Log("Distance: " + hit.distance);
Debug.Log("Point: " + hit.point);
}
}レイの可視化
void Update()
{
Vector3 forward = transform.TransformDirection(Vector3.forward) * 10;
Debug.DrawRay(transform.position, forward, Color.green);
}地面判定
bool IsGrounded()
{
return Physics.Raycast(transform.position, Vector3.down, 0.1f);
}レイヤーマスクで特定オブジェクトのみ
LayerMask mask = LayerMask.GetMask("Enemy", "Obstacle");
if (Physics.Raycast(ray, out hit, 100.0f, mask))
{
// EnemyかObstacleレイヤーにのみ反応
}OverlapSphere - 範囲内の検出
基本的な使い方
void DetectNearbyObjects()
{
Collider[] hitColliders = Physics.OverlapSphere(transform.position, 5.0f);
foreach (Collider collider in hitColliders)
{
Debug.Log("Nearby: " + collider.gameObject.name);
}
}実用例: 範囲攻撃
public class AreaAttack : MonoBehaviour
{
public float attackRadius = 3.0f;
public int damage = 50;
void Attack()
{
Collider[] enemies = Physics.OverlapSphere(transform.position, attackRadius);
foreach (Collider enemy in enemies)
{
if (enemy.CompareTag("Enemy"))
{
enemy.GetComponent()?.TakeDamage(damage);
}
}
}
void OnDrawGizmosSelected()
{
// Sceneビューで範囲を可視化
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, attackRadius);
}
} Joint - ジョイント
Fixed Joint(固定)
// 2つのオブジェクトを固定
FixedJoint joint = gameObject.AddComponent();
joint.connectedBody = otherRigidbody; Hinge Joint(蝶番)
ドア、橋、振り子などに使用。
HingeJoint hinge = GetComponent();
hinge.axis = new Vector3(0, 1, 0); // Y軸回転
hinge.useLimits = true;
JointLimits limits = new JointLimits();
limits.min = 0;
limits.max = 90;
hinge.limits = limits; Spring Joint(バネ)
SpringJoint spring = gameObject.AddComponent();
spring.connectedBody = targetRigidbody;
spring.spring = 50.0f;
spring.damper = 5.0f; パフォーマンス最適化
1. FixedUpdateを使う
// ❌ 悪い例
void Update()
{
rb.AddForce(force);
}
// ✅ 良い例
void FixedUpdate()
{
rb.AddForce(force);
}2. Mesh Colliderは慎重に
Mesh Collider同士の衝突は重い- 静的オブジェクトにのみ使用推奨
- 可能ならBox/Sphere/Capsule Colliderを使う
3. Rigidbodyのスリープ
// 動いていないRigidbodyは自動的にスリープ
rb.sleepThreshold = 0.1f; // デフォルト: 0.0054. レイヤーの衝突マトリクス
Edit > Project Settings > Physics
// 不要な衝突を無効化してパフォーマンス向上トラブルシューティング
オブジェクトが貫通する
- Continuous Collision Detection を使う
rb.collisionDetectionMode = CollisionDetectionMode.Continuous;ジャンプが二段ジャンプになる
// OnCollisionEnterではなくRaycastで地面判定
bool IsGrounded()
{
return Physics.Raycast(transform.position, Vector3.down, 0.1f);
}回転がおかしい
// 不要な回転を固定
Rigidbody > Constraints > Freeze Rotation にチェック物理演算が不安定
Edit > Project Settings > Time
Fixed Timestep: 0.02 (50fps) または 0.01667 (60fps)まとめ
Unity物理演算を理解すれば、リアルで楽しいゲームが作れます。
重要ポイント
- Rigidbodyで物理挙動を追加
- Colliderで当たり判定
- AddForceで力を加える
- FixedUpdate()で物理演算を制御
- Raycastで精密な検出
次のステップ
- Character Controllerの使用
- 3D物理と2D物理の違い
- カスタム物理マテリアル
- 高度なジョイント活用