ひつじを動かそう のバックアップ差分(No.20)


  • 追加された行はこの色です。
  • 削除された行はこの色です。
#contents
*はじめに [#x7454d9b]
[[プロジェクトを作成しよう]]の続きです。
#br
「[[プロジェクトの作成]]」では重力操作や当たり判定などの簡単な物理演算による操作を勉強しました。
「[[プロジェクトを作成しよう]]」では重力操作や当たり判定などの簡単な物理演算による操作を勉強しました。
しかし、さらに複雑な操作をしようと思うとプログラミングでの操作が必要になります。
そこで、このページではUnity上でのC#のプログラミングの基本を勉強します。
#br
今回は
 1. ひつじを移動させる
 2. 徐々に移動させる
 3. スピードを調整できるようにする
 4. キー入力で操作できるようにする
の4つをステップごとに実装して、C#を学んでいきます。
#br
*ひつじをC#で動かす [#a2e972d3]
C#のソースコードは、他の重力操作や当たり判定などと同様にコンポーネントとして追加することができます。
C# のソースコードのファイルをコンポーネントとしてひつじにつけましょう。
C#のソースコードは、他の重力操作や当たり判定などと同様に&color(,#FBB){コンポーネントとして追加することができます};。
C# のソースコードのファイルをコンポーネントとしてひつじにつけてみましょう。
AddComponent > NewScript を押し、「move_seep」と入力してください。
すると、プロジェクトのアセットに「move_seep.cs」というのが追加されました。
#br
画像
#br
これをダブルクリックします。
#br
#geshi(csharp,number){{
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MoveSheep : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
    }

    // Update is called once per frame
    void Update()
    {
    }
}
}}

