[Unity] #06: 直線レール敷設と列車の自走・停止

はじめに

Unity4日目。今日もUnityをボチボチやってみました。

前回の記事は、以下でその続きになります。

Three.jsで実装した、線路・列車をUnityでもやってみたいと初期の頃から考えていて、今日はそれをやってみました。

毎回同じ事を言ってますが、Three.jsだと線路を引いたり、列車を走らせるのも回転制御など書くべきコードが沢山あり大変ですが、Unityだと短いコードで列車の移動や回転制御が出来てしまいます。

ただ、別の意味でUnity特有のインセプターなどのGUI操作を覚える必要がありその辺りのトラブル情報などもまとめています。

1. レールの大量配置(直線)まで完成

最初に取り組んだのは、街の外側へ向かう 直線レール区間の敷設。 今回採用した railway_short 系のローポリモデルは、1ピースあたりの長さが程よく、複製 → 配置 → 微調整 の流れが非常に扱いやすかった。

Unity の強みは、複製(Ctrl + D)と配置のフィードバックが速いところにある。 複製したレールを Scene 上でドラッグすると、Three.js のようにコードで座標を打ち込む必要がなく、視覚的に“線路を延ばしている感覚”が得られる。

レールを大量に並べるにあたっては、1本ずつシーンに放置すると管理が破綻するので、すべてのレールを Empty(例:StraightLine01)の子にまとめた。 これにより、

  • 直線区間ごとの管理
  • 一括移動
  • プレハブ化の準備
  • ルートごとの整理

などがやりやすくなる。

また配置作業を進める中で、Unity の Inspector で数値を直接調整する手法が Three.js より圧倒的に早いことに気づいた。 特に Z 軸方向の位置合わせや、高さの誤差修正が1〜2クリックで完結するのは大きな利点。 Three.js 時代にやっていた「コード → 保存 → リロード → 誤差確認 → 再調整」のループが完全に不要になった。

レールを 20 本、30 本と並べていくと、 「本当にゲームの地形を作っている」という手応えが出てくる。 Three.js のように“自前で地形エンジンを作っている感覚”ではなく、Unity のエディタ上で“現場監督”のように建設する作業フローがそのまま身についたのが今日の大きな収穫だった。

2. 列車(Train)オブジェクトの移動スクリプトが完成

線路が直線区間だけでも成立することが分かったので、次のステップとして 列車の移動ロジックを TrainMove.cs として実装した。 やっていることは非常にシンプルで、「次の目標座標に向かって進む」だけだが、Unity の Transform 制御は Three.js とほぼ同じ思想のため、実装は驚くほどスムーズだった。

今回作ったスクリプトの核は、

  • ターゲット Transform との方向ベクトルを取り
  • normalized で進行方向を計算し
  • 毎フレーム少しずつ移動させる

という最低限の仕組み。 Three.js で散々触ってきた lookAt() の延長線で理解できるため、UnityはAPI名が違うだけで、空間ベクトルの扱いが同じという強い手応えがあった。

興味深いのは、停止処理の自然さ。 駅の手前に StopPoint を置いて、列車からその Transform との距離を計算し、一定以下なら停止するだけだが、それでも“それらしく”見える。 Unity は Transform の更新が単純で、シーンビューとゲームビューが常に連動しているため、実装の正誤が直観的に確認できるのが Three.js より圧倒的に楽だ。

実際の動作では、 駅に突っ込んで脱線したり、ターゲット座標の設定で暴走したりと、事故もあったが、それすらも方向ロジックが正しく動いている証拠。 “壊れ方が分かりやすい”のはデバッグにおいて重要で、今回の実装で Unity の Transform 制御に完全に慣れた。

総じて、今回の TrainMove の実装で

  • 方向ベクトルの計算
  • 位置更新のループ
  • シーン内オブジェクトとの距離判定
  • 停止条件の設計

といった、3Dの基礎ロジックが Unity でも全く同じ形で通用することを実感した。

Three.js で磨いた「空間の直感」が、Unity でもそのまま武器になる── そう確信できたポイントだった。

