入力と物理演算
プレイヤーを操作するには入力を読み取り、その値をオブジェクトの動きへ反映します。物理演算を使う場合は、入力を読むタイミングとRigidbodyを動かすタイミングを分けることが重要です。
入力システムを選ぶ
Unityにはキーボード、マウス、ゲームパッドなどを扱う仕組みがあります。Input System Packageは現在のUnityで推奨される拡張可能な方式です。旧Input Manager APIはInput.GetAxisやInput.GetKeyなどを使う従来方式です。この章のコードは旧Input Manager APIを使用します。プロジェクト設定のActive Input HandlingでInput ManagerまたはBothを有効にしてください。Input System Packageのみの設定では、そのまま動作しません。
入力を取得する
using UnityEngine;
public class InputReader : MonoBehaviour
{
public Vector2 MoveInput { get; private set; }
void Update()
{
float horizontal = Input.GetAxisRaw("Horizontal");
float vertical = Input.GetAxisRaw("Vertical");
MoveInput = new Vector2(horizontal, vertical);
if (MoveInput.sqrMagnitude > 1f)
MoveInput = MoveInput.normalized;
}
}
HorizontalとVerticalは旧Input Managerに用意されている標準的な入力軸名です。GetAxisRawは入力方向を-1、0、1などの値として取得します。Vector2はX・Yの2次元値を表し、ここでは横方向と前後方向をまとめています。斜め入力ではベクトルの長さが1を超えるため、normalizedで長さを1にそろえ、斜めだけ移動が速くなることを防いでいます。
Rigidbodyで移動する
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class RigidbodyMover : MonoBehaviour
{
[SerializeField] private float moveSpeed = 4f;
private Rigidbody rb;
private Vector3 moveDirection;
void Awake()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
float horizontal = Input.GetAxisRaw("Horizontal");
float vertical = Input.GetAxisRaw("Vertical");
moveDirection = new Vector3(horizontal, 0f, vertical);
if (moveDirection.sqrMagnitude > 1f)
moveDirection.Normalize();
}
void FixedUpdate()
{
Vector3 nextPosition = rb.position + moveDirection * moveSpeed * Time.fixedDeltaTime;
rb.MovePosition(nextPosition);
}
}
AwakeでRigidbodyを取得し、Updateで入力を読み取ります。FixedUpdateでは入力方向、移動速度、Time.fixedDeltaTimeから次の位置を計算し、MovePositionでRigidbodyを移動します。RequireComponentは必要なRigidbodyが同じGameObjectに追加されるようにする属性です。
Time.deltaTimeは通常のフレーム更新で使い、Time.fixedDeltaTimeは物理更新の時間幅を表します。RigidbodyをFixedUpdateで動かすこの例ではfixedDeltaTimeを使います。
ColliderとRigidbody
- Collider:物体の当たり判定の形状を定義します。
- Rigidbody:物理演算による移動や力の影響を受けるためのComponentです。
3D用のCollider/Rigidbodyと2D用のCollider2D/Rigidbody2Dは別の物理システムです。同じイベントとして混在させないでください。RigidbodyのUse Gravityを無効にすると重力による落下を止められます。回転を固定したい場合はConstraintsを設定します。
衝突イベントとTrigger
OnCollisionEnterは物理的な衝突が始まったとき、OnTriggerEnterはTrigger領域に入ったときに呼ばれます。TriggerではColliderのIs Triggerを有効にします。
using UnityEngine;
public class ItemDetector : MonoBehaviour
{
void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Item"))
{
Debug.Log("Item detected");
}
}
}
このスクリプトをPlayerなどのGameObjectに追加し、接触相手のTagがItemならログを出します。3DのTriggerイベントを受け取るには、関係するColliderの少なくとも一方にRigidbodyが必要です。タグはInspectorで対象オブジェクトに設定します。
動作しないときの確認
- Input Managerが有効か、軸名が正しいか。
- スクリプトが有効なGameObjectに追加されているか。
- RigidbodyとColliderが3D同士、または2D同士で組み合わされているか。
- Triggerを使う場合、Is TriggerとRigidbodyの条件を満たしているか。
- PhysicsのLayer Collision Matrixで対象レイヤー同士の衝突が無効になっていないか。
- Inspectorで必要な参照やTagが正しく設定されているか。
この章の要点
入力はUpdateで取得し、Rigidbodyの移動はFixedUpdateで行う構成が基本です。Colliderは接触形状、Rigidbodyは物理挙動、Triggerは物理的に押し返さず領域への出入りを検知する仕組みです。