[Unity] #01:CubeとPlaneで始める最短入門(Three.js経験者向け)

はじめに

一か月間、Three.jsで開発を続けて、ちょっと煮詰まってきたので(まだやる事は無限にありますが)何となく、

「Three.js開発経験者が、Unityを使うとどうなるのか?」

ゲームエンジンを使う方が楽という意見が多く以前から興味があったので、1か月の節目を境に試してみました。

結果はというと、AIのサポートもありましたが、plaingeometry?の床を置いて、キューブジオメトリーを設置して、[W][A][S][D]キーで動かし、カメラを動かすところまで爆速で出来ました。

ここまでの内容を、記事にまとめてみます。

1. プロジェクト作成

Unity Hub を開いて新規プロジェクトを作る。今回は Unity 6(2025 / 2026 時点の最新 LTS)+ URP(Universal Render Pipeline) を選んだ。理由は単純で、見た目が綺麗で軽いから。

Three.js のように ライティングや影の設定を自分で書かなくても 最初から揃っている。

VSCode を外部エディタにする

Unity は内部にエディタを持っていないので、スクリプトを編集するために外部エディタを使う。 今回は VSCode を使用した。軽いし、既に慣れている。

Unity 側での設定 Edit → Preferences → External Tools → VSCode を選択

これで、スクリプトをダブルクリックすると VSCode が開く。


Unity の GUI(最初は意味不明だけど覚えると強い)

Three.js の場合はコードで全部管理するが、Unity は GUI を中心に進む。 最初は意味不明に見えるが、用途は明確に分かれている。

Unity Editor は大きく6つのパネルで構成されている:

Hierarchy(階層)

シーン内に存在するオブジェクトの一覧。 Three.js で言うところの Scene.children

Scene View(シーンビュー)

開発者用の自由視点カメラ。 右クリック+WASD で自由に動ける。 Three.js の OrbitControls より圧倒的に扱いやすい。

Game View(ゲームビュー)

実際にプレイした時の「プレイヤーの視点」。 Main Camera の映像がここに映る。

Inspector(インスペクタ)

選択したオブジェクトの詳細設定。 Three.js の「material の中身」や「geometry のプロパティ」を 全部 GUI で編集できる感じ。

Project(プロジェクト)

アセットの置き場。 スクリプト、画像、Prefab、シーンなど全部ここに入る。 Three.js でいう「src」「public」「assets」フォルダ。

Console(コンソール)

エラー・警告・ログ。 JavaScript の console.log と同じ。 Unity が勝手に一時停止する原因の9割はここにエラーが出てる時。


ここまでで、Unity の世界を歩くための最低限の地図ができる。

Three.js の経験があるおかげで

  • Scene(空間)
  • Camera(視点)
  • Mesh(見た目)
  • Inspector=プロパティ編集 が直感で結びつくと思う。

続いて Cube と Plane を作って、物理と移動を加えていく。

2. Cube 生成 & Plane(床)生成

まずはシーンに最低限のオブジェクトを置く。 Three.js で言えば BoxGeometry と PlaneGeometry を置くところ

Cube を作る

Hierarchy 上で右クリックして、

Create → 3D Object → Cube

これで白い立方体がシーン中央に出現する。 以降、この Cube をプレイヤー役として使う。

位置はそのままで問題ないが、 後で落下するので Y を少し上げておくと分かりやすい。

Position Y = 1

Plane を作って床にする

同じ手順で Plane を作る。

Create → 3D Object → Plane

Plane はそのままだと小さいので、床として使うには拡大する。

Inspector の Transform で Scale を変更する。

Scale X = 5
Scale Z = 5

これで Cube が乗れる床になる。

ハマりポイント②:Cube が落下して消える

この段階で Play を押すと、 Cube が そのまま下に落ちて視界から消えることがある。

理由は単純で、

  • Cube は物理的に「落ちる存在」
  • 床が無い or 当たり判定が無い

から。

Unity の Plane には 最初から Collider が付いているので、 床として使う場合は Plane 自体は問題ない。

ただし次の章で Rigidbody を付けた瞬間に、 この「落下問題」を必ず踏むことになる。


この時点では、

  • Cube は「見た目だけのオブジェクト」
  • Plane は「ただの床」

まだ物理は有効になっていない。

次は Cube に Rigidbody を追加して、 Unity の物理世界に突入する。

3. Rigidbody をつける(物理 ON)

Three.js にも「物理エンジン(cannon.js など)」があるが、 Unity では物理は 標準搭載。 Rigidbody を付けただけで重力・質量・加速度・摩擦が即有効になる。

Cube に Rigidbody を追加する手順

  1. Hierarchy で Cube を選択
  2. Inspector の下部にある Add Component をクリック
  3. Rigidbody と入力して追加

これで Cube は 物理オブジェクトになる。

  • 重力で落ちる
  • AddForce で力を加えられる
  • 他の Collider と衝突する

