Unityで接触時の物体の傾きを防止する方法
質問内容
Unityで物体同士が接触した際に体が傾くのを無くしたいです。キャラクターや物体が他のオブジェクトと接触すると不自然に傾いてしまう問題を解決する方法を教えてください。
回答
こんにちは!Unityで物体が接触時に傾いてしまう問題は、多くの開発者が直面する一般的な課題です。この問題を解決するための最も効果的な方法の一つが、Rigidbodyのコンストレイント(制約)機能を活用することです。
1. Rigidbodyのコンストレイントとは
Rigidbodyコンストレイントは、物理演算が適用されるオブジェクトの動きを特定の軸に沿って制限するための機能です。これにより、物理エンジンの計算に基づく不要な動きを選択的に無効化できます。
// 基本的な使用例
using UnityEngine;
public class PlayerController : MonoBehaviour
{
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
// すべての回転を凍結
rb.constraints = RigidbodyConstraints.FreezeRotation;
}
}
2. 実践的な使用例
2.1 完全に回転を防止する
キャラクターや物体が全く傾かないようにしたい場合は、すべての回転軸を凍結します。
// すべての回転を凍結
rb.constraints = RigidbodyConstraints.FreezeRotation;
2.2 特定の軸のみ回転を防止する
多くのゲームでは、Y軸(垂直軸)を中心とした回転は許可しつつ、X軸とZ軸の回転を防止したい場合があります。
// X軸とZ軸の回転を凍結(Y軸回転のみ許可)
rb.constraints = RigidbodyConstraints.FreezeRotationX |
RigidbodyConstraints.FreezeRotationZ;
2.3 位置の固定と組み合わせる
場合によっては、回転だけでなく特定の軸の移動も制限したい場合があります。
// Y軸の移動と、X軸とZ軸の回転を凍結
rb.constraints = RigidbodyConstraints.FreezePositionY |
RigidbodyConstraints.FreezeRotationX |
RigidbodyConstraints.FreezeRotationZ;
3. よくある失敗パターンと解決策
3.1 コンストレイントの過剰制限
❌ 悪い例:
// すべての動きを凍結してしまう
rb.constraints = RigidbodyConstraints.FreezeAll;
✅ 改善例:
// 必要な軸のみ凍結する
rb.constraints = RigidbodyConstraints.FreezeRotationX |
RigidbodyConstraints.FreezeRotationZ;
3.2 衝突時の力の無視
❌ 悪い例:
// 衝突の力を完全に無視してしまう
void OnCollisionEnter(Collision collision) {
rb.velocity = Vector3.zero;
rb.angularVelocity = Vector3.zero;
}
✅ 改善例:
// 衝突後に回転のみリセット
void OnCollisionEnter(Collision collision) {
Vector3 currentRotation = transform.rotation.eulerAngles;
transform.rotation = Quaternion.Euler(0, currentRotation.y, 0);
}
4. ベストプラクティス
-
必要最小限の制約を使用する
- ゲームの種類や求められる動きに応じて、必要な軸のみを制限しましょう
-
状況に応じた動的な制約の変更
// 通常時の制約
void SetNormalMovement() {
rb.constraints = RigidbodyConstraints.FreezeRotationX |
RigidbodyConstraints.FreezeRotationZ;
}
- インスペクタからの設定
- スクリプトでの設定だけでなく、Unityエディタのインスペクタからも制約を設定できます
- Rigidbodyコンポーネントの「Constraints」セクションで各軸のチェックボックスを操作します
実装時の注意点
- コンストレイントを設定しても、衝突の力そのものが消えるわけではありません
- 回転が防止されることで、力がほかの方向に向かうことがあります
isKinematic = trueを設定すると、物理演算が完全に無効化されるため注意が必要です- Character Controllerを使う場合は、Rigidbodyは通常不要です
参考資料とリンク
更新履歴
- 2025-03-02: 初版作成
この回答は、Unity 2022.3 LTSを基準に作成されています。新しいバージョンでは仕様が変更されている可能性があるため、適宜公式ドキュメントを参照してください。