私は33年間、業務システムを書いてきました。COBOLから始まって、VB、C#、ASP.NET……お客様の会社の請求や在庫を支える、地味だけど「絶対に間違えられない」プログラムです。
そんな私が、憧れだったUnityで初めてCubeを動かしたとき。他の入門記事には書かれていない、3つのつまずきに出くわしました。
動くコードを載せた記事は、たくさんあります。この記事もまず、Cubeを移動・ジャンプさせるコードを一通り作ります。でもそれだけでは終わりません。業務プログラマの目で見たときに「ん?」と引っかかった箇所と、2026年のUnity 6で実際に動かし直した検証結果を、正直に足していきます。
もしあなたも業務システムやWindowsアプリを書いてきた人なら、きっと同じ場所で立ち止まるはずです。一緒に見ていきましょう。
UnityプロジェクトとCubeの準備
Unityでオブジェクトを動かすために、まずはプロジェクトを作成し、シーンにCubeを配置していきましょう!
シンプルなステップなので、初めての方でも安心して進められます。
新しいプロジェクトを作成する

まずはUnity Hubを開き、新しいプロジェクトを作成します。
- Unity Hubを起動します。
- 「新しいプロジェクト」をクリックします。
- テンプレートは「3D(Built-In Render Pipeline)Core」を選択します。
- プロジェクト名は分かりやすく「CubeMoveJump」としましょう。
- 保存場所を指定して「作成」を押します。
これで、移動・ジャンプを試すためのシンプルな3D環境が整いました!
Plane(地面)オブジェクトを配置する

プロジェクトが立ち上がったら、まずシーンに舞台となるPlane(地面)を配置していきます。
- Hierarchy(ヒエラルキー)ウィンドウ上で右クリック
- 【3D Object】→【Plane】を選択します
- シーン中央にPlane(地面)が配置されます
※もし中央に配置されていない場合、インスペクターのTransform→Positionを全て0にする
Cubeオブジェクトを配置する

プロジェクトが立ち上がったら、次はシーンにCubeオブジェクトを配置していきます。
- Hierarchy(ヒエラルキー)ウィンドウ上で右クリック
- 【3D Object】→【Cube】を選択します
- シーン中央に白いCubeが配置されます
これが、今回操作の対象になるオブジェクトです。
Rigidbodyコンポーネントを追加する

次に、Cubeに「物理挙動」を持たせるためのコンポーネントを追加します。
- HierarchyでCubeを選択
- Inspector(インスペクター)ウィンドウで「Add Component」をクリック
- 「Rigidbody」と検索し、追加します
これでCubeに重力や物理演算が働くようになりました!
Rigidbodyがあることで、ジャンプや落下など「現実っぽい動き」ができるようになります。
Rigidbodyを追加するだけで、Unityは自動的に重力や衝突などの物理演算を有効にしてくれます。
Cubeを移動させる(WASDキー操作)

Cubeを前後左右に動かせるように、
WASDキーの入力を受け取り、Rigidbodyを使って物理的に動かすスクリプトを作成します。
これができると、ゲームキャラクターの**「基本の移動操作」**が自分で制御できるようになります!
移動用スクリプトを作成する

Assetsフォルダで右クリック → Create > C# Script- スクリプト名を
CubeMoverにします - Cube オブジェクトを選択し、作成したスクリプトをドラッグ&ドロップでアタッチします
スクリプトがCubeに紐づいた状態になります!

WASD入力を受け取る仕組みを理解しよう
CubeMoverファイルを開き、以下のようなコードを記述します。
using UnityEngine;
public class CubeMover : MonoBehaviour
{
public float moveSpeed = 5f;
private Rigidbody rb;
private void Start()
{
rb = GetComponent<Rigidbody>();
}
private void FixedUpdate()
{
float moveX = Input.GetAxis("Horizontal");
float moveZ = Input.GetAxis("Vertical");
Vector3 move = new Vector3(moveX, 0f, moveZ) * moveSpeed;
rb.velocity = new Vector3(move.x, rb.velocity.y, move.z);
}
}
解説
Input.GetAxis("Horizontal")→ A・Dキー(または←→キー)Input.GetAxis("Vertical")→ W・Sキー(または↑↓キー)FixedUpdate()→ Rigidbodyを扱うときに使うフレーム制御関数
WASDの入力をリアルタイムに取得し、Rigidbodyの速度として反映させます。
Cubeオブジェクトが回転してしまうときは…