3. Empty + Inspector ロック の技を習得

大量のレールを並べていく途中で、Unity 特有の 「Inspector ロック(🔒)」 を初めて本格的に使った。 これが想像以上に強力で、Three.js では絶対に味わえない “エディタならではの作業効率” を実感したポイントだった。

Unity では、Hierarchy 上でオブジェクトを切り替えると、Inspector の内容も自動で切り替わる。 普段は便利だが、 「ある親オブジェクトの Inspector を固定しつつ、他の子オブジェクトを次々と選択する」 という操作が必要になる場面では、逆に足かせになる。

今回で言えば、直線レールをまとめるために作った Empty(例:StraightLine01)に、 railway_short_k (1〜40) を次々ドラッグ&ドロップする必要があったが、普通にやると:

  • 子レールをクリック → Inspector が子 rail の情報に切り替わる → 親を再選択し直す → また子をクリック → Inspectorが切り替わる…

という無限ループで、とても作業にならない。

ここで登場したのが 🔒(Lock) ボタン。 Inspector の右上にあるこの小さな鍵アイコンを ON にしておくと、 どのオブジェクトをクリックしても Inspector の対象が切り替わらなくなる。

つまり、

  1. 親の Empty を選択
  2. 🔒 を ON にする(Inspectorを固定)
  3. 子レールを好きなだけ選択・移動・追加できる

という状態になり、作業効率が一気に跳ね上がる。

Three.js や Web のワークフローでは “場面ごとに同じUIを保つ” という概念が薄いので、 この「Inspector を固定して、別のオブジェクトを自由に選べる」UIは完全に Unity ならではの体験だと感じた。

レールだけでなく、列車、駅、地形など 複数オブジェクトを階層ごと整理する場面では必須のテクニックで、 Unityの “エディタが持つ強さ” を理解した瞬間だった。

4. Sceneビューの操作がさらに上達

街づくり作業の中で、Sceneビューでのカメラ操作と Gizmo 操作が一気に体に馴染んできた。 最初は “どこが正面でどこが上か” 迷うことも多かったが、今日だけでかなり直感的に動けるようになった。

具体的には、

  • 右ドラッグ → 視点を回す
  • 中クリック(ホイール押し) → 平行移動(パン)
  • ホイール回転 → ズーム
  • W/E/R キーで Gizmo を即切り替え(移動・回転・拡大)

これらの操作が、意識しなくても指が勝手に動くレベルに到達した。 Unity は “エディタで直接触って作る” のが本質なので、この操作感に馴染むかどうかが作業スピードを大きく左右する。

レールを敷きながら視点を移動したり、駅舎を微調整したり、地形のテクスチャを貼り替えて確認したり―― 作業のたびに Scene カメラを動かす必要があるが、これがスムーズにできるようになったことで、 「Unity で街を形にしていく手応え」が一気に増した。

また、地形テクスチャの調整では、 “見た目がどう変わるか” をそのまま Scene でリアルタイムに確認できるのも Unity の強みだと感じた。

Three.js ではコードを書き換えて再読み込み、という工程が必要だったが、 Unity は Scene をドラッグして回しながら、リアルタイムに見た目を確認できる。 これは地味に大きな差で、作業スピードとモチベーションが段違いになる。

今日で、Sceneビューの扱いがようやく “工具箱の中身を使いこなし始めた段階” に入った。

5. 地形づくりと Prefab 整理が一気に進んだ

レール敷設と並行して、地形(Ground)と街(Town)のフォルダ構造を整理し始めた。 ここは Three.js とはまったく違う考え方が必要で、Unityらしい “Scene階層で世界を管理する” 感覚が少しずつ身についてきた。

Ground/Town を明確に分離

最初はすべてがバラバラに Scene に存在していたが、 地形ブロック(Ground_00)を複製して範囲を広げ始めたタイミングで、 「地形」「街」「線路」の役割ごとに階層を分ける必要性が強くなった。

最終的に、