Unity が全部やってくれる。


Rigidbody のデフォルト設定

追加直後の設定はこうなっている:

Use Gravity : ON
Is Kinematic : OFF
Mass : 1
Drag : 0
Angular Drag : 0.05

特に触らなくていい。


ハマりポイント①:Play(再生)中に追加すると無効

Unity の “青い再生ボタン” が押されている状態は 仮想世界 になっている。

再生中に

  • コンポーネントの追加
  • パラメータの変更 を行っても、停止した瞬間に全て消える

これは Unity の強烈な罠で、 初心者は 100% 一度は痛い目を見る。

Rigidbody の追加は必ず停止中に行う。


ハマりポイント②:Rigidbody なしで AddForce を呼ぶとエラー

後で Cube を WASD で動かすときに AddForce() を使うが、Rigidbody が無いと Unity が怒る。

典型的なエラー:

MissingComponentException: There is no 'Rigidbody' attached to the "Cube"

Rigidbody がない状態で物理命令を出すと、 Unity は「設定ミス」と判断してゲームを停止する。 (Console の Error Pause が ON だと強制 Pause になる)


Rigidbody を付けた時点で Cube は “世界に属する物体” になる。

次は Cube を WASD で動かせるようにスクリプトを追加していく。

4. Cube を WASD で動かすスクリプト

Rigidbody を付けた Cube は、もう「物理世界の住人」なので 次は入力を与えて動かす。

Three.js でいうと keydown を拾って position を更新するのと同じ役割。


MoveCube.cs を作成する

Project ビューで:

Assets → 右クリック → Create → C# Script

名前を MoveCube にする。

作成したスクリプトをダブルクリックして VSCode で開き、 中身を以下に置き換える。

using UnityEngine;

public class MoveCube : MonoBehaviour
{
    Rigidbody rb;

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

    void Update()
    {
        float x = Input.GetAxis("Horizontal");
        float z = Input.GetAxis("Vertical");

        rb.AddForce(new Vector3(x, 0, z) * 10f);
    }
}

保存したら、この MoveCube スクリプトを Cube の Inspector にドラッグ&ドロップする。


このコードでやっていること

  • Input.GetAxis("Horizontal") → A / D または ← / →
  • Input.GetAxis("Vertical") → W / S または ↑ / ↓

Unity が内部でキー入力を −1〜1 に正規化してくれる。

AddForce を使っているので、 直接座標を書き換えず 力として動かしている

Three.js で言えば 「position を直接いじる」より 「物理エンジンに任せる」書き方。


ハマりポイント:Input System のエラー

Play を押すと、以下のエラーが出ることがある。

You are trying to read Input using the UnityEngine.Input class,
but you switched to Input System (New)

Unity 6 では 新しい Input System がデフォルト有効になっている。 しかしこのコードは 旧 Input(Input.GetAxis) を使っている。

そのため、設定を変更する必要がある。


解決方法

Edit → Project Settings → Player

右側の設定を下にスクロールして、

Active Input Handling

Both に変更する。

  • Input System (New)
  • Input Manager (Old)
  • Both ← これ

変更後、Unity の再起動を求められる。


ここが地味にしんどいポイント

この設定、 1回で反映されないことがある

  • 再起動しても戻っている
  • Play するとまたエラー
  • もう一度設定 → 再起動

というのを 2〜3回繰り返してやっと反映された。

Unity に「本当にやるの?」と試されている感じが強い。

ただ、一度通ると以降は安定する。


ここまでできれば、

  • Cube に Rigidbody があり
  • WASD 入力が入り
  • 力として動く

状態になる。

次は床(Plane)を揺らしたり、 カメラを動かして「見る側」を制御していく。

5. Plane を揺らす(Mesh を動的変形)

Three.js を触っていると、 「Plane の頂点を動かして波や地形を作る」 という発想は自然に出てくる。

Unity でも同じことができるが、 共有メッシュの扱いで必ず一度ハマる。


DeformPlane.cs を作成する

Project ビューで:

Assets → 右クリック → Create → C# Script

名前を DeformPlane にする。

作成したスクリプトを開き、 以下のコードに置き換える。

using UnityEngine;

public class DeformPlane : MonoBehaviour
{
    Mesh mesh;
    Vector3[] vertices;

    void Start()
    {
        MeshFilter mf = GetComponent<MeshFilter>();
        mesh = Instantiate(mf.sharedMesh); // 共有メッシュを複製
        mf.mesh = mesh;

        vertices = mesh.vertices;
    }

    void Update()
    {
        for (int i = 0; i < vertices.Length; i++)
        {
            vertices[i].y =
                Mathf.Sin(Time.time * 2f + vertices[i].x * 2f) * 2f;
        }

        mesh.vertices = vertices;
        mesh.RecalculateNormals();
    }
}

スクリプトを Plane に追加する