Rigidbodyを使った移動では、オブジェクトが物理的に回転してしまうことがあります。
それが気になる場合は、Cubeのインスペクターで Constrains→Freeze Rotation のX/Zにチェックを入れておくと、地面の上をまっすぐ動かすことができます。
今回はCubeオブジェクトの物理さしさを生かすため、回転はあえてそのままでもOKです。
お好みに合わせて設定してみてください。
つまずき①|FixedUpdate って、何の時計で動いてるの?
さっそくコードを書いていきますが、その前に。移動スクリプトの中に、こんな見慣れないメソッドが出てきます。
private void FixedUpdate()
{
// ここに移動の処理を書く
}Start はまだわかります。「最初に一回だけ呼ばれる」——業務でいう初期化処理ですね。でも FixedUpdate って、いったい誰が、いつ呼んでいるんでしょうか?
私はここで、最初の大きなつまずきに出くわしました。
業務プログラムは「呼ばれてから動く」
33年間、私が書いてきた業務システムやWindowsアプリは、基本的にぜんぶイベント駆動でした。
ボタンが押される → Button_Click が呼ばれる → 処理する → 終わり。
画面が開かれる → Form_Load が呼ばれる → 初期表示する → 終わり。
「何かが起きたら、それに反応する」。これが体に染みついた基本形です。逆に言えば、何も起きなければ、プログラムは何もしません。ボタンを押さないのに Button_Click が勝手に走り出したら、それはもう不具合です。
Unityは「誰も呼ばないのに、ずっと動いている」
ところがUnityは、まるで逆でした。
Update() というメソッドは、誰もクリックしていないのに、あなたが何もしていないのに、勝手に毎秒約60回、走り続けています。ゲームが起動している間ずっと、休みなく。
初めてこれを知ったとき、正直ぞわっとしました。業務の感覚では「暴走」に見えるからです。でも、考えてみれば当たり前でした。ゲームの画面は、キャラが動き、敵が迫り、時間が流れ続けている。世界そのものが、止まらずに動き続けている。だから毎フレーム、世界を少しずつ描き直す必要がある。その「毎フレームの心臓の鼓動」が Update() なんです。
業務アプリが「お客さんが窓口に来たら対応する銀行の受付」だとしたら、Unityは「お客さんがいてもいなくても回り続ける、遊園地のメリーゴーラウンド」。この違いに気づいたとき、Unityがすっと腑に落ちました。
で、Update と FixedUpdate、時計が2つある
やっかいなのは、その「勝手に動く時計」が、Unityには2種類あることです。
| メソッド | 呼ばれるタイミング | 何に使う |
|---|---|---|
Update() | 毎フレーム(PCの性能で回数が変わる) | キー入力の受付、見た目の更新 |
FixedUpdate() | 一定の時間ごと(性能に関係なく一定) | Rigidbodyを使った物理の処理 |
なぜ分かれているのか。ここに、業務プログラマがハマる罠があります。
Update() は、PCが速ければ毎秒120回、遅ければ毎秒30回、と回数がバラバラになります。画面を描くだけならそれでいい。でも、これで物理演算(重力や速度の計算)をやると、速いPCと遅いPCで、キャラの動く距離が変わってしまうんです。同じゲームなのに、環境によって挙動が変わる。
業務システムでこれをやったら大事故です。「このPCだと合計金額が合うのに、別のPCだと合わない」——考えただけで冷や汗が出ます。Unityはこの問題を避けるために、物理の計算だけは、性能に左右されない一定リズムの FixedUpdate() に隔離しているわけです。
だから、この記事の移動処理はこうなっています。
- キー入力を「受け付ける」のは、反応の速さが大事だから →
Update()寄りの発想 - Rigidbodyで「実際に動かす」のは、環境で挙動が変わっては困るから →
FixedUpdate()
「入力は素早く、物理は正確に」。時計を使い分ける理由が腑に落ちると、FixedUpdate はもう怖くありません。
つまずき②|このコード、2026年のUnity 6だと勝手に書き換わりました
移動のコードを、もう一度見てください。
rb.velocity = new Vector3(move.x, rb.velocity.y, move.z);この記事のベースは、私がUnity 2022.3で書いたものです。当時、このコードは何の問題もなく、これが正解でした。
ところが2026年、私はこのプロジェクトをUnity 6で開き直しました。そして移動処理を見て、思わず二度見しました。自分では一文字も触っていないのに、コードがこう変わっていたんです。
rb.linearVelocity = new Vector3(move.x, rb.linearVelocity.y, move.z);velocity が linearVelocity に。誰が書き換えたのか。私は書いていません。
「旧形式です」——戻してみて、理由がわかった
気になったので、試しに元の rb.velocity に手で戻してみました。すると、Visual Studioがすかさず警告を出しました。

