『Unityの寺子屋 定番スマホゲーム開発入門』「Chapter02 放置ゲームをつくろう」+ 秋葉原Weeyble勉強会 学習記録2

Unityの寺子屋 定番スマホゲーム開発入門

Unityの寺子屋 定番スマホゲーム開発入門

序文

少し遅くなりましたが、前回の秋葉原Weeybleで行われた和尚本の勉強会の内容について軽くまとめておきます。

weeyble-game.connpass.com

進捗

  • Chapter02 放置ゲームをつくろう
    • 2-1 放置ゲームの画面を作ろう
    • 2-2 オーブを産み出そう
    • 2-3 成長する仕組みを組み込む

コード実装部分(一部)

\180715TheTemple\Assets\Scripts\GameManager.cs

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

public class GameManager : MonoBehaviour {
    // 定数定義
    private const int MAX_ORB = 10; // オーブ出現最大数
    private const int PRESPAWN_TIME = 1; // オーブが発生する間隔
    private const int MAX_LEVEL = 2; // 最大レベル

    // オブジェクト参照
    public GameObject orbPrefab;    // オーブプレハブ
    public GameObject smokePrefab; // 煙プレハブ
    public GameObject kusudamaPrefab; // くすだまプレハブ
    public GameObject canvasGame;   // ゲームキャンバス
    public GameObject textScore; // スコアテキスト
    public GameObject imageTemple; // お寺イメージ

    // メンバ変数
    private int score = 0;
    // 次のレベルに必要なスコア
    private int nextScore = 10;
    // 現在表示中のオーブの数
    private int currentOrb = 0;
    // お寺のレベル
    private int templeLevel = 0;
    // 最後にオーブを生成した時間
    private DateTime lastDateTime;
    // レベルアップに必要なスコアの配列(スコアはレベルアップごとにリセットされる)
    private int[] nextScoreTable = new int[] { 10, 50, 100 };

    // Use this for initialization
    void Start () {
        currentOrb = 10; // 現在のオーブ数
        // 初期オーブ生成
        for(int i = 0; i < currentOrb; i++)
            CreateOrb();

        // 初期設定
        lastDateTime = DateTime.UtcNow;
        // 次のレベルに必要なスコア
        nextScore = nextScoreTable[templeLevel];
        // レベルに対応したお寺のイメージをセットする
        imageTemple.GetComponent<TempleManager>().SetTemplePicture(templeLevel);
        // 次のレベルが近づくに連れてScaleを0.5~1.0の間で変化させる
        imageTemple.GetComponent<TempleManager>().SetTempleScale(score, nextScore);
        // スコアテキストを更新する
        RefreshScoreText();
    }

    // 新しいオーブの生成
    public void CreateNewOrb()
    {
        // 最後にオーブを生成した時間を更新する
        lastDateTime = DateTime.UtcNow;
        // 表示中のオーブの数が最大値を超えていたら何もせずにreturnする
        if (currentOrb >= MAX_ORB)
            return;
        // オーブを生成する
        CreateOrb();
        // 表示中のオーブの数を1増やす
        currentOrb++;
    }

    // オーブを生成する
    private void CreateOrb()
    {
        // オーブのプレハブを実体化する
        GameObject orb = (GameObject)Instantiate(orbPrefab);
        // オーブをCanvasGameの子オブジェクトにする
        // 第二引数をfalseにすることで親オブジェクトの影響を受けなくなるっぽい
        // trueにすると親オブジェクトのScale : 0.0078 の逆数であるScale : 128とかいう数値になる
        orb.transform.SetParent(canvasGame.transform, false);
        // ランダムに配置する(RigidBody2Dをアタッチしているので重なったらはじかれる)
        orb.transform.localPosition = new Vector3(
            UnityEngine.Random.Range(-300.0f, 300.0f),
            UnityEngine.Random.Range(-140.0f,-500.0f),
            0f);

        // オーブの種類をランダムに設定する
        // 出現するオーブの種類は0~お寺レベルの間でランダムに出現する
        // Ex.Level0のときは0しか出ない。Level2のときは0,1,2がでる
        int kind = UnityEngine.Random.Range(0, templeLevel + 1);
        switch (kind)
        {
            // 青オーブ(1点)
            case 0:
                orb.GetComponent<OrbManager>().SetKind(OrbManager.ORB_KIND.BLUE);
                break;
            // 緑オーブ(5点)
            case 1:
                orb.GetComponent<OrbManager>().SetKind(OrbManager.ORB_KIND.GREEN);
                break;
            // 紫オーブ(10点)
            case 2:
                orb.GetComponent<OrbManager>().SetKind(OrbManager.ORB_KIND.PURPLE);
                break;
        }
    }

