← Unity C#

LESSON / ARTICLE

入力と物理演算

Unityの入力取得、Rigidbody、Collider、衝突イベントとTriggerの仕組みを学びます。

入力と物理演算

プレイヤーを操作するには入力を読み取り、その値をオブジェクトの動きへ反映します。物理演算を使う場合は、入力を読むタイミングと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は物理的に押し返さず領域への出入りを検知する仕組みです。