Unity 6(正確にはUnity 2023.3以降)で、Rigidbody.velocity は非推奨になりました。今後は linearVelocity(線形速度)を使ってください、という案内です。角速度 angularVelocity と名前の対を揃えるための変更ですね。
つまり、こういうことでした。
- 2022年に書いた
rb.velocityは、当時は正しかった - Unity 6でプロジェクトを開いたとき、Unityが「これは古い書き方だから直しておくよ」と、自動で
linearVelocityに書き換えた - 警告文の末尾にあった
(UnityUpgradable) -> linearVelocityが、その「自動で直していい印」だった
フレームワークが、勝手に私のコードを直す
ここで、また業務畑の私が固まりました。
フレームワークが、開発者に断りなくソースコードを書き換える。 業務システムの世界では、まず起こりません。私たちの現場では、ソースは一行たりとも「誰が・いつ・なぜ変えたか」を記録します。勝手に書き換わるなんて、恐怖でしかない。もし基盤が黙ってコードを直したら、その日は原因調査で一日が終わります。
でもUnityのこれは、恐怖ではなく——正直、ありがたい親切でした。
ゲームエンジンは、バージョンが上がると古い書き方がどんどん非推奨になります。その全部を手で追いかけるのは大変です。Unityは「よく使われる古いAPIは、開こうとした時に自動で新しい書き方へ直す」という仕組み(API Updater)を持っていて、面倒を肩代わりしてくれる。業務システムの「絶対に勝手に変えるな」という文化とは真逆ですが、変化の速いゲーム開発では、この割り切りのほうが合っているんだと思います。ここでもまた、二つの世界の価値観の違いを感じました。
で、私はどっちを書けばいいの?
あなたの環境しだいで、答えが変わります。
| あなたのUnity | 書くべきコード |
|---|---|
| Unity 2022.3 など(〜2023.2) | rb.velocity(linearVelocity はまだ無い) |
| Unity 6(2023.3〜) | rb.linearVelocity(velocity は非推奨警告が出る) |
新しくこれから作るなら、Unity 6を使っている方が多いはずなので、linearVelocity で書いておけば安心です。もし古い教材や記事のコードをコピーして「警告が出た」「動かない」と焦ったら、まずこの名前の違いを疑ってみてください。
そしてこれは、入門記事を読むとき全体に言えることです。サンプルコードには「賞味期限」があります。 書かれた当時のバージョンでは正しくても、数年経つと非推奨になっていることがある。
だから私はこの記事で、あえて「いつのバージョンで書いたか」を明記しています。あなたが2028年にこれを読んでいたら——そのときはまた、別のAPIが変わっているかもしれません。
Cubeオブジェクトをジャンプさせる(スペースキー)