Sandbox
├ Ground
│   ├ Ground_00
│   ├ Ground_01
│   └ Ground_02
└ Town
    └ Town01_StartVillage

という構造に整理。 Unityは階層構造がそのまま「世界のモデル図」になるため、 ここを整えるだけで作業速度と視認性が劇的に向上した。

Ground_00 を基準に地形を延伸

地形は 64×64 の Plane を使っているので、 X/Z 軸を 64 単位で揃えると タイル状に正確に並べられる。 Three.js でポリゴン地形を自作していた頃のような“境界のズレ”がないのは安心材料。

ただし、テクスチャの境界がくっきり見える問題は残ったので、 最終的には同じテクスチャで統一して作業を進めた。

Prefab 化で「駅」「列車」「レール」を再利用可能な状態へ

Unity の強みである Prefab を利用して、

  • 駅(Station)
  • 列車(Train)
  • レール(railway_short)

をすべて Prefabs フォルダへ保存。 特にレールと駅は、何度も再利用するパーツなので、Prefab 化のメリットが大きい。

Prefab 化したことで、

  • Scene 全体を壊さずに複製できる
  • 駅セットを丸ごと再配置できる
  • 線路の種類(直線・短尺・曲線)ごとに管理できる

と、街づくりゲームのような作業フローが確立された。

アセットの“サルベージ”(取得)も経験した

駅アセットを分解して、

  • 駅舎
  • ランプ
  • ベンチ
  • 石の装飾
  • 小道具一式

を抜き出し、Prefab 化して再利用できるようにした。 Unity の良さはここで、Three.js ではあり得なかった 「アセットごと吸収して自分の世界に組み込む」柔軟性を体感した。


ここまでで、 地形ブロック × レール × 駅 × 街並み という “ワールドの基礎構造” が完全に固まった。

Unity が一気に「作業空間として手に馴染んだ」手応えがあった章だった。

6. StopPoint(停止ポイント)と WayPoint を使った列車制御の基礎が完成

直線レールを敷き終えた段階で、列車を「ただ走らせるだけ」では物足りなくなり、 “駅で止まる” 挙動を実装するフェーズに入った。

Unity の利点は、Three.js と違って Empty(空オブジェクト)を自由に置けるところ。 これを使って「ルート」「停止位置」を視覚的に設置できるのが非常に快適だった。

StopPoint(駅の停止位置)を設置

駅オブジェクトの中に Empty を作り、名前を StopPoint に変更。 これを「列車が停止すべき座標」として使う。

Scene 上で 実際の駅の手前に配置できるので、 Three.js 時代みたいに “座標値の調整 → 再読み込み” の無駄がない。

列車側(Train オブジェクト)の TrainMove スクリプトにある StopPoint に この Empty をドラッグするだけで、列車は そこに向かって走り、そこで停止 する。

最初は勢い余って駅に突っ込み脱線したが、 それも「座標を正しく指定すれば解決する」という意味で、 制御ロジック自体は問題なく動いているのを確認できた。

WayPoint(進行ルート)を設定して列車を誘導

StopPoint だけでは直線上の1点にしか止まれない。 そこで、線路に沿って Empty の WayPoint 群 を大量に設置し、 TrainMove のルート配列として渡すことで、

  • 線路に合わせて進行方向が変わる
  • カーブ(将来的に)にも対応可能
  • 次の駅までルート誘導できる

という “鉄道らしい動作” が実現できる構造になった。

特に便利だったのが、Unity の Inspector ロック(🔒)。 ルートを登録する際、

  • Train をロック
  • 下で線路パーツを選んで
  • WayPoint を大量にドラッグして追加

という作業が一気に楽になった。

Three.js の頃に比べると、 「視覚的にルートを作れる」というのは圧倒的な快適さだった。

方向ベクトルと回転は Three.js の経験がそのまま生きた

TrainMove.cs のコア処理はシンプルで、

Vector3 dir = (target.position - transform.position).normalized;
transform.position += dir * speed * Time.deltaTime;
transform.forward = dir;

