スポンサーリンク
Unity入門・基礎

【Unity】オブジェクト移動の作り方まとめ|座標移動・クリック移動・ランダム移動を解説

Unity入門・基礎

Unityでゲームを作り始めると、かなり早い段階で「オブジェクトを動かしたい」という場面に出会います。

プレイヤーを移動させたり、敵キャラクターを追いかけさせたり、クリックした場所へ移動させたりと、移動処理はほとんどのゲームで使われる重要な仕組みです。

ところがUnityには、オブジェクトを移動する方法が複数あります。

transform.positionRigidbody.MovePositionVector3.MoveTowardsなど、似たような名前の機能が並んでいるため、「結局どれを使えばいいの?」と迷ってしまう方も多いのではないでしょうか。

私もUnityを学び始めた頃は、すべて同じような機能だと思っていました。しかし実際には、それぞれ得意な用途が異なります。

例えば、瞬間的にワープさせたい場合と、物理演算を使って自然に移動させたい場合では、選ぶべき方法が変わります。

ここを理解しておくと、後からスクリプトを書き直す手間を減らしやすくなります。

オブジェクト移動の基本を整理しながら、目的地への移動、クリック移動、ランダム移動まで順番に見ていきましょう。


Unityの移動方法は4種類を覚えれば十分

Unityにはさまざまな移動方法がありますが、初心者のうちは次の4種類を理解しておけば、多くのゲームで対応できます。

移動方法主な用途特徴
transform.position座標変更・ワープ位置を直接変更する
Rigidbody.MovePosition物理移動Rigidbodyと連携して移動する
Vector3.MoveTowards目的地への移動一定速度で目標へ近づく
Raycast + 座標取得クリック移動クリック地点を取得して移動する

transform.positionとMovePositionの違い

初心者が最も迷いやすいのが、transform.positionMovePositionの違いです。

どちらもオブジェクトを移動できますが、内部の仕組みが異なります。

transform.positionは位置を直接書き換えます。そのため処理がシンプルで扱いやすく、ワープやUI移動などに向いています。

一方でRigidbody.MovePositionは物理演算システムと連携して移動します。

Rigidbodyを使用しているオブジェクトの場合、positionを直接変更すると物理挙動が不自然になることがあります。

プレイヤーや敵キャラクターなど、物理演算を利用するオブジェクトではMovePositionを選ぶ場面が多くなります。

どれを選べばよいか判断基準

迷ったら次の基準で考えると選びやすくなります。

  • 瞬間移動したい → transform.position
  • Rigidbodyを使った移動 → MovePosition
  • 目標地点へ移動したい → MoveTowards
  • クリックした場所へ移動したい → Raycast
  • NPCを徘徊させたい → Random + MoveTowards

ゲーム開発では「移動する」という結果は同じでも、実現方法は状況によって変わります。

まずは「どんな移動を作りたいのか」を考えてから手法を選ぶクセを付けると、スクリプト設計がかなり楽になります。




transform.positionで座標移動する方法

Unityで最もシンプルな移動方法がtransform.positionです。

オブジェクトの位置情報を書き換えるだけなので理解しやすく、Unityを学び始めたばかりの方が最初に触れる移動方法でもあります。

transform.positionの基本構文

位置を変更するには、transform.positionへ新しい座標を代入します。

transform.position = new Vector3(5f, 0f, 0f);

このコードを実行すると、オブジェクトはX座標が5の位置へ瞬時に移動します。

Vector3は3D空間の座標を表す型で、X・Y・Zの3つの値を持っています。

  • X:左右方向
  • Y:上下方向
  • Z:前後方向

実際にCubeを移動してみよう

例えばゲーム開始時にCubeを移動するなら、次のように記述できます。

using UnityEngine;

public class MoveCube : MonoBehaviour
{
    void Start()
    {
        transform.position = new Vector3(3f, 1f, 0f);
    }
}

実行すると、Cubeはシーン開始と同時に指定した座標へ移動します。

非常にシンプルなので、「まずは座標を変更する感覚を覚えたい」という段階にぴったりです。

transform.positionが向いている場面

特に次のようなケースで使いやすい方法です。

  • ワープポイントによる瞬間移動
  • チェックポイント復帰
  • UIオブジェクトの位置変更
  • シーン開始時の初期配置

「今いる場所から移動する」というより、「この座標へ配置する」というイメージに近い処理です。

transform.positionを多用すると起きる問題

便利な方法ですが、すべての移動処理をpositionで行うのはおすすめできません。