キャラクターのジャンプは、ゲームらしい操作のひとつです。
ここでは Cube にジャンプ機能を追加して、スペースキーで「ぴょんっ」と跳ねる動きを実装してみましょう!
スクリプトにジャンプ処理を追加する
前回作成した CubeMover.cs に、ジャンプのための変数と処理を追記します。
public float jumpForce = 5f;
private bool isGrounded = true;そして Update() メソッド内に以下の処理を追加します
if (Input.GetKeyDown(KeyCode.Space) && isGrounded)
{
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
isGrounded = false;
}このコードではスペースキー押下と「地面にいるとき」にジャンプできるようにしています。
地面に触れたら再びジャンプできるようにする
ジャンプのあとに再びジャンプができるように、OnCollisionEnter() を使って「何かに触れたら着地したとみなす」処理を追加します。
private void OnCollisionEnter(Collision collision)
{
isGrounded = true;
}ここではすべてのオブジェクトとの接触で isGrounded = true にしていますが、
あとで「地面だけに限定する」処理も追加可能です。今回は省略します。
完成したジャンプコードの全体像
最終的に、CubeMover.cs は以下のようになります。
using UnityEngine;
public class CubeMover : MonoBehaviour
{
public float moveSpeed = 5f;
private Rigidbody rb;
public float jumpForce = 5f;
private bool isGrounded=true;
private void Start()
{
rb = GetComponent<Rigidbody>();
}
private void Update()
{
// ジャンプ
if (Input.GetKeyDown(KeyCode.Space) && isGrounded)
{
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
isGrounded = false;
}
}
private void FixedUpdate()
{
float moveX = Input.GetAxis("Horizontal");
float moveZ = Input.GetAxis("Vertical");
Vector3 move = new Vector3(moveX, 0f, moveZ) * moveSpeed;
rb.velocity = new Vector3(move.x, rb.velocity.y, move.z);
}
private void OnCollisionEnter(Collision collision)
{
// 地面に触れたら再ジャンプ可能にする(Planeなど)
isGrounded = true;
}
}つまずき③|「今回は省略します」に、私はゾッとした
ジャンプのコードは、これで一応動きます。でも私は、この部分を書いた瞬間に手が止まりました。
private void OnCollisionEnter(Collision collision)
{
// 地面に触れたら再ジャンプ可能にする
isGrounded = true;
}もう一度、コードをよく見てください。このメソッドは「何かに触れたら」isGrounded を true にしています。何か、です。地面とは書いていません。
つまり——空中でジャンプ中に、横の壁にちょっと触れただけで、また跳べてしまうんです。壁を蹴って二段ジャンプ、三段ジャンプ。マリオならアクロバティックですが、たいていのゲームでは「バグ」と呼ばれる動きです。
入門記事では、ここをこう書いて済ませることがよくあります。「今回は省略します」と。実は、この記事のベースにした私自身の下書きにも、そう書いてありました。
でも、この「省略します」に、業務畑の私はゾッとしたんです。
なぜ業務プログラマはここで固まるのか
業務システムの世界で、「条件が漏れてるけど、まあ動くから今回はいいか」は、絶対にやりません。
たとえば請求書の合計金額を計算するコード。「特定の取引先だけ、消費税の丸め方が違う」という条件を一つ書き忘れたら、請求額が数円ずれます。たった数円。でもそれが100社分、毎月積み重なって、決算のときに「帳簿が合わない」と大騒ぎになる。私はそういう現場を、何度も見てきました。
だから業務プログラマの体には、「例外条件を書き漏らす気持ち悪さ」が染みついています。この OnCollisionEnter を見た瞬間、頭の中で赤ペンが走りました。「これ、レビューなら差し戻しだぞ」と。
業務の「気持ち悪さ」で、ちゃんと直してみる
というわけで、直しましょう。やることはシンプルで、「触れた相手が地面かどうか」を確認してから isGrounded を戻すだけです。
まず、地面役のPlaneに「Ground」というタグを付けます。
- HierarchyでPlaneを選択します
- Inspectorの一番上、名前の下にある「Tag」→「Add Tag…」をクリックします
- 「+」で
Groundというタグを新規作成します - もう一度Planeを選び、Tagのプルダウンから
Groundを選びます
そして、コードをこう書き換えます。
private void OnCollisionEnter(Collision collision)
{
// ★「地面」に触れたときだけ、再ジャンプ可能にする
if (collision.gameObject.CompareTag("Ground"))
{
isGrounded = true;
}
}CompareTag("Ground") で、「今ぶつかった相手はGroundタグを持っているか?」を確認しています。壁に触れても、その壁がGroundタグでなければ isGrounded は true になりません。これで、空中で壁を蹴って跳ぶことはできなくなりました。
「省略」が正しいときもある、という話
ここまで書いておいて、ちゃぶ台をひっくり返すようですが——元記事の「省略します」が間違いだったとは、実は思っていません。
ゲーム開発を始めたばかりの段階で大事なのは、とにかく「動いた!」という体験を早く得ることです。細かい条件を全部潰してから先に進もうとすると、たいてい途中で力尽きます。まず動かして、面白さを感じて、それから「あれ、壁でも跳べちゃうな」と気づいて直す。この順番でいいんです。
業務システムは「最初から完璧」を求められる世界。ゲームは「まず動かして、遊びながら育てる」世界。同じプログラミングでも、正しい進め方がまるで違う。 私がUnityで一番面白いと感じたのは、実はこの価値観のギャップでした。
だからこの記事では、あえて両方載せました。「まず動く版(省略あり)」と「気持ち悪さを潰した版(タグ判定)」。あなたの今の気分で、好きなほうを選んでください。
動きの完成!プレイしてみよう