ここがかなり重要。

  • Hierarchy の Plane を選択
  • Inspector → Add Component
  • DeformPlane を追加

Project ビュー(アセット側)の Plane に付けても 何も起きない


ハマりポイント①:共有メッシュを書き換えていた

Unity の標準 Plane は 全オブジェクトでメッシュを共有している。

そのまま頂点を書き換えると、

  • 変化しない
  • 変わったように見えない
  • 最適化で無視される

という状態になる。

対策はこれ:

mesh = Instantiate(mf.sharedMesh);
mf.mesh = mesh;

Three.js でいう geometry.clone() を忘れた状態と同じ。


ハマりポイント②:Inspector に追加していなかった

スクリプトを書いただけでは動かない。

必ず Plane の Inspector に Add Component する必要がある

これを忘れると、

  • エラーなし
  • 見た目も変わらない
  • 原因が分からない

という、地味に一番しんどい状態になる。


補足:なぜ Cube は揺れないのか

Plane の 見た目(Mesh)だけ を変形しているため、 当たり判定(Collider)は変わっていない。

そのため Cube は「揺れていない床」の上に立っている。

これは Unity の仕様で、 ゲームではこの方法がむしろ一般的。


Plane がウネウネ動けば成功。

次はカメラを動かして、 この世界を自由に観察できるようにする。

6. カメラを動かす

オブジェクトを動かせるようになると、 次に必ず出てくるのが 「視点が固定で見づらい」問題

Unity では カメラもただの GameObject なので、 スクリプトを付ければ普通に動かせる。


CameraMove.cs を作成する

Project ビューで:

Assets → 右クリック → Create → C# Script

名前を CameraMove にする。

中身を以下に置き換える。

using UnityEngine;

public class CameraMove : MonoBehaviour
{
    void Update()
    {
        float x = Input.GetAxis("Horizontal");
        float y = Input.GetAxis("Vertical");

        transform.Translate(new Vector3(x, 0, y) * Time.deltaTime * 10f);
    }
}

スクリプトを Main Camera に追加する

ここも忘れやすい。

  • Hierarchy で Main Camera を選択
  • Inspector → Add Component
  • CameraMove を追加

これで WASD 操作に応じて カメラが前後左右に移動する。


この挙動について

このカメラは、

  • Cube を追いかけるわけではない
  • 自由に空中をスライドするだけ

Three.js で言うと、 位置だけ動くシンプルなカメラ

まずは 「カメラもスクリプトで動かせる」 という感覚を掴むのが目的。


ハマりポイント①:Scene View と Game View の違い

Unity には視点が2つある。

  • Scene View → 開発者用の自由視点
  • Game View → プレイヤーが見る画面(Main Camera)

Game View が見づらい時、 Scene View を動かしても ゲーム画面は変わらない

動かすべきなのは Main Camera 自体


ハマりポイント②:スクリプトを付け忘れる

スクリプトを書いただけでは何も起きない。

  • 作成した
  • 保存した
  • でも Inspector に追加していない

この状態だと、

  • エラーなし
  • 入力も正常
  • でもカメラは動かない

Unity では Add Component されて初めて世界に参加する


ハマりポイント③:マウスで視点操作したくなる

ここまで来ると、

  • 右クリックで視点回転したい
  • マウスで見回したい

という欲求が出る。

ただし今回は WASD 移動だけ に留めている。

理由は単純で、 カメラ制御は一気に複雑になるから。

追従カメラやマウス操作は 次の段階でまとめてやった方が理解しやすい。


これで、

  • Cube を作る
  • 床を作る
  • 物理を有効にする
  • WASD で動かす
  • 地形を揺らす
  • 視点を動かす

という Unity の基礎動線を一通り踏めた。

次に進むなら、

  • カメラ追従
  • 物理マテリアル
  • Terrain
  • Prefab

このあたりが自然な流れになる。

おわりに

Unityのインストールや設定から始めたとはいえ、物凄い速度で、というのも書いたコード量が少ないのでほとんど何もしてないに等しいです。

Three.jsだと、sceneを作って、cameraを作って、renderer、アニメーションループ、キューブジオメトリーの作成と配置、キー入力イベント作成、その他。

1つ1つすべてコードを書く必要があるので非常に手間がかかりますが、その辺りをUnityが全部バックで処理してくれるのでほぼ何もせず、僅かなコードを書くだけで動くようになります。

ただ、Unityの場合は、開発環境の使い方を覚える必要があるので、その学習コストで時間をとられるので、トータル時間は同じになるかもしれません。

今回は、GUI操作の不明点をAIに聞いて補助してもらったので早かったですが、ネットでマニュアルや参考サイトを見ながらだとこんなに早くはできなかったと思います。

それでも、今回、始めて動かしてみて開発の仕方は少しわかるようになりました。

今後の目標としては、Three.jsで製作した物と同じものを作って見ようかと思ってます。