#br
エディターが開いて、このようなファイルが出てきたと思います。
これがデフォルトのC#のソースコードになります。
初めて見る人には、何が何だかわからないと思いまが、少しづつ勉強していきましょう。
C#の基本的な構文に関しては[[ここ>C#の基本構文]]で勉強できます。
#br
**1. ひつじを移動させる [#o72a7874]
#br
では、ここにいろいろ書き足して、実際にひつじを動かしてみましょう。
#br
#geshi(csharp,number){{
// 省略
    void Start()
    {
        // ここから書いていく
        Vector3 pos = this.transform.position; // このオブジェクト(ひつじ)の位置を取得
        Vector3 pos = this.transform.position; // このオブジェクト(ひつじ)の位置を変数として取得

        pos.x = 3; // x座標を変更
        pos.y = 4; // y座標を変更

        this.transform.position = pos; // 変更の更新
        this.transform.position = pos; // 変数を代入
    }
// 省略
}}
#br
「void Start()」 の後に続く {} の中に上の通りに書き込んでください。
「//」から後は書かなくても大丈夫です。
(「//」より後は''コメントアウト''といって、プログラムとして読み込まれなくなります)
#br
少し説明すると、ここでは''関数の定義''というのを行っています。
''関数''とは、簡単にいうと&color(,#FBB){一連の命令をまとめたもの};です。
「void」というのが戻り値の型で、「Start」というのが関数の名前です。
「()」は、今回は空欄ですが引数を入れます。
「()」は、関数定義をする際に必要な記号です。
(「()」にも役割があるのですが、今回は割愛します。細かい関数に関する話はまた今度!)
関数を定義する際は必ずその関数の呼び出し元に返す値として''戻り値''というものを指定する必要があり、
その値の型を定義の際に宣言しなければなりません。
ただし、今回は戻り値が必要ありません。
その場合は値を返さないことを指定するために、&color(,#FBB){戻り値の型として「void」を使用};します。
(引数等の関数に関する話はまた今度!)
""型""というワードが出ましたが、型というのは&color(,#FBB){値(データ)の種類のこと};です。
整数を入れる整数型、文字列を入れる文字列型やデータの集合を入れる配列型などがあり、C#ではこの型というのをその都度指定して書く必要があります。
#br
「''void Start()''」は、&color(,FBB){そのオブジェクトがゲームに出現したときに一番初めに一度だけ呼び出される関数};です。
今回ひつじは、初めからゲームに出現しているので、ゲームを起動するとすぐに「void Start()」の中身の命令(後に続く {} の中の命令)が実行されます。
#br
命令の中身を見ていくと、1行目は「このオブジェクトの位置を『Vector3』という型の『pos』という名前を持つ変数に代入する」というものです。
命令の中身を見ていくと、1行目は「『Vector3』という型の『pos』という名前を持つ変数にこのオブジェクトの位置を代入する」というものです。
「''=''」は、C#では&color(,#FBB){「左辺に右辺を代入する」といった意味};で使われます。
「''Vector3''」とは三次元ベクトルを扱う型になります。
ひつじ位置は(0,0,0)ですので「pos」には(0,0,0)が代入されたことになります。
2、3行目は「その変数のxy座標を(3,4)にする」、4行目は「このオブジェクトの位置を、新しい変数で更新する」といったものになります。
つまり2,3行目で「pos」が(3,4,0)になり、4行目でひつじの位置も(3,4,0)に更新されます。
2、3行目は「その変数のxy座標を(3,4)にする」、4行目は「このオブジェクトの位置を、新しい変数で代入する」といったものになります。
つまり2,3行目で「pos」が(3,4,0)になり、4行目でひつじの位置も(3,4,0)に変更されます。
#br
まとめると、「ゲームが開始されてすぐに一度だけ、ひつじの位置が(0,0,0)から(3,4,0)に変わる」という命令になります。
以上の命令をまとめると、「ゲームが開始されてすぐに一度だけ、ひつじの位置が(0,0,0)から(3,4,0)に変わる」という命令になります。
#br
実際に動かしてみましょう。
ファイルの変更を保存して、エディターを閉じ、ゲームを再生してみると、
ひつじは右上に移動したと思います。
#br
**2. 少しずつ動す [#q3f2dde7]
**2. 少しずつ動かす [#q3f2dde7]
#br
これだと、一瞬での移動になってしまいます。
しかし、多くのゲームでは少しづつ移動していくことが多いです。
ひつじは移動できましたが、これだと一瞬での移動になってしまいます。
しかし、多くのゲームでは瞬間での移動より少しづつ移動していくことが多いかと思います。
ということで次は、少しずつ移動できるように改良してみましょう。
#br
#geshi(csharp,number){{
// 省略
    // Start is called before the first frame update
    void Start()
    { 
// 全部消す
    }

    // Update is called once per frame
    void Update()
    { 
        // ここから書いていく
        Vector3 pos = this.transform.position; // このオブジェクト(ひつじ)の位置を取得
        Vector3 pos = this.transform.position; // このオブジェクト(ひつじ)の位置を変数として取得

        pos.x += 0.01f; // x座標を変更
        pos.y += 0.01f; // y座標を変更

        this.transform.position = pos; // 変更を更新
        this.transform.position = pos; // 変数を代入
    }
}
}}
#br
次は、一旦「void Start()」の中身を消して、「void Update()」の中身を上のように変えてください。
#br
「''void Update()''」は&color(,#FBB){そのオブジェクトがゲームに出現してから毎フレーム呼び出される関数};です。
''フレーム''とは、アニメーションのコマ割り、パラパラ漫画のようなもので、ようは、&color(,#FBB){1つの静止画を表示させてから、次の静止画を表示するまでの間隔};のことを言います。
先ほどと同様、ひつじは最初からいますので、ゲームが開始したら毎フレームで「void Update()」の中身が実行されます。
''フレーム''とは、アニメーションのコマ割り、パラパラ漫画の一コマのようなもので、ようは、&color(,#FBB){1つの静止画を表示させてから、次の静止画を表示するまでの間隔};のことを言います。
先ほどと同様ひつじは最初からいますので、ゲームが開始したら毎フレームで「void Update()」の中身が実行されます。
中身についてみていくと、1行目と4行目はさっきと同じですね。
変わったのは2、3行目で、「現在の変数のxy座標にそれぞれ0.01足す」というものです。
ちなみに、数値の後にある"f"は数値が''float型''(少数の型)であることを識別するためにつけています。
ちなみに、数値の後にある「f」は数値が''float型''(小数の型)であることを識別するためにつけます。(&color(,#FBB){小数を扱う際は必ずつけます};)
#br
まとめると、「ゲームが開始してから毎フレームごとに、xy座標がそれぞれ0.01ずつ増えていく」となります。
#br
実際動かしてみると、少しずつ右上に移動するようになるかと思います。
#br
**3. スピード調節をする [#r264312f]
#br
今は、ひつじのスピードの係数は0.01で固定ですね。
ゲームによっては「これより早くしたい、遅くしたい」ということが多々あると思うます。
今は、ひつじのスピードの係数(毎フレームに加算される数値の大きさ)は0.01で固定ですが、
ゲームによっては「これより早くしたい、遅くしたい」ということが多々あると思います。
しかし、調整のために毎回ソースコードを書き換えるのは手間かと思います。
そこで、スピードをインスペクターから自由に調節できるように改良してみましょう。
#br
#geshi(csharp,number){{
// 省略
    //ここに書き加える
    public float speed = 0.01f; // 初期値付きで変数を定義

    // Start is called before the first frame update
    void Start()
    {
    }

    // Update is called once per frame
    void Update()
    { 
        Vector3 pos = this.transform.position;

        pos.x += speed; //0.01f から speed に書き換え 
        pos.y += speed; //0.01f から speed に書き換え 

        this.transform.position = pos;
    }
}
}}
#br
「void Start()」の上と、「void Update()」の中身をこのように変えます。
#br
3行目では、''変数の定義''をしています。
変数は、&color(,#FBB){データを保存しておく入れ物のようなもの};です。
変数の定義では、&color(,#FBB){その変数の型と名前を宣言する必要};があります。
今回はfloat型(小数を扱う型)として「speed」という名前の変数を定義します。
また、初期値を代入の形で指定することができます。(指定がない場合はそれぞれの型に設定されたデフォルトの値が入ります。)
今回は予め0.01fを初期値として入れておきます。
ところで、前にある「public」は、&color(,#FBB){UnityEditerのインスペクターや他のスクリプトからspeedの値を変更できるようになる合言葉のようなもの};です。(クラスの直下の{}記号の場所でだけ付けます。)
詳しい話は今度しますが、ここではこのように覚えておいてください。
変数の宣言場所に関してですが、基本的にどこでもできます。(もちろん例外はありますが。)
ですが、その変数を利用できる範囲は&color(,#FBB){宣言した場所を含む直下の{}記号の内側だけ};です。
そのため、その変数の使用する範囲を考えて変数を宣言する必要があります。
今回の場合は、このクラスの外部(Unityエンジンのインスペクター)からの利用があるため一番外側に書きました。
#br
14,15行目では、数値を変数に置き換えています。
こうすることで、これまでは0.01で固定だったものがspeedに入れる数値を変えることで変えられるようになりました。
#br
実際にひつじのインスペクターからspeedの数値を変えて、ゲームを開始してみましょう。
ひつじのスピードは変わったでしょうか。
#br
**4. キー入力で操作できるようにする [#s2a580b5]
#br
今のままでは、ずっと同じ方向に行くばかりです。
しかし、ゲームではプレイヤーの操作(キーボードやマウスなどの入力)による操作が必要不可欠です。
そこで、次はひつじをキー入力で操作できるようにします。
#br
#geshi(csharp,number){{
// 省略
    // Update is called once per frame
    void Update()
    { 
        Vector3 pos = this.transform.position;

        //pos.x += speed; ->消す
        //pos.y += speed; ->消す

        //ここから編集
        if (Input.GetKey(KeyCode.D)) // Dキーの入力があったら
        {
            pos.x += speed; // x座標に speed 分だけ加算
        }

        if (Input.GetKey(KeyCode.A)) // Aキーの入力があったら
        {
            pos.x -= speed; // x座標に speed 分だけ減算
        }

        this.transform.position = pos;
    }
}
}}
#br
これまでは、Update関数が呼び出されるたびに無条件で「pos」を増加させてきましたが、
今回は「特定のキーが入力されたら」という条件が満たされていれば「pos」を変化させる、という風に命令の実行に条件を設けたいわけです。
そこで使われるのが''if文''になります。
if文の書き方は、
#geshi(csharp,number){{
if (条件文) 
{
命令文
}
}}
と、なっています。
&color(,#FBB){条件文が満たされていれば(条件文の戻り値が「true」であれば){}の中の命令文が実行};され、
&color(,#FBB){条件文が満たされていなければ(条件文の戻り値が「false」であれば){}の中の命令文は無視};されるようになっています。
&color(,#FBB){条件文が満たされていれば(条件文の結果が「真」であれば){}の中の命令文が実行};され、
&color(,#FBB){条件文が満たされていなければ(条件文の結果が「偽」であれば){}の中の命令文は無視};されるようになっています。
「真」「偽」と表現しましたが、コードの中ではそれぞれ ''true'' 、''false'' という値で扱います。
この二値は''bool型''と呼ばれる型で保存される値(bool型は true 、falseのみを扱う型)で、
if分を始め&color(,#FBB){条件判定の際に頻繁に使われます};。
(以後、「真」を true、「偽」を false として表記します)
#br
今回の例を見ていくと、
「Input.GetKey (KeyCode.D)」というのが、Dキーが入力されれば「true」、されていなければ「false」が返されるため、
Dキーを押していると、"pos"のx座標が"speed"の大きさ分増えるようになり、
「Input.GetKey (KeyCode.A)」というのが、Aキーが入力されれば「true」、されていなければ「false」が返されるため、
「Input.GetKey (KeyCode.D)」というのが、Dキーが入力されれば true 、されていなければ false が返されるため、
Dキーを押していると、「pos」のx座標が「speed」の大きさ分増えるようになり、
「Input.GetKey (KeyCode.A)」というのが、Aキーが入力されれば true 、されていなければ false が返されるため、
Aキーを押していると、「pos」のx座標が「speed」の大きさ分減るようになります。
何もキーを押していないと、どちらのif文の条件式も満たされないので、「pos」の値は変化しないことになります。
#br
これを実行してみると、
ひつじはDキーを押している間は右に、Aキーを押している間は左に移動して、何も押していないと動かないようになったはずです。
(「speed」が正の数の時。負の数の時は左右逆に。インスペクターから正の数に直そう!)
(ただし「speed」が正の数の時だけ。負の数の時は左右逆に。インスペクターから正の数に直そう!)