【Unity初心者向け】作りながら覚えるゲーム制作講座 #2 スクリプト入門

前回の記事では、Unityでよく使う画面の説明と、実際にオブジェクトを追加して簡単な操作を行いました。
今回は、 自機をキーボードで操作するための前準備として、スクリプトでオブジェクトを移動させてみます!

まず、先に完成形をお見せします。
このように、自動でオブジェクトが右に移動するようにプログラムします。

https://twitter.com/karakuri_colla/status/1357316637884510216?s=20

今回は「変数」という概念を順に理解するため、記事が長くなってしまいましたが、実際にやることはそこまで多くありません。
最終的に追加するプログラムは3行のみです!
実際にプログラムを書いている部分は、ぜひ動画と照らし合わせてご覧ください。

↓この記事の内容は動画でも解説しています↓

では、1つずつやっていきます!

スクリプトファイルを作成

まず、プログラムを書くためのスクリプトファイルを作成します。
前回少し説明した、画面下にある「Project」ウィンドウで行います。

フォルダの選択

左側の階層で Assets フォルダを選択してください。
Assets フォルダの中身が右側に表示されます。

ファイルを作成

右側のところを右クリックして出てくるメニューから、「Create」→「C# Script」を選択してください。

ファイル名を決定

ファイル名の入力モードになりますので、「Player」という名前にして確定してください。

スクリプトをキューブに適用する

このスクリプトでキューブを操作できるようにするには、キューブに対してスクリプトを適用します。
これを「アタッチ」といいます。

スクリプトファイルをキューブにドラッグ&ドロップ

作成した Player スクリプトを選択し、 Hierarchy にあるキューブにドラッグ&ドロップしてください。

これでアタッチが完了です!

確認

アタッチできたかを確認するには、 Hierarchy でキューブを選択した状態で Inspector を一番下までスクロールしてください。
「Player」と書かれた項目が追加されていれば成功です!

スクリプトファイルを開く

実際にプログラムを書いていくためにスクリプトファイルを開きます。
Playerスクリプトをダブルクリックすることで VisualStudio が起動します。

起動しない場合は、 #0 のインストールを確認してみてください。

はじめてのスクリプトを書いてみる

では、いよいよスクリプトを書いていきます!

スクリプトファイルを開くと、デフォルトで StartUpdate という塊があります。
この塊は、Unityが実行する処理の単位だと思ってください。
プログラミング用語では、この塊のことを メソッド と呼びます。

この中に処理を書いていくのですが、まず StartUpdate の役割について簡単に説明しておきます。

Start メソッド

Start は、開始時に1回だけ実行されるメソッドです。
ゲームの初期化処理などを行いたい場合はここに処理を書きます。

Update メソッド

Update は、実行中に毎フレーム実行されるメソッドです。
例えば、60FPSでゲームが動いている場合は1秒間に60回実行されます。
今回の移動処理もここに書いていきます。

Startメソッドは今回使いません

今回のプログラムでは Start メソッドは使わないので、この塊ごと削除しても大丈夫です。
もともと中身が空なので残しておいても問題ありませんが、この記事では消しておきます。

Start メソッドを消した状態のプログラムがこちらです!

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour
{
    // Update is called once per frame
    void Update()
    {
        
    }
}

この状態から始めていきます!
今回は Update メソッド以外の部分は変更しないので、これ以降のプログラムは Update メソッドの部分だけを記載します。

Updateメソッドに処理を追加する

では、試しに Update メソッドの中でCubeの位置を変更してみましょう。
下記のように1行追加してください。
設定する位置は () の中に記入します。

void Update()
{
    transform.localPosition = new Vector3(5, 0, 0);
}

これでゲームを実行してみてください。
Cubeの位置がスクリプトで設定した (5, 0, 0) という座標に移動すれば成功です!

Cubeの位置は InspectorTransform にある Position で確認してください。

もしもエラーが出てうまくいかない場合、打ち間違いの可能性があります。
その場合は #1 で説明した Console ウィンドウを確認してみてください。

エラーが出た場合はConsoleウィンドウで確認を

エラーが発生した場合は Console ウィンドウに赤いアイコンで表示されます。
画像の例は、行の最後にあるセミコロンという記号「;」を打ち忘れた場合に出るエラーです。