これは Three.js の lookAt() や方向ベクトル処理とまったく同じ発想。 Unity になっても “方向ベクトルを決めて、進ませて、向かせる” という基礎が完全に共通していた。

Unity に来ても、三次元の基礎知識が無駄になっていないどころか、 Three.js で地獄を味わった分、Unity が楽に感じる部分も多くなっている。

7. Blender × Unity の往復でレールモデルを加工

直線レールを敷設していく中で、railway_short モデルをそのままスケール調整すると レール幅や枕木の比率が崩れる問題に直面した。 Z軸方向を縮めれば長さは変えられるが、見た目としては不自然になる。

この時点で、 「Unity 上で無理に誤魔化すより、モデルを正しく加工した方が早い」 と判断し、Blender に戻ることにした。

Unity から Blender へエクスポート

Unity には標準で FBX Exporter が用意されており、

  • 対象のレールオブジェクトを選択
  • Export to FBX で書き出し
  • Blender でそのまま読み込み

という流れで、非常にスムーズにモデルを受け渡せた。 「Unity → Blender → Unity」という往復が、思った以上に軽い。

Blender 側でのレール加工

Blender では、レール部分と枕木部分の構造を確認しつつ、

  • 枕木の数を整理
  • レールの長さを 頂点編集で正確に短縮
  • 全体の比率を崩さないように調整

という、最小限の加工だけを行った。

  • 編集モード
  • 頂点選択
  • 横からのオルソ表示
  • Gキーでの頂点移動

再インポート後の確認

加工後の FBX を Unity に戻すと、

  • レールの長さが意図通り
  • 見た目の違和感なし
  • 直線敷設にちょうど良いサイズ

という結果になった。

白っぽく見えるなどマテリアル周りの違いはあったが、 ゲームプレイ視点ではほぼ問題にならないことも確認。 細部よりも、まず全体を前に進める判断を優先した。


この工程を通して、 Unity と Blender を横断する作業フローが完全に手に馴染んだ。

「Unityで配置 → Blenderで加工 → Unityで再配置」 この循環が回り始めると、 市販アセットを“素材”として扱える段階に入った感覚がある。

8. Unity 6 特有の UI・仕様で詰まった点の整理

Unity 6 は細かい UI 仕様が変わっており、古い記事や回答がそのまま役に立たない場面が多かった。 今日だけでも複数の “Unity6特有のハマりポイント” に遭遇したので、再発防止のためにまとめておく。


1. 「回転スナップ(Rotate Snap)」がどこにも見つからない問題

ネットの情報は Unity 2021〜2022 向けが多く、

  • Snap Overlay が勝手に出てくる
  • 🧲アイコンの横に「Rotate Snap 15°」がある
  • Edit → Grid and Snap Settings が開ける

……などの説明が一切 Unity 6 では当てはまらない。

実際は、Unity 6 では Snap Overlay がデフォルトOFF になっており、 そのせいで「スナップUIが存在しないように見える」状態になっていた。