これまでの作業で、CubeはWASDキーでの移動とスペースキーでのジャンプができるようになりました。
ここでは、実際にプレイして動作を確認してみましょう。
ゲームを再生して操作を試そう
Unityエディター上部の【▶️再生ボタン】をクリックすると、
ゲームがスタートします。
以下の操作を試してみましょう
| 操作キー | 内容 |
|---|---|
| W / A / S / D | 前後左右に移動 |
| Space | ジャンプ(空中では無効) |
スムーズに動けば成功です!
思った通り動かないときのチェックポイント
うまく動かない場合は、次のポイントを確認してみてください:
移動しない場合
- RigidbodyがCubeにアタッチされているか
- スクリプト内の
moveSpeedが0になっていないか
ジャンプしない場合
Input.GetKeyDown(KeyCode.Space)がUpdate()に書かれているかisGroundedがfalseのままになっていないか(OnCollisionEnterの書き忘れ)
回転してしまうのが嫌な場合
- Rigidbody の Freeze Rotation(X/Z) にチェックを入れると安定します
まとめ|業務畑の「違和感」は、Unityでも武器になる

お疲れさまでした。これで、Cubeを自由に動かして、ジャンプさせることができました。
でもこの記事で本当にお伝えしたかったのは、動かし方そのものよりも、その途中で私がつまずいた3つのことでした。振り返っておきます。
- つまずき①:別の時計 — 業務プログラムは「呼ばれてから動く」。でもUnityの
Update()は、誰も呼ばないのに毎フレーム勝手に動き続ける。物理はFixedUpdate()という別の時計で動く。この「世界が止まらない」感覚が、ゲーム開発の入口でした。 - つまずき②:勝手に書き換わるコード — 2022年に書いた
rb.velocityが、Unity 6で開いたらrb.linearVelocityに自動で直っていた。フレームワークが黙ってソースを書き換える——業務では恐怖ですが、変化の速いゲーム開発ではありがたい親切でした。 - つまずき③:省略への違和感 — 「何に触れても再ジャンプOK」なコードに、業務畑の私はゾッとした。でも「まず動かして、遊びながら直す」のもゲーム開発では正解。
CompareTagで地面だけに絞って、気持ちよく直しました。
この3つに共通しているのは、業務システムの常識で見たときに「ん?」と引っかかった、という点です。
私は最初、33年の業務経験なんてゲーム開発では役に立たないんじゃないか、むしろ変な癖がついていて邪魔なんじゃないか、と思っていました。でも実際にやってみると、逆でした。「これ、条件が漏れてない?」「これ、環境で動きが変わらない?」という業務で染みついた違和感は、Unityでもちゃんとバグを見つける嗅覚として働くんです。
もしあなたも、業務システムやWindowsアプリを書いてきた人なら。その経験は、遅れてゲーム開発を始めるうえで、足かせではなく武器になります。私はそれを、このCubeを動かすだけの小さなサンプルで確信しました。
次は、この動くCubeに「見た目」を与えていきましょう。次回は〇〇です。それでは、また。
次のステップに進みたくなったら…
もしあなたが「もっと見た目を整えたい」「キャラクターっぽくしたい」と思ったら、
次は アニメーション付きの3Dキャラクターで、同じように移動やジャンプを実装してみましょう!

あるいは、カメラの視点をプレイヤーに追従させたい!と感じたなら、
次は Unity標準のカメラを使って、カメラをキャラクターに追従させる方法をチェックしましょう。

読者様への一言

Unityの開発は、ひとつずつ動かして試すことが最短ルートです。
うまくいかなくても大丈夫。
次に「なぜだろう?」と手を止めて考える時間こそが、
あなたの実力をグンと伸ばしてくれます。
📌このブログでは、Unityをこれから学ぶ方へ向けて、
「動く楽しさ」「わかる安心感」を軸に、丁寧な記事を発信しています。
また一歩進みたいときに、ぜひ戻ってきてくださいね!
次のチャレンジも、一緒に取り組んでいきましょう😊
使用しているソフトウェア
- Unity Editor 6000.3.91f1(LTS)
※本文中のエディター画面のスクリーンショットは、Unity Technologies社が提供する開発環境の画像を紹介・解説目的で引用しています。
