Developer

【初心者Unity】懐かしのゲームを作ってみよう!③
2021.10.01
Lv1

【初心者Unity】懐かしのゲームを作ってみよう!③


はじめに

今回は前回に引き続き、↓のゲームを作っていきます。

前回はBallを動かすところまで行きました。
今回は画面の際まで来たBallを跳ね返らせる処理を実装します。
いよいよBallが一時的に完成しますね。。。
それでは早速作りましょう!


第2段階:ボールを作成しよう!(3)

下記、前回までのスクリプトになります。

public class BallScript : MonoBehaviour
{
    Vector2 pos;
    // Start is called before the first frame update
    void Start()
    {
        pos = transform.position;
    }

    // Update is called once per frame
    void Update()
    {
        //斜め45度に進ませる
        Move();

        //右端に着いた時の処理
        if (IsRightEdge())
        {
            //何かの処理
        }

        //左端に着いた時の処理
        if (IsLeftEdge())
        {
            //何かの処理
        }

        //上端に着いた時の処理
        if (IsUpperEdge())
        {
            //何かの処理
        }

        //下端に着いた時の処理
        if (IsLowerEdge())
        {
            //何かの処理
        }
    }

    void Move()
    {
        pos.x += 0.03f;
        pos.y += 0.03f;
        transform.position = pos;
    }

    bool IsRightEdge()
    {
        //一時的に「false」にしてるだけ後で処理書く
        return false;
    }

    bool IsLeftEdge()
    {
        //一時的に「false」にしてるだけ後で処理書く
        return false;
    }

    bool IsUpperEdge()
    {
        //一時的に「false」にしてるだけ後で処理書く
        return false;
    }

    bool IsLowerEdge()
    {
        //一時的に「false」にしてるだけ後で処理書く
        return false;
    }
}

今回は、このスクリプトの内、Ballが画面の際に来たことを判定するIs~Edge()メソッド4つを完成させ、Update()メソッド内のif文の中に実際の処理を書くという2つのタスクがあります。
まず、Is~Edge()メソッドです。このメソッドは4つもありますが、まずはIsRightEdge()メソッドを完成させてから、残りの3つのメソッドにもその方針を適用しましょう。
IsRightEdge()メソッドは、Ballが画面の右端に来たことを判定するメソッドです。
「右端」という表現から、Ballのx座標が関係していることが読み取れます。
スタートボタンを押してから、Ballのx座標はどんどん増加していきます。そしてある地点に到達、そして超えたときに「Ballは右端に来た」と言えます。
そこで、↓の写真の様にInspectorタブ上で数字を操作し、Gameタブ上のBallを見て、xの値がいくつの時に右端になるのかを実験します。

そして実験の結果、右端はx = 2.5(くらい)であるということが分かりました。(ただこの値は画面サイズによって異なるのでみなさん各自で値の確認をしましょう)
次に、この値を基に実際にIsRightEdge()メソッドを完成させます。
とはいっても簡単で、xが2.5より大きければ右端だという意味でtrue。2.5以下であれば右端ではないという意味でfalseを返せばよいだけなので、IsRightEdge()メソッドは以下の様になります。

    bool IsRightEdge()
    {
        return pos.x > 2.5;
    }

このメソッドが完成したと同時に、IsLeftEdge()メソッドも作れてしまいますね。
なぜなら0から見て2.5の正反対の場所が左端ですからね、おのずとx = -2.5が左端であることはわかるのではないでしょうか?
したがって、IsLeftEdge()メソッドは以下の様になります。

    bool IsLeftEdge()
    {
        return pos.x < -2.5;
    }

上の2つのメソッドと同様に進めていけばIsUpperEdge()メソッドもIsLowerEdge()メソッドも簡単に作成できます。
まずはIsUpperEdge()メソッドですが、IsRightEdge()メソッド同様、↓の写真の様に上の際を見定めます。

実験の結果、上の端はy = 5であるということが分かったので、これを基にIsUpperEdge()メソッドを以下の様に完成させます。

    bool IsUpperEdge()
    {
        return pos.y > 5;
    }

最後に、IsLowerEdge()メソッドを作成します。
IsUpperEdge()メソッドの値より、y = -5が下の際であるということが分かるので、IsLowerEdge()メソッドは下の様になります。

    bool IsLowerEdge()
    {
        return pos.y < -5;
    }

以上でIs~Edge()メソッドは全て完成しました。
ここまでのスクリプトをまとめると以下の様になります。

public class BallScript : MonoBehaviour
{
    Vector2 pos;
    // Start is called before the first frame update
    void Start()
    {
        pos = transform.position;
    }

    // Update is called once per frame
    void Update()
    {
        //斜め45度に進ませる
        Move();

        //右端に着いた時の処理
        if (IsRightEdge())
        {
            //何かの処理
        }

        //左端に着いた時の処理
        if (IsLeftEdge())
        {
            //何かの処理
        }

        //上端に着いた時の処理
        if (IsUpperEdge())
        {
            //何かの処理
        }

        //下端に着いた時の処理
        if (IsLowerEdge())
        {
            //何かの処理
        }
    }

    void Move()
    {
        pos.x += 0.03f;
        pos.y += 0.03f;
        transform.position = pos;
    }

    bool IsRightEdge()
    {
        return pos.x > 2.5;
    }
    