特にRigidbodyが付いているオブジェクトでは注意が必要です。

例えばプレイヤーキャラクターにRigidbodyを付けている状態で毎フレームpositionを書き換えると、物理演算との整合性が崩れることがあります。

その結果として次のような問題が発生する場合があります。

  • 壁をすり抜ける
  • 当たり判定が不安定になる
  • 移動がカクつく
  • 物理挙動が不自然になる

私も初心者の頃は「移動できるなら全部positionでいいのでは?」と思っていましたが、プレイヤーや敵キャラクターを作り始めると限界が見えてきました。

物理演算を利用するオブジェクトでは、次に紹介するRigidbody.MovePositionを選んだほうが自然な動作になるケースが多くあります。




MovePositionで滑らかに移動する方法

Rigidbodyを使っているオブジェクトを移動するなら、Rigidbody.MovePositionが有力な選択肢になります。

プレイヤーキャラクターや敵キャラクターなど、物理演算と連携しながら移動させたい場合によく使われます。

特に「positionを書き換えたら挙動がおかしくなった」という経験がある方は、MovePositionを覚えておくと役立ちます。

Rigidbody.MovePositionとは

MovePositionは、Rigidbodyの移動を物理演算システムに伝えながら位置を更新する機能です。

見た目はposition変更と似ていますが、内部的には物理演算を考慮して処理されます。

そのため、Rigidbodyを利用しているオブジェクトでは自然な移動になりやすい特徴があります。

プレイヤーを操作するゲームや、物理判定を利用するゲームでは頻繁に登場する移動方法です。

MovePositionの実装手順

まずは移動対象のオブジェクトにRigidbodyを追加します。

次にスクリプトでRigidbodyを取得し、MovePositionを使用します。

using UnityEngine;

public class MovePositionExample : MonoBehaviour
{
    private Rigidbody rb;

    [SerializeField]
    private float speed = 5f;

    private void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    private void FixedUpdate()
    {
        Vector3 move = transform.forward * speed * Time.fixedDeltaTime;

        rb.MovePosition(rb.position + move);
    }
}

ここで重要なのは、Update()ではなくFixedUpdate()を使用していることです。

FixedUpdateは物理演算用の更新タイミングで実行されるため、MovePositionとの相性が良くなります。

MovePositionが向いている場面

次のようなケースではMovePositionを検討する価値があります。

  • Rigidbodyを使ったプレイヤー移動
  • 敵キャラクターの追従移動
  • 押し出しや衝突判定を伴う移動
  • 物理演算を利用するアクションゲーム

逆に、ワープや単純な座標変更だけならpositionの方がシンプルです。

大切なのは「Rigidbodyを使っているかどうか」を判断基準の一つにすることです。

transform.positionとMovePositionの使い分け

比較項目transform.positionMovePosition
用途座標変更物理移動
Rigidbodyとの相性あまり良くない良い
実装の手軽さ非常に簡単少し準備が必要
推奨更新処理UpdateFixedUpdate

迷った場合は、「Rigidbodyが付いているならMovePosition、それ以外ならposition」という考え方から始めると理解しやすいでしょう。

Rigidbodyについてまだ理解があいまいな場合は、先に基礎を押さえておくと移動処理の理解が深まります。




MoveTowardsで目的地へ移動する方法

「指定した場所までゆっくり移動したい」「敵キャラクターをプレイヤーへ近づけたい」という場合は、Vector3.MoveTowardsが便利です。

transform.positionが瞬間移動だったのに対し、MoveTowardsは一定速度で目標地点へ近づいていきます。

ゲームでよく見かける移動処理の多くは、この考え方を応用しています。

MoveTowardsとは

MoveTowardsは、現在位置から目標位置へ向かって少しずつ移動するためのメソッドです。

基本構文は次のようになります。

transform.position = Vector3.MoveTowards(
    transform.position,
    target.position,
    speed * Time.deltaTime
);

第1引数が現在位置、第2引数が目標位置、第3引数が移動量です。

目標に到達すると自動的に停止するため、初心者でも扱いやすい移動方法です。

ターゲットへ移動するサンプル

例えばCubeをSphereへ向かって移動させる場合は、次のように実装できます。

using UnityEngine;

public class MoveToTarget : MonoBehaviour
{
    [SerializeField]
    private Transform target;

    [SerializeField]
    private float speed = 3f;

    private void Update()
    {
        transform.position = Vector3.MoveTowards(
            transform.position,
            target.position,
            speed * Time.deltaTime
        );
    }
}