C#では、文の終わり(処理の終わり)にセミコロンを打つ必要があります!
慣れないうちは打ち忘れることが多いと思うので、こんな感じのエラーが出たら確認してみてください。

そして、Consoleウィンドウでエラーをダブルクリックすると、VisualStudio上でエラーが出ている箇所にジャンプできます!
また、プログラムの書き方が間違っているときのエラー(コンパイルエラー)の場合はVisualStudio上でもエラー内容が確認できます!

ちなみに、Consoleウィンドウは今後もよく使うので、画面のスペースに余裕がある場合は常に見える位置に置いておくことをオススメします!

初めてのスクリプト まとめ

初めてのスクリプトで、Cubeの位置を設定しました!

しかし、このままではずっと同じ (5, 0, 0) という位置に止まっているだけです。
これを移動させるには、この 5 という値を徐々に変化させていく必要があります。

それには 変数 というものを使います!
まずは変数の使い方を見ていきましょう。

変数を使ってみよう

プログラムで数値を扱うのに欠かせない「変数」という機能について説明します!

変数とは、数値を入れておく箱のようなものです。[1]正確には数値以外を入れる変数も存在しますが、今は気にしないでください。
プログラムで計算した値を保存したり、保存した値を別の計算や処理に活用したりできます。
使い道はいろいろありますが、まずは数値を入れてそれをそのまま使ってみます。

変数を宣言する

変数を使うには、変数に名前を付けて作る必要があります。
これを変数の「宣言」といいます。
ここでは x という名前の変数を宣言してみます。

Update メソッドの外に、「int x;」という行を追加してください。

int x;
void Update()
{
    transform.localPosition = new Vector3(5, 0, 0);
}

x の手前にある int というのは変数の種類です。
これを変数の「型」といいます。
変数は型ごとに入れられる値の種類が決まっていて、
int の場合は整数の値だけを入れることができます。

変数に値を代入する

次に、変数に値を入れてみます。
変数に値を入れることを、値の「代入」といいます。
ここでは 5 という値を入れてみましょう。

int x;
void Update()
{
    x = 5;
    transform.localPosition = new Vector3(5, 0, 0);
}

x = 5」という部分で、変数に値を入れています。
=」は数学では「等しい」という意味ですが、プログラムでは「代入」という意味になります。
つまり、ここでは 「5 を代入」しています。

変数を使う

次に、変数の値を使ってCubeの座標を変更してみます。
ここでは x を使ってX座標を設定します。

int x;
void Update()
{
    x = 5;
    transform.localPosition = new Vector3(x, 0, 0);
}

さっきは 5 という固定の値を入れてましたが、代わりに変数 x を使うようにしてみました。
このように、数値の代わりに変数を使うことができます!

結果は変数を使う前と同じで X座標5 となっているので、変数 x5 が代入できていることが分かりますね。

変数の値を変更する

int の変数には好きな整数の値を入れることができます。[2]正確には -2,147,483,648 ~ 2,147,483,647 という制限がありますが、よほど大きな値を使わなければ大丈夫です。
試しに x の値を好きな値にしてみてください。
ここでは 3 に変えてみます。

int x;
void Update()
{
    x = 3;
    transform.localPosition = new Vector3(x, 0, 0);
}

そうすると、キューブの X 座標に設定される値も 3 に変わります。
このように、同じプログラムでも変数の値を変えることで結果を変えることができます!

変数の値を上書きする

変数は文字通り中身の変更、つまり値を上書きすることができます。
試しに、 x に 3 を入れた後に 4 を入れてみます。
そうすると、最後に入れた 4 がセットされていることが分かります。

int x;
void Update()
{
    x = 3;
    x = 4;
    transform.localPosition = new Vector3(x, 0, 0);
}

変数を初期化する

変数は、作ると同時に値を入れることもできます。
これを「初期化」と言います。
試しに、 x を宣言すると同時に 5 で初期化してみます。
そうすると、ちゃんと 5 がセットされていることが分かります。

int x = 5;
void Update()
{
    transform.localPosition = new Vector3(x, 0, 0);
}

次は x3 で初期化した例です。

int x = 3;
void Update()
{
    transform.localPosition = new Vector3(x, 0, 0);
}

このように、宣言と代入を一気に行うのが初期化です!

四則演算

変数を使えるようになったので、次は数値の四則演算を見ていきます。
演算を行うには、「演算子」という記号を使います。
名前は難しそうですが、意味自体は普段の計算で使っている「+-×÷」と同じです。