対処:

  1. Scene の右上にある [`](BackQuote)で Overlay メニューを開く
  2. 検索窓で Snap と打つ
  3. Snap Overlay(┇)を有効化

これでようやく、マグネット・移動スナップ・回転スナップが使えるようになる。

Unity 6 では「見えなくても存在しているUIがある」という罠。


2. Play中に編集してしまい、全変更が消える問題

何度も続いた “赤い警告バー” の通り、Playモードでの編集は 再生終了と同時に全消滅 する。

Unity 6 では、 Play中の変更はわりと気付かないまま適用できてしまうため、事故が起きやすい。

特に今日のように:

  • 駅を組み立て
  • 馬を抜き出し
  • 植林して街を拡張し
  • Prefab化し

などを Play中に全部やってしまい、消える 可能性があった。

Unityの“古典的地雷”だが、Unity6でも健在。

※パフォーマンス画面から、Colors、Pleymode で色を赤などにしておくとミスがなくなると思います。

3. Prefab → Unpack Completely が古いUI記事と違う

古い記事では

  • Prefab の右クリック → Unpack Completely

と書かれているが、Unity 6 は 別名でメニューに入っている場合がある。

Unity 6 の場合の挙動は:

  • Prefab を Hierarchy に置くと青色になる
  • 親を選択 → 右クリック
  • Prefab → Unpack Completely の構造になっている (古いUIは Prefab 直下のメニューだった)

さらに、アセット元のPrefabを触っているか、 ゲーム内で複製したPrefab Variantを触っているかで表示項目が変わる。

今日みたいに「選べたり選べなかったり」が起きるのはこれが原因。


4. Mesh Renderer の “Materials” が見えない問題

BlenderからUnityに戻したレール(railway_short.fbx)が、 Inspectorで Mesh Renderer に Materials 欄がそもそも表示されない 状態になっていた。

これは Unity 6 特有の挙動として:

  • インポートしたFBXの Root ノード と
  • 実際の Mesh オブジェクト

が階層として分離しているケースがある。

つまり、親を選んでも Materials が見えず、 子の Mesh を選ぶと初めて表示される。

アセットによって階層構造がまったく違うため、 Unity 6 は「見えるものが必ずメッシュとは限らない」 のが大きな罠。


5. Scene操作の Overlay が Unity 6 で激変

Unity 6 は Scene の Overlay(ツールパネル)がかなり変更されており、 古いブログ記事にある

  • モード切替ボタン
  • Grid / Snap
  • Gizmo設定

の配置が全然違う。

実際、lain が見た UI:

  • ハンバーガーアイコン → カメラ設定
  • 3つ点のメニュー → Scene全体の表示切替
  • 歯車 → Gizmo設定
  • Snap → なぜか非表示

これは Unity 6 の Overlay設定が初期状態でミニマム構成だからで、 Snap Overlay をオンにしないと “そもそも存在しないUI” になる。

Unity 6 の UIが極端にモジュール化されたことで起きる混乱。


6. Blenderから戻したFBXのマテリアルが白くなる問題

原因は単純で、

  • Blender → FBX → Unity に戻すと
  • Blender側で設定してたマテリアルは基本引き継がれない

Unity 6 の URP は Standard と別物なので、 再インポート時は常に白い“デフォルトマテリアル”になる仕様。

今日みたいに「見た目ほぼ変わらない」というケースもあるが、 本当は URP 向けに Shader Graph を組んだ方が美しい。


7. パーツをドラッグしようとしても Inspector が消える問題

これは Inspector ロック🔒 を使うと一発で解決したが、 Unity 6 のエディタは

  • 右クリック
  • 左クリック
  • ドラッグ
  • 押しっぱなし

で Inspector がコロコロ切り替わるため、 Three.js 出身者にはとにかくストレス。

Inspectorロックは Unity 6 でも救いの機能。

9. まとめ

今日は Unity 上で “街と鉄道の基礎構造” を一気に築き上げた日だった。

  • Ground(地形)を整理し、街と線路の配置がしやすい環境を整え
  • ローポリのレールアセットを分解して必要なパーツだけ抽出
  • Blender と Unity を往復してレールを正しい比率で加工し
  • Prefab 化した駅・レール・小物で街のモジュール化が進み
  • 直線レールを長距離設置して世界が横に広がり
  • 列車(Train)に簡単な移動スクリプトを作り
  • StopPoint と WayPoint で “レールに沿って駅まで走る” 挙動が完成

と、要素ごとの小さな成功が積み重なって 結果として “鉄道シーンの基礎全体” が成立した。

特に今日は Unity の強みがはっきり見えた。

  • Sceneビューで直感的に配置できる
  • Inspector ロックで大量オブジェクトを扱える
  • Prefab 化で再利用と整理がどんどん楽になる
  • アセットをBlenderで加工してUnityに戻す自由度
  • Empty をポンと置くだけで “停止位置” や “進行ルート” が作れる

Three.js 時代の “何でもコードで書いていた世界” と比べると、 Unity はまさに 「手で街を建設できる環境」 だと実感する。