    bool IsLeftEdge()
    {
        return pos.x < -2.5;
    }
    
    bool IsUpperEdge()
    {
        return pos.y > 5;
    }
    
    bool IsLowerEdge()
    {
        return pos.y < -5;
    }
}

次に、それぞれの端にBallが来たらどの様な処理をさせるか考えていきましょう。
まず、Ballが右端に来た場合ですが、動きの変化として座標に着目すると、y座標の増加に変化はありません。
しかし、x座標だけ、増加していたものが右端に来ると減少させなければなりません。
何言ってるかよくわからない方は↓の写真とにらめっこしながら上の文を再度読んでみてください(笑)

したがって、それまで「+」だった増加量を「-」にすれば良いのですね!
これを実現するためにMove()メソッドのx軸を増加させる式に変数「directionX」を掛けます。
このdirectionXは初期値を1とします。そのため、これまで通りの動きをします。
しかし、右端に来た時にはこのdirectionXの値を-1に変更します。
するとどうでしょう。見事にBallが進行方向を反対にするのではないでしょうか?
反対に、左端に到達した際にはこのdirectionXの値を1に戻してあげましょう。そうすれば元の様に右に進んでいくのではないでしょうか?
以上の設計を実現したスクリプトが以下の様になります。

public class BallScript : MonoBehaviour
{
    Vector2 pos;
    int directionX;
    // Start is called before the first frame update
    void Start()
    {
        pos = transform.position;
        directionX = 1;
    }

    // Update is called once per frame
    void Update()
    {
        //斜め45度に進ませる
        Move();

        //右端に着いた時の処理
        if (IsRightEdge())
        {
            directionX = -1;
        }

        //左端に着いた時の処理
        if (IsLeftEdge())
        {
            directionX = 1;
        }

        //上端に着いた時の処理
        if (IsUpperEdge())
        {
            //何かの処理
        }

        //下端に着いた時の処理
        if (IsLowerEdge())
        {
            //何かの処理
        }
    }

    void Move()
    {
        pos.x += 0.03f * directionX;
        pos.y += 0.03f;
        transform.position = pos;
    }

    bool IsRightEdge()
    {
        return pos.x > 2.5;
    }
    
    bool IsLeftEdge()
    {
        return pos.x < -2.5;
    }
    
    bool IsUpperEdge()
    {
        return pos.y > 5;
    }
    
    bool IsLowerEdge()
    {
        return pos.y < -5;
    }
}

これで、右端、左端にBallが到達した時の処理は完成です。
次に、それぞれの上の端と下の端にBallが来たらどの様な処理をさせるか考えていきましょう。
先ほどの左右の端と同様に考えると、まず、Ballが上端に来た場合には動きの変化としてx座標の増加に変化はありませんが、y座標には変化を及ぼします。
yの増加量の符号を反転させるためにMove()メソッドのy軸を増加させる式に変数「directionY」を掛けます。
このdirectionYは初期値を1とします。そのため、これまで通りの動きをします。
しかし、上端に来た時にはこのdirectionYの値を-1に変更します。
すると、Ballは進行方向を反対にします。
反対に、下端に到達した際にはこのdirectionYの値を1に戻します。そうすれば元の様に上に進んでいきます。
以上の設計を実現したスクリプトが以下の様になります。

public class BallScript : MonoBehaviour
{
    Vector2 pos;
    int directionX;
    int directionY;
    // Start is called before the first frame update
    void Start()
    {
        pos = transform.position;
        directionX = 1;
        directionY = 1;
    }

    // Update is called once per frame
    void Update()
    {
        //斜め45度に進ませる
        Move();

        //右端に着いた時の処理
        if (IsRightEdge())
        {
            directionX = -1;
        }

        //左端に着いた時の処理
        if (IsLeftEdge())
        {
            directionX = 1;
        }

        //上端に着いた時の処理
        if (IsUpperEdge())
        {
            directionY = -1;
        }

        //下端に着いた時の処理
        if (IsLowerEdge())
        {
            directionY = 1;
        }
    }

    void Move()
    {
        pos.x += 0.03f * directionX;
        pos.y += 0.03f * directionY;
        transform.position = pos;
    }

    bool IsRightEdge()
    {
        return pos.x > 2.5;
    }
    
    bool IsLeftEdge()
    {
        return pos.x < -2.5;
    }
    
    bool IsUpperEdge()
    {
        return pos.y > 5;
    }
    
    bool IsLowerEdge()
    {
        return pos.y < -5;
    }
}

これにて完成です!
皆さん早速スタートボタンを押してみてください。
↓の様にBallが跳ね返りながら飛びまわる姿を見ることができたのではないでしょうか?


おわりに

3回の記事を経てようやくBallが一段落着きました。。。
いかがでしょう?時間はかかりましたが、その分、プログラムを書く際にどの様な思考をしてどの様な方針で進めれば良いかが実感できたのではないでしょうか?
次回はいよいよBall以外のオブジェクトであるPaddleが登場します。
プログラミングはBallに比べそんなに難しくありませんが、Ballとの衝突が生まれるため、衝突判定の知識が必要になってきます。
しかし、今回の3記事の様にゆっくり丁寧に実装していきますのでご安心ください。
乞うご期待!

 


連載目次リンク

「初心者のための」Unityゲーム制作 目次

Unity実践編 - 目次リンク

実践Unityゲームプログラミング 連載目次