加算

加算(足し算)は「+」という演算子を使います。
これは算数や数学と同じですね。
他のプログラムと同様に半角で入れる必要があります。

試しに、変数 x に「5 + 3」の計算結果を代入してみます。

int x;
void Update()
{
    x = 5 + 3;
    transform.localPosition = new Vector3(x, 0, 0);
}

これで、CubeのX座標が 8 になりました!

減算

減算(引き算)は「」という記号を使います。
これも算数や数学と同じですね。

変数 x に「5 – 3」の計算結果を代入してみます。

int x;
void Update()
{
    x = 5 - 3;
    transform.localPosition = new Vector3(x, 0, 0);
}

乗算

乗算(掛け算)は「*」という記号を使います。
これは算数や数学では見慣れない書き方ですね。
半角で × を表す記号が無いので、代わりに * を使っていると考えてください。

変数 x に「5 * 3」の結果を代入してみます。

int x;
void Update()
{
    x = 5 * 3;
    transform.localPosition = new Vector3(x, 0, 0);
}

除算

除算(割り算)は「/」という記号を使います。
これも ÷ とは違う記号ですが、分数を表す線だとイメージすれば覚えやすいのではないでしょうか。

変数 x に「5 / 3」の結果を代入してみます。

なお、算数では「5 ÷ 3」の結果は「1 あまり 2」ですが、
プログラムで整数の割り算を行った場合、余りは無視されます。[3]正確には、余りを求めるための「剰余演算子」という演算子が存在します。使うときに改めて説明します。
つまり、「5 / 3」の結果は単に「1」となります。

int x;
void Update()
{
    x = 5 / 3;
    transform.localPosition = new Vector3(x, 0, 0);
}

四則演算の順番

計算の順番は、実際の算数や数学と同じで、掛け算と割り算を先に計算します。
試しに足し算の後に割り算を書くと、先に割り算の方が計算されます。

次の例では、まず「5 / 3」が先に計算されて「1」になり、その後に「2 + 1」が計算されます。

int x;
void Update()
{
    x = 2 + 5 / 3;
    transform.localPosition = new Vector3(x, 0, 0);
}

また、算数や数学と同じで () で囲むとその部分を先に計算します。
試しに「2 + 5」を先に計算してみます。

int x;
void Update()
{
    x = (2 + 5) / 3;
    
    transform.localPosition = new Vector3(x, 0, 0);
}

変数を含んだ計算

四則演算の中に変数を使うこともできます。
試しに変数 a b を作って、その2つを使って計算してみます。

int a;
int b;
int x;
void Update()
{
    a = 5;
    b = 3;
    x = a + b;
    transform.localPosition = new Vector3(x, 0, 0);
}

変数と定数(普通の数値)を混ぜても大丈夫です。
変数 a b と、定数 1 を使って計算してみます。

int a;
int b;
int x;
void Update()
{
    a = 5;
    b = 3;
    x = a + b + 1;
    transform.localPosition = new Vector3(x, 0, 0);
}

計算結果を自分自身に代入する

変数を使った計算結果を、自分自身に代入することもできます。
次の例では、「x + 3」の計算結果を x自身 に代入しています。
つまり、「5 + 3」の計算結果の 8 が入ります!

int x;
void Update()
{
    x = 5;
    x = x + 3;
    transform.localPosition = new Vector3(x, 0, 0);
}

この「x = x + 3」という表記は、数学では「x と x + 3 が等しい」という意味なので、最初は違和感を感じるかもしれません。
しかし、プログラムでは「x + 3 を計算した結果を x に代入する」という意味なので、こういった書き方も可能なのです!

加算代入演算子

そして、「x = x + 〇」という形は実際のプログラムではよく使うので、簡略化して書く方法があります。
それが「x += 〇」という書き方です。

int x;
void Update()
{
    x = 5;
    x += 3;
    transform.localPosition = new Vector3(x, 0, 0);
}

この「+=」は加算と代入を同時に行う演算子なので、文字通り「加算代入演算子」といいます。
減算、乗算、除算にも同様の演算子が存在します。

小数を使う

今までは、 53 などの整数のみを扱いました。
次に、 5.5 などの小数を扱ってみます。

小数の書き方