インスペクターからSphereを設定すると、Cubeが自動的に近づいていきます。

敵がプレイヤーを追いかける処理や、アイテムがプレイヤーへ吸い寄せられる処理などでもよく利用されます。

Time.deltaTimeが必要な理由

MoveTowardsを使うときに忘れてはいけないのがTime.deltaTimeです。

これは「前回フレームから経過した時間」を表しています。

例えば次のコードの場合を考えてみましょう。

transform.position = Vector3.MoveTowards(
    transform.position,
    target.position,
    speed
);

この書き方だと、1フレームごとにspeed分だけ移動します。

その結果、60FPSのPCと120FPSのPCで移動速度が変わってしまいます。

ゲームによっては「高性能なPCほど移動速度が速い」という不自然な状態になることもあります。

Time.deltaTimeを掛けることで、フレームレートに依存しない一定速度の移動になります。

移動処理を書くときは、まず「deltaTimeを掛け忘れていないか」を確認するクセを付けると失敗を減らせます。

MoveTowardsが向いているゲーム

MoveTowardsは次のような場面で活躍します。

  • 敵キャラクターの追尾AI
  • NPCの移動
  • アイテムの吸い寄せ演出
  • タワーディフェンスの敵移動
  • 目的地への自動移動

一方で、カーブを描く移動や複雑なアニメーションを作りたい場合は、補間ライブラリを利用する方法もあります。

移動演出をさらに手軽に作りたい場合は、DOTween Proのような定番アセットも選択肢になります。

DOTween Pro
✅アセットストアでチェックする




Unityでクリックした場所へ移動する方法

RTSやシミュレーションゲームでは、「クリックした場所へキャラクターを移動させる」という操作がよく使われます。

Unityでは、マウスでクリックした画面上の位置を3D空間の座標へ変換することで実現できます。

一見難しそうに見えますが、仕組みを分解するとそれほど複雑ではありません。

クリック移動の仕組み

まず理解しておきたいのが、マウスが取得できるのは画面上の座標だということです。

例えば、マウスカーソルの位置は「画面の何ピクセル目にあるか」という情報で管理されています。

しかし、オブジェクトを移動させるためには3D空間上の座標が必要です。

そこでUnityでは、カメラから見たクリック位置に向かってRay(見えない光線)を飛ばし、その当たり判定から座標を取得します。

この変換処理に使われるのがRaycastです。

Raycastでクリック地点を取得する

クリック位置を取得する流れは次のようになります。

  1. マウスクリックを検知する
  2. クリック位置へRayを飛ばす
  3. Rayが当たった座標を取得する
  4. その座標へオブジェクトを移動する

特に重要なのが次の2つです。

  • Camera.main.ScreenPointToRay()
  • Physics.Raycast()

ScreenPointToRayが画面座標からRayを作成し、Physics.Raycastが実際の当たり判定を行います。

クリック移動のサンプルコード

Planeをクリックした位置へCubeを移動させる例です。

using UnityEngine;

public class ClickMove : MonoBehaviour
{
    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(
                Input.mousePosition
            );

            if (Physics.Raycast(ray, out RaycastHit hit))
            {
                transform.position = hit.point;
            }
        }
    }
}

このスクリプトをCubeへアタッチし、シーン内にCollider付きのPlaneを配置すると、クリックした場所へ瞬時に移動します。

移動先へ滑らかに向かわせたい場合は、取得したhit.pointを目的地として保存し、MoveTowardsで移動させる方法もよく使われます。

クリック移動でよくある失敗

クリック移動が動かない場合、多くは次のどれかが原因です。

  • クリック対象にColliderが付いていない
  • Raycastが対象へ届いていない
  • Camera.mainが取得できていない
  • 別のオブジェクトがRayを遮っている

特に初心者の方は「Planeは置いたのに反応しない」というケースによく遭遇します。

その場合は、まずPlaneにColliderが付いているか確認してみてください。

また、クリック判定がうまく取得できない場合は、次の記事も参考になります。




Unityでランダム移動を作る方法

敵キャラクターや動物、NPCなどを「その場でうろうろ動かしたい」ときに便利なのがランダム移動です。

ただし、初心者の方がよく勘違いするのですが、Random.Range()だけでは移動処理は完成しません。

ランダムな目的地を決めて、その目的地まで移動する処理を組み合わせる必要があります。

Random.Rangeで目的地を決める

まずは移動先となる座標をランダムに生成します。

例えば、X座標とZ座標を-5〜5の範囲でランダムに決める場合は次のようになります。