    // オーブを入手した時の処理
    public void GetOrb(int getScore)
    {
        // スコアが次のレベルに必要なスコアに到達していなければ
        if (score < nextScore)
        {
            // スコアを加算
            score += getScore;

            // レベルアップ値を超えないよう制限
            if (score > nextScore)
            {
                score = nextScore;
            }

            // お寺がレベルアップしたか判定
            TempleLevelUp();

            // スコアテキスト更新
            RefreshScoreText();

            // 次のレベルが近づくに連れてScaleを0.5~1.0の間で変化させる
            imageTemple.GetComponent<TempleManager>().SetTempleScale(score, nextScore);

            // ゲームクリア判定
            // スコアが次のレベルに必要なスコアに到達していてかつ最大レベルならクリア(くす玉を表示)
            if ((score == nextScore) && (templeLevel == MAX_LEVEL))
            {
                // くす玉を表示
                ClearEffect();
            }
        }
        // 表示中のオーブの数を減らす
        currentOrb--;
    }

    // スコアテキスト更新
    private void RefreshScoreText()
    {
        textScore.GetComponent<Text>().text = "徳:" + score + " / " + nextScore;
    }

    // お寺のレベルアップを判定する
    void TempleLevelUp()
    {
        // 次のレベルに必要なスコアに到達していれば
        if (score >= nextScore)
        {
            // 最大レベルまで到達していなければ
            if (templeLevel < MAX_LEVEL)
            {
                // レベルアップ
                templeLevel++;
                // スコアは0に戻す
                score = 0;
                // レベルアップエフェクトを表示する
                TempleLevelUpEffect();
                // 次のレベルに必要なスコアを更新する
                nextScore = nextScoreTable[templeLevel];
                // レベルに対応した寺の絵を設定する
                imageTemple.GetComponent<TempleManager>().SetTemplePicture(templeLevel);
            }
        }
    }

    // レベルアップエフェクトを表示する
    private void TempleLevelUpEffect()
    {
        // 煙プレハブを生成する
        GameObject smoke = (GameObject)Instantiate(smokePrefab);
        // 煙プレハブをcanvasGameの子オブジェクトに設定する
        smoke.transform.SetParent(canvasGame.transform, false);

        // Debug.Log("SIBLING");
        // 煙オブジェクトのヒエラルキー内での並び順を2番めに設定する
        // (0番目が背景、1番目が寺、2番目が煙、3番目が木魚、4番目が坊主になる)
        smoke.transform.SetSiblingIndex(2);

        // 煙オブジェクトは0.5秒後に削除する
        Destroy(smoke, 0.5f);
    }

    // くす玉を表示
    void ClearEffect()
    {
        // プレハブからくす玉を生成する
        GameObject kusudama = (GameObject)Instantiate(kusudamaPrefab);
        // canvasGameの子オブジェクトに設定する
        kusudama.transform.SetParent(canvasGame.transform, false);
    }


    // Update is called once per frame
    void Update () {
        // 現在のオーブの表示数が最大数未満なら
        if (currentOrb < MAX_ORB)
        {
            // 最後にオーブを生成した時間との差分を取得して
            TimeSpan timeSpan = DateTime.UtcNow - lastDateTime;
            // 設定した間隔以上経過していれば
            if (timeSpan >= TimeSpan.FromSeconds(PRESPAWN_TIME))
            {
                // 経過時間に対応した数のオーブを生成する
                while(timeSpan >= TimeSpan.FromSeconds(PRESPAWN_TIME))
                {
                    // 新しいオーブを1つ生成する
                    CreateNewOrb();
                    // timeSpanを間隔分減算する
                    timeSpan -= TimeSpan.FromSeconds(PRESPAWN_TIME);
                }
            }
        }
    }
}

実行結果

www.youtube.com

ロゴとかぶってスコアが見えないっていうね

感想

日曜日にやったやつなんで、もう割と忘れちゃってるんですが…

あ、キャンバスのサイズをカメラに合わせる方法がわかったのは大発見でした。
なんで教えてくれなかったんだろー。

割とスクリプトをガンガン書いていかないと間に合わないような分量で、とりあえずコードを全部書いて、あとづけでコメントをどんどんつけていきました。
一応基本的な動作は理解できたつもりですが、C#とかの経験があんまりない人には厳しい内容ですよねぇ。
実際、ほとんどの人は最後までできなかったみたいです。

とりあえず、もうちょっとコード内にコメントを書いてほしいところです。

カロリーメイトください。

BGM

One Life / Zeleive

www.youtube.com