小数は、5.5 のように小数点を使って数値を書いた後、末尾に f をつけてください。[4]正確には f をつけずに 5.5 と書くだけでも小数として扱うパターンもあるのですが、それは今度説明します。
5.5 の場合は 5.5f と表記します。
試しに座標設定を小数で行ってみます。

void Update()
{
    transform.localPosition = new Vector3(5.5f, 0, 0);
}

小数の変数

小数を入れるための変数もあります。
int のかわりに float と書くと、小数を入れるための変数になります。

宣言と代入

float 型の変数 x を宣言して、 5.5 を代入してみます。
そしてそれを座標設定に使ってみます。

float x;
void Update()
{
    x = 5.5f;
    transform.localPosition = new Vector3(x, 0, 0);
}

四則演算

小数の四則演算も整数と同様の演算子で行えます。

float x;
void Update()
{
    x = 5.5f + 3.3f;
    transform.localPosition = new Vector3(x, 0, 0);
}

基本的に整数と同じですが、割り算だけは整数の時と少し違います。
小数の割り算は整数と違って余りが存在しません。

次の例では小数で 5 ÷ 3 を計算していて、結果は 1.666667 になります。
5 / 3 ではなく 5.0f / 3.0f と表記しているのがポイントです。

float x;
void Update()
{
    x = 5.0f / 3.0f;
    transform.localPosition = new Vector3(x, 0, 0);
}

本当は 5 ÷ 3 を小数で計算すると、 1.666666… と無限に続きます。
しかし、プログラムでは小数点以下の細かすぎる部分には誤差が出ます。
このあたりは後々説明しますので、今は気にしなくても大丈夫です。

オブジェクトを右に移動させる

では、いよいよ変数を使ってオブジェクトを移動させてみます!
座標は小数で扱うので、 float 型の変数を使います。

変数でオブジェクトの座標を加算していく

float 型の x という変数を作って、 0.0 で初期化します。
これを 3.0 ずつ増やしていき、それを使って座標を設定します。
X軸は右方向がプラスなので、これでオブジェクトが右に移動するはずです。

float x = 0.0f;
void Update()
{
    x = x + 3.0f;
    transform.localPosition = new Vector3(x, 0, 0);
}

実際に実行してみてください。
オブジェクトが右に移動しましたね!

ただ、移動が速すぎますね…
環境によっては速すぎて消えたように見えてしまったかもしれません。

移動が速すぎた理由

実は、 Update メソッドは1フレームに1回実行されるので、この処理だと毎フレーム 3.0 ずつ移動してしまっています。
仮に60FPSでゲームが動いてるとすると、1秒で180も移動してしまっている計算になります。
なので、うまく1秒間に3だけ移動するように修正します。

ここで、速度と時間から距離を求める公式を使います。

距離 = 速度 × 時間

まず、速度は1秒間に移動する距離なので 3.0 です。
次に、時間は前のフレームから何秒経過したかです。
Unityでは Time.deltaTime と書けば前フレームからの経過時間を取ることができます。
つまり、「距離 = 3.0 × Time.deltaTime」となります!
これをプログラムに当てはめてみます。

float x = 0.0f;
void Update()
{
    x = x + 3.0f * Time.deltaTime;
    transform.localPosition = new Vector3(x, 0, 0);
}

これで再度実行してみてください。
今度こそ、ちゃんと1秒間に3.0右に移動するはずです!

「+=」を使って式を簡略化する

先ほど、「x = x + ○○」という形は「x += ○○」と簡略化もできると説明しましたが、
丁度いいのでここも += という演算子に置き換えてみます。

float x = 0.0f;
void Update()
{
    x += 3.0f * Time.deltaTime;
    transform.localPosition = new Vector3(x, 0, 0);
}

まとめ

お疲れさまでした。
今回は、スクリプトを書いてオブジェクトが移動するようにしました。

次回は、プレイヤーがキーボードを押した方向に自機が移動するようにします!
自機が移動できるようになると徐々にゲームっぽさが出てきます!

脚注

1 正確には数値以外を入れる変数も存在しますが、今は気にしないでください。
2 正確には -2,147,483,648 ~ 2,147,483,647 という制限がありますが、よほど大きな値を使わなければ大丈夫です。
3 正確には、余りを求めるための「剰余演算子」という演算子が存在します。使うときに改めて説明します。
4 正確には f をつけずに 5.5 と書くだけでも小数として扱うパターンもあるのですが、それは今度説明します。