float randomX = Random.Range(-5f, 5f);
float randomZ = Random.Range(-5f, 5f);

Vector3 targetPosition = new Vector3(
    randomX,
    transform.position.y,
    randomZ
);

これで移動先の候補は作れますが、この段階ではまだオブジェクトは動きません。

あくまで「次に向かう場所を決めた」だけの状態です。

MoveTowardsと組み合わせて徘徊を作る

ランダム移動では、先ほど学んだMoveTowardsとの組み合わせがよく使われます。

transform.position = Vector3.MoveTowards(
    transform.position,
    targetPosition,
    speed * Time.deltaTime
);

こうすることで、ランダムに決まった目的地へ一定速度で移動できます。

実際のゲームでも「ランダム座標を決める処理」と「目的地へ移動する処理」を分けて考えることが多いです。

一定時間ごとに移動先を変更する

ランダム移動らしく見せるには、一定時間ごとに新しい目的地を設定します。

例えば5秒ごとに移動先を変更するなら次のような実装になります。

using UnityEngine;

public class RandomMove : MonoBehaviour
{
    [SerializeField]
    private float moveRange = 5f;

    [SerializeField]
    private float speed = 2f;

    [SerializeField]
    private float changeInterval = 5f;

    private float timer;
    private Vector3 targetPosition;

    private void Start()
    {
        SetNewTarget();
    }

    private void Update()
    {
        timer += Time.deltaTime;

        if (timer >= changeInterval)
        {
            timer = 0f;
            SetNewTarget();
        }

        transform.position = Vector3.MoveTowards(
            transform.position,
            targetPosition,
            speed * Time.deltaTime
        );
    }

    private void SetNewTarget()
    {
        targetPosition = new Vector3(
            Random.Range(-moveRange, moveRange),
            transform.position.y,
            Random.Range(-moveRange, moveRange)
        );
    }
}

このような仕組みを使うと、NPCが周囲を巡回しているような自然な動きを作れます。

ランダム移動が向いているゲーム

ランダム移動は次のようなゲームでよく利用されます。

  • 村人や住民NPCの徘徊
  • 動物の行動パターン
  • 警備ロボットの巡回
  • カジュアルゲームの敵キャラクター

ただし、決められたルートを移動する敵や、障害物を避けながら移動するAIには向いていません。

そのような場合はNavMeshAgentなどの経路探索機能を使うことが一般的です。

まずは「ランダムな目的地を決める」と「そこへ移動する」を分けて考えると、移動処理の仕組みが理解しやすくなります。




Unityの移動処理で初心者がよく間違えるポイント

移動処理は一見シンプルですが、初心者がつまずきやすいポイントがいくつかあります。

実際に「コードは書いたのに思った通りに動かない」という相談の多くは、ここで紹介する内容が原因になっています。

UpdateとFixedUpdateを混同する

Unityには複数の更新タイミングがあります。

特に混同しやすいのがUpdate()FixedUpdate()です。

  • Update → 毎フレーム実行
  • FixedUpdate → 物理演算用の一定間隔実行

例えばMoveTowardsのような通常移動ならUpdateが適しています。

一方でMovePositionやAddForceなど、Rigidbodyを使う処理はFixedUpdateで実行するのが一般的です。

更新タイミングを間違えると、移動がカクついたり物理挙動が不安定になったりする場合があります。

Rigidbodyがあるのにpositionを書き換える

初心者によくある失敗の一つです。

Rigidbodyを使っているにもかかわらず、毎フレームtransform.positionを書き換えてしまうケースがあります。

すると物理演算と座標変更が競合し、不自然な挙動になることがあります。

例えば次のような現象が発生する場合があります。

  • 壁をすり抜ける
  • 衝突判定が不安定になる
  • 移動がガタつく
  • 予期しない跳ね返りが発生する

Rigidbodyを利用する場合は、MovePositionやAddForceなどの物理向けAPIを優先的に検討しましょう。

Time.deltaTimeを掛け忘れる

移動速度がおかしくなる原因として非常に多いのが、Time.deltaTimeの掛け忘れです。

例えば次のコードを見てみましょう。

transform.position += Vector3.forward * speed;

この場合、1フレームごとにspeed分だけ移動します。

そのため、高FPS環境ほど移動速度が速くなります。

多くの移動処理では次のように記述します。

transform.position +=
    Vector3.forward *
    speed *
    Time.deltaTime;

フレームレートの違いによる影響を減らせるため、安定した速度で移動できるようになります。

MoveTowardsは瞬間移動ではない

