ダークモード
第3回 自機を動かす
この回でつくるもの:初めてのスクリプト「PlayerController」を書いて、キーボードの WASD や矢印キー、ゲームパッドで自機を上下左右に動かせるようにします。
この回で学ぶこと
- スクリプト(C#)ファイルの作り方と、ゲームオブジェクトへの付け方
StartとUpdateのちがい、Debug.Logで Console に文字を出す方法- Input System の Move アクションで入力を受け取る方法
- 変数、
Vector2とVector3、Time.deltaTimeの意味 public変数を Inspector で変える方法
前回までのふりかえり
第2回では、空のオブジェクト Player の下に Bank > Model(宇宙船のモデル)と Muzzle(弾が出る場所)を作り、右を向いた自機を画面の左側(x = -6)に置きました。 まだ自機は動きません。
1. スクリプトを作る
1-1. スクリプトとは
スクリプト(Script)は、ゲームオブジェクトに「どう動くか」を教えるプログラムです。 Unity では C#(シーシャープ)という言葉で書きます。 スクリプトもコンポーネントの1つで、ゲームオブジェクトに付けると動き出します。
1-2. PlayerController を作る
- Project ウィンドウで
Assets/_Game/Scriptsを開きます。 - 右側の何もないところで右クリックし、Create > Scripting > MonoBehaviour Script を選びます。
- ファイルができて、名前を入力できる状態になります。すぐに
PlayerControllerと入力して Enter キーを押します。
よくあるまちがい
ファイル名とクラス名は必ず同じ にします。ファイル名は、スクリプトの中の public class PlayerController の PlayerController の部分と一致していないといけません。 名前を入れる前に Enter を押してしまったり、あとからファイル名だけ変えたりすると、ずれてしまいます。まちがえたときは、ファイルを消して作りなおすのがいちばん簡単です。 大文字・小文字も区別されます。playercontroller や Playercontroller ではダメです。
2. コードを書くエディタの設定
2-1. コードエディタとは
スクリプトは、コードエディタ というアプリで書きます。次のどれかを使います。
| エディタ | 特ちょう |
|---|---|
| Visual Studio Code(VS Code) | 軽くて、Windows でも Mac でも使える |
| Visual Studio | Windows 向け。Unity のインストール時にいっしょに入れられる |
| Rider | 高機能。学生は無料で使えることがある |
どれを使うかは、先生の指示にしたがってください。
2-2. Unity にエディタを教える
- Windows はメニューの Edit > Preferences、Mac はメニューの Unity > Settings を選びます。
- 開いたウィンドウの左側で External Tools を選びます。
- External Script Editor の欄を押して、使うエディタ(例: Visual Studio Code、Visual Studio Community 2022)を選びます。
- ウィンドウを閉じます。
ヒント
一覧に使いたいエディタが出てこないときは、Browse... を選んで、エディタのアプリを直接選びます。 VS Code を使う場合は、VS Code の拡張機能(Extensions)で Unity(Microsoft 製)を入れておくと、入力の候補が出て便利です。
先生へ
VS Code を使う場合、Unity 側は Window > Package Manager で Visual Studio Editor パッケージが入っていることを確認してください(Unity 6 のテンプレートには通常入っています)。VS Code 側は Unity 拡張機能(C# Dev Kit が一緒に入ります)を推奨します。
2-3. スクリプトを開く
- Project ウィンドウの
Assets/_Game/Scriptsにある PlayerController をダブルクリックします。 - コードエディタが開いて、次のようなコードが表示されます。
csharp
using UnityEngine;
public class PlayerController : MonoBehaviour
{
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}これが、Unity が最初に用意してくれる「ひな形」です。
3. Start と Update
3-1. Start と Update のちがい
| 名前 | いつ動く? |
|---|---|
Start | ゲームが始まったとき(そのオブジェクトが動き始めたとき)に 1回だけ |
Update | ゲーム中、毎フレーム(1秒に何十回も)くり返し |
ゲームの画面は、パラパラまんがのように1枚ずつ絵をかきかえて動いています。この1枚を フレーム とよびます。 { と } の間に、やってほしいことを書きます。
3-2. Debug.Log を書いてみる
Debug.Log("文字") と書くと、Console に文字が出ます。プログラムが動いているか確かめるのに使います。
- コードエディタで、PlayerController を次のように書きかえます。
csharp
using UnityEngine;
public class PlayerController : MonoBehaviour
{
void Start()
{
Debug.Log("ゲームスタート!"); // ★追加
}
void Update()
{
Debug.Log("Update が動いた"); // ★追加
}
}- Ctrl+S(Macは Cmd+S)でファイルを保存します。
- Unity に戻ります。右下でくるくる回るマークが消えるまで待ちます。(Unity がスクリプトを読み込んでいます)
注意
- 文の最後には、必ず
;(セミコロン)を付けます。 "や;、()は 半角 で入力します。日本語入力をオフにしてから打ちましょう。("の中の文字は日本語でもOK)//から右は コメント(メモ)です。プログラムとしては無視されるので、日本語で説明を書いておけます。
3-3. スクリプトを Player に付ける
- Unity の Hierarchy で Player を選びます。
- Project ウィンドウの PlayerController を、Inspector のいちばん下の何もないところにドラッグして離します。
- Inspector に Player Controller (Script) というコンポーネントが追加されたことを確認します。
ヒント
Inspector の Add Component ボタンを押して、PlayerController と入力して選んでも付けられます。
3-4. 動作確認(Debug.Log)
- Project ウィンドウのとなりの Console タブを押して、Console を表示します。
- ▶ ボタンを押します。
- Console に「ゲームスタート!」が1回、「Update が動いた」がどんどん出てくればOK。
- もう一度 ▶ ボタンを押して止めます。
Start は1回、Update は何回も動いていることがわかりますね。
ヒント
Console の上にある Clear を押すと、出ているメッセージを消せます。Collapse を押すと、同じメッセージを1行にまとめて、右に回数を表示してくれます。
4. Move アクションを見てみる
4-1. Input System とは
Input System(インプット・システム)は、キーボードやゲームパッドの入力を受け取るしくみです。 「右へ動く」「撃つ」のような アクション(Action)を作っておき、そこにキーやボタンを結びつけます。 こうすると、プログラムでは「どのキーか」を気にせず、「Move の入力はどれくらい?」とだけ聞けば済みます。
テンプレートには、最初から InputSystem_Actions というファイルが入っていて、プロジェクト全体で使えるように設定されています。
4-2. InputSystem_Actions を開く
- Project ウィンドウの左側で Assets を選びます。
- 右側にある InputSystem_Actions をダブルクリックします。
- Input Actions のエディタ(アクションを編集するウィンドウ)が開きます。
4-3. Move を確認する
- いちばん左の Action Maps の列で Player が選ばれていることを確認します。
- 真ん中の Actions の列に Move、Look、Attack、Jump などが並んでいます。
- Move の左の ▶ を押して開きます。
- Left Stick [Gamepad](ゲームパッドの左スティック)や、WASD のようなセットがあることを確認します。
- WASD の ▶ を開くと、Up、Down、Left、Right に、W・A・S・D や矢印キーが結びつけられていることがわかります。
- 何も変えずに、ウィンドウを閉じます。
ヒント
Move を選ぶと、右側に Action Type が Value、Control Type が Vector2 と出ています。Vector2 は「x と y の2つの数」のことです。Move は「左右(x)と上下(y)がどれくらい押されているか」を教えてくれます。
注意
この回では InputSystem_Actions は 何も変えません。もしうっかり変えて「保存しますか?」と聞かれたら、保存しないで閉じましょう。
4-4. Move の値
Move の値は、押したキーによって次のようになります。
| 押したキー | x | y |
|---|---|---|
| 何も押さない | 0 | 0 |
| → または D | 1 | 0 |
| ← または A | -1 | 0 |
| ↑ または W | 0 | 1 |
| ↓ または S | 0 | -1 |
ゲームパッドのスティックなら、少しだけたおすと 0.3 のような途中の値になります。
5. 自機を動かすコードを書く
5-1. コードを書く
- Project ウィンドウの PlayerController をダブルクリックして、コードエディタで開きます。
- 中身を 全部消して、次のコードに書きかえます。
csharp
using UnityEngine;
using UnityEngine.InputSystem;
// 自機を動かすスクリプト
public class PlayerController : MonoBehaviour
{
public float speed = 6f; // 移動の速さ
InputAction moveAction;
void Start()
{
moveAction = InputSystem.actions.FindAction("Move");
}
void Update()
{
// 入力を読む(左右が x、上下が y。-1 から 1 の値)
Vector2 input = moveAction.ReadValue<Vector2>();
// 動かす
Vector3 move = new Vector3(input.x, input.y, 0f);
transform.position += move * speed * Time.deltaTime;
}
}- Ctrl+S(Macは Cmd+S)でファイルを保存します。
- Unity に戻り、読み込みが終わるまで待ちます。
- Console に赤いエラーが出ていないか確認します。
5-2. コードの解説
変数(へんすう)は、数や物を入れておく「名前つきの箱」です。
| 行 | 意味 |
|---|---|
using UnityEngine.InputSystem; | Input System の機能を使います、という宣言 |
public float speed = 6f; | speed という名前の箱に、小数 6 を入れる。float は小数を入れる箱の種類。f は「小数だよ」という印 |
InputAction moveAction; | Move アクションを入れておく箱 |
InputSystem.actions.FindAction("Move") | プロジェクトのアクションの中から Move を探してくる |
moveAction.ReadValue<Vector2>() | 今の Move の値(x と y)を読む |
new Vector3(input.x, input.y, 0f) | x と y と z の3つの数のセットを作る。z は 0(Z = 0 のルール) |
transform.position += ... | 自分の位置に、動く分を足す |
Vector2 と Vector3
| 名前 | 中身 | 使い道 |
|---|---|---|
Vector2 | x, y の2つの数 | 入力(左右・上下) |
Vector3 | x, y, z の3つの数 | 3D の世界での位置や動き |
入力は2つの数(Vector2)ですが、自機の位置は3D の世界なので3つの数(Vector3)が必要です。だから z に 0f を足して Vector3 に作りなおしています。
Time.deltaTime とは
Time.deltaTime は「前のフレームから何秒たったか」です。(1秒に60回 Update が動くなら、約 0.017 秒)
- パソコンが速いと、Update は1秒にたくさん動きます。
- パソコンが遅いと、Update は1秒に少ししか動きません。
speed * Time.deltaTime のように掛けると、どんなパソコンでも 「1秒に speed だけ進む」 ようになります。speed が 6 なら、1秒に 6 進みます。
ヒント
move * speed * Time.deltaTime は「向き × 速さ × 時間 = 進む距離」です。理科で習う「速さ × 時間 = 道のり」と同じ考え方です。
5-3. 動作確認
- Ctrl+S(Macは Cmd+S)でシーンを保存します。
- ▶ ボタンを押します。
- Game ビューを1回クリックします。(キー入力が Game ビューに届くようにするため)
- W A S D キーや 矢印キー を押して、自機が上下左右に動けばOK。
- ゲームパッドを持っている人は、左スティックでも動くか試します。
- もう一度 ▶ ボタンを押して止めます。
先生へ
この時点では画面の外まで動けてしまいます。第4回でこの問題を直すので、生徒が気づいたら「次回直します」と伝えてください。
6. Inspector で speed を変える
6-1. public 変数は Inspector に出る
public を付けた変数は、Inspector に表示されて、そこから値を変えられます。
- Hierarchy で Player を選びます。
- Inspector の Player Controller (Script) を見ます。Speed という欄に
6が入っています。 - Speed を
10に変えます。 - ▶ ボタンを押して動かしてみます。さっきより速く動きます。
- ▶ ボタンを押して止めます。
- 好きな速さが決まったら、その値にしておきます。(迷ったら
6)
ヒント
コードでは speed(小文字)ですが、Inspector では Speed(先頭が大文字)と表示されます。Unity が読みやすく表示してくれているだけで、同じものです。
注意
Inspector の値と、コードの = 6f の値がちがうときは、Inspector の値が使われます。コードの数字を変えても速さが変わらないときは、Inspector の値を確認しましょう。
6-2. プレイ中の変更は元に戻る
- ▶ ボタンを押して、プレイを始めます。
- プレイ中に、Inspector の Speed を
20に変えます。すぐに速くなります。 - ▶ ボタンを押して止めます。
- Speed を見ると、プレイ前の値に 戻っています。
プレイ中は「ためしに変えてみる」のに便利ですが、止めると元に戻ります。 いい値が見つかったら、数字をメモしておいて、止めてから入れなおしましょう。
よくあるまちがい
プレイ中だと気づかずに、たくさん設定を変えてしまい、止めたら全部消えた…というのはよくある失敗です。▶ ボタンが青く光っているときはプレイ中です。
6-3. 保存する
- Ctrl+S(Macは Cmd+S)でシーンを保存します。
チャレンジ課題
StartにDebug.Log("速さは " + speed);と書くと、Console に今の速さが出ます。試してみましょう。(試したら消してOK)new Vector3(input.x, input.y, 0f)をnew Vector3(input.x, 0f, 0f)にすると、どうなるでしょう? 試したら元に戻します。Time.deltaTimeを消すとどうなるか、予想してから試してみましょう。(すごく速くなります。試したら元に戻します)
つまずきポイント
| こんなときは | ここを確認 |
|---|---|
| スクリプトを付けようとすると「クラスが見つからない」と出る | ファイル名とクラス名(public class の後ろ)が同じか。Console に赤いエラーがないか |
| Console に赤いエラーが出る | ; の付けわすれ、{ } の数、全角の文字がまざっていないか。エラーをダブルクリックするとまちがいの行が開く |
| キーを押しても動かない | Game ビューを1回クリックしたか。Player に PlayerController が付いているか。Speed が 0 になっていないか |
NullReferenceException というエラーが出る | FindAction("Move") の Move のつづりが合っているか。Edit > Project Settings > Input System Package で Project-wide Actions に InputSystem_Actions が入っているか |
| コードを変えたのに動きが変わらない | コードエディタで保存したか。Inspector の値が優先されていないか |
まとめ
- Create > Scripting > MonoBehaviour Script でスクリプトを作り、ゲームオブジェクトに付けると動きます。ファイル名とクラス名は同じにします。
Startは最初に1回、Updateは毎フレーム動きます。InputSystem.actions.FindAction("Move")で入力を受け取り、speed * Time.deltaTimeを掛けて動かします。public変数は Inspector で変えられます。プレイ中の変更は止めると元に戻ります。