MoveTowardsを使うと、指定した地点へ一瞬で移動すると思っている方もいます。

しかし実際には、指定した速度で徐々に近づいていく処理です。

もし瞬間移動させたいなら、MoveTowardsではなくpositionの直接代入を使用します。

「目的地へ向かう」のか、「目的地へ配置する」のかを区別すると選びやすくなります。

Random.Rangeだけでは移動しない

ランダム移動を作る際に最も多い勘違いがこれです。

Random.Rangeはランダムな数値を生成する機能であり、移動機能ではありません。

例えば次のコードを書いても、オブジェクトは動きません。

float x = Random.Range(-5f, 5f);

生成した座標を目的地として保存し、MoveTowardsやMovePositionなどで実際に移動させる必要があります。

「座標を決める処理」と「移動する処理」は別物だと考えると理解しやすいでしょう。


まとめ

Unityのオブジェクト移動にはさまざまな方法がありますが、最初は次の4つを理解しておけば十分です。

  • transform.positionで座標を直接変更する
  • MovePositionで物理演算を考慮して移動する
  • MoveTowardsで目的地へ移動する
  • Raycastを使ってクリック地点へ移動する

また、ランダム移動を作る場合は、Random.Rangeで目的地を決めてからMoveTowardsなどで移動するという考え方が重要になります。

移動処理を学び始めた頃は「とりあえず動けばOK」と考えがちですが、実際のゲーム開発では用途に応じて移動方法を使い分けることが大切です。

私自身も最初はすべてtransform.positionで実装していました。しかしプレイヤー操作や敵AIを作るようになると、MovePositionやMoveTowardsの役割がはっきり見えてきました。

特に初心者の方は、まず次の順番で覚えると理解しやすいと思います。

  1. transform.position
  2. MoveTowards
  3. MovePosition

この3つを理解できると、Unityで作るゲームの移動処理の多くに対応できるようになります。

さらに本格的なキャラクター移動を実装したい場合は、専用アセットを活用する方法もあります。

Character Controller Pro
✅アセットストアでチェックする

Easy Character Movement 2
✅アセットストアでチェックする

また、Unity全体の基礎を体系的に学びたい方には書籍も役立ちます。

Unityの教科書 Unity 6完全対応版
✅ Amazonでチェックする✅ 楽天でチェックする


よくある質問(FAQ)

Q
MovePositionとAddForceはどちらを使うべき?
A

目的によって使い分けます。

MovePositionは「決まった場所へ正確に移動したい」場合に向いています。

例えばプレイヤーの移動や敵キャラクターの追従など、移動量を自分で制御したいケースです。

一方のAddForceは、力を加えて移動させる物理ベースの方法です。

ジャンプ、爆発による吹き飛び、ボールの転がりなど、物理挙動を活かしたい場合に使用します。

迷った場合は、キャラクター制御ならMovePosition、物理演算を活かした演出ならAddForceと考えると選びやすいでしょう。

Q
RigidbodyがなくてもMoveTowardsは使える?
A

使えます。

MoveTowardsはVector3同士の座標計算を行うメソッドなので、Rigidbodyは必須ではありません。

実際にNPCの移動やUI要素の移動など、Rigidbodyを使わずにMoveTowardsだけで実装するケースも多くあります。

ただし、物理演算を利用しているオブジェクトの場合は、MoveTowardsで算出した座標をMovePositionへ渡す構成の方が適している場合があります。

「物理演算が必要かどうか」を判断基準にすると迷いにくくなります。

Q
2Dゲームでも同じ考え方で使える?
A

基本的な考え方は同じです。

2DゲームではVector3の代わりにVector2を使用する場面が増えますが、座標移動・目的地移動・ランダム移動という考え方は変わりません。

また、物理演算を利用する場合はRigidbodyではなくRigidbody2Dを使用します。

例えば次のように対応関係があります。

  • transform.position → 2Dでも使用可能
  • Rigidbody → Rigidbody2D
  • Vector3 → Vector2
  • Physics.Raycast → Physics2D.Raycast

3Dで移動処理の考え方を理解できれば、2Dゲーム開発にも応用しやすくなります。

※当サイトはアフィリエイト広告を利用しています。リンクを経由して商品を購入された場合、当サイトに報酬が発生することがあります。

※本記事に記載しているAmazon商品情報(価格、在庫状況、割引、配送条件など)は、執筆時点のAmazon.co.jp上の情報に基づいています。
最新の価格・在庫・配送条件などの詳細は、Amazonの商品ページをご確認ください。

スポンサーリンク