転職を繰り返したサラリーマンの多趣味ブログ

30才未経験でSEに転職した人の多趣味ブログ

【Unity】Coroutine continue failureというエラーの解決法

StopCoroutineでコルーチンを停止させようと実装したら、「Coroutine continue failure」とエラーがでた。
f:id:uuc1h:20210807115211p:plain
で、エラーがでた実装はこんな感じです。

public void GameOver() {

        // リトライボタンとタイトルボタンの表示
        RetryButton.SetActive(true);
        TitleButton.SetActive(true);

        // ブログ用
        StopCoroutine(calculationManager.someCoroutine);

        // ハイスコアのジャッジ
        if (PlayerPrefs.GetInt("HighPingScore", 0) < scoreManager.pingScore) {

            PlayerPrefs.SetInt("HighPingScore", scoreManager.pingScore);

        }

        if (PlayerPrefs.GetInt("HighCalcScore", 0) < scoreManager.rightScore) {

            PlayerPrefs.SetInt("HighCalcScore", scoreManager.rightScore);

        }

    }

色々調べてみると、StopCoroutineの引数に渡しているインスタンスが、外部クラスなことが原因っぽかったです。
なんで、以下のように変更しました。

public void GameOver() {

        // リトライボタンとタイトルボタンの表示
        RetryButton.SetActive(true);
        TitleButton.SetActive(true);

        // 計算のカウントダウンの停止
        calculationManager.StopSomeCoroutine();

        // ハイスコアのジャッジ
        if (PlayerPrefs.GetInt("HighPingScore", 0) < scoreManager.pingScore) {

            PlayerPrefs.SetInt("HighPingScore", scoreManager.pingScore);

        }

        if (PlayerPrefs.GetInt("HighCalcScore", 0) < scoreManager.rightScore) {

            PlayerPrefs.SetInt("HighCalcScore", scoreManager.rightScore);

        }

    }

コルーチンを停止させる動きは、CalculationManagerクラスのStopSomeCoroutineメソッドで行うように修正。で、CalculationManagerクラスのStopSomeCoroutineメソッドは、こんな実装です。

public Coroutine someCoroutine;

public void Init() {

        // カウント開始
        someCoroutine = StartCoroutine(countDownManager.CountDown(false));

    }

public void StopSomeCoroutine() {

        StopCoroutine(someCoroutine);

    }

StopCoroutineに渡す引数は自クラス内で処理するように修正したら、エラーでなくなりました。

【Unity】エディター操作時のみキーボードから操作する方法

今、ブロック崩しゲームを作ってます。スマホでプレイする際は、画面のボタンから操作するけど、Unityエディター時にはキーボードから操作したいっていう場合の実装方法です。
ちなみに作ってるゲームは、こんな感じ。f:id:uuc1h:20210725144707p:plain

この緑色のバーを動かすプログラムがこれです。

if (Application.isEditor) {

        // キーボードの矢印右を操作
        if (Input.GetKeyDown("right")) {

                moveDirection = MOVE_DIR.RIGHT;

        // キーボードの矢印左を操作
        } else if (Input.GetKeyDown("left")) {

                moveDirection = MOVE_DIR.LEFT;

        // キーボードから離した操作
        } else if (Input.GetKeyUp("right") || Input.GetKeyUp("left")) {

                moveDirection = MOVE_DIR.STOP;

        }

}

【Unity】コルーチンの停止方法

Unityの技術書を買うと、コルーチンの使い方は必ずといいほど書かれている。けど、実際にコルーチンを使うときって、ある操作を開始したらコルーチンを止めたい時があるんやけど、小tルーチンの止め方を書いてある本って少ない気がする。

で、コルーチンの止め方はというとStopCoroutineメソッドを使うんやけど、この使い方にハマったんでメモしときます。

private Coroutine coroutine;

void Start() {

    coroutine = StartCoroutine(problemManager.SetProblem(0f));

}

public void OnStopButton() {

    StopCoroutine(coroutine);

}

StartCoroutineには戻り値があって、それを変数に格納。StopCoroutineの引数に、その変数をセットしないとちゃんと動かなかった。
このStartCoroutineに戻り値があるの知らんくって、結構ハマりました。

【Unity】Random.Range()の使い方

ゲームを作っていると乱数を扱うことが多々あります。で、いつも使い方が分からなくなるのがRandom.Range()なんで、ここで改めて整理します。

    // 0〜9が出力される
    int num = Random.Range(0, 10);

    // 0〜10が出力される
    float num = Random.Range(0f, 10f);

引数にfloat型かint型を渡すことで、出力される最大値が変わる。int型は、最大値が出力されない。

【Unity】横向きアプリの設定方法

横向き固定のアプリを作り際のUnityの設定方法です。あっAndroidの場合です。

Project Settings / Player / Resolution and Presentation で、「Landscape Right」、「Landscape Left」にチェックを入れます。
※「Portrait」、「Portrait Upside Down」のチェックは外します。
f:id:uuc1h:20210723140112p:plain

【Unity】子コンポーネントを取得する方法

Unityでゲームを作っていると、ボタンオブジェクトの子コンポーネントにあるテキストオブジェクトの名前を動的に出したいときが出てくる。
例えばRPGでいうと、アイテムを所持していないときは「なし」と表示し、アイテムを拾うと拾ったアイテム名を出したいなどだ。

そういったときは、ボタンオブジェクトにアタッチしたスクリプトから、アイテムの所持品を確認し、そこから子コンポーネントのテキストオブジェクトを取得してテキストを動的に変える方法をとっている。
ソースで表すとこんな感じ。

// アイテムの所持数をチェック
if (playerManager.model.itemBagList.Count >= tagId) {

    // 該当のItemModelを生成
    model = new ItemModel(playerManager.model.itemBagList[tagId - 1]);

    // 該当のアイテム名称を表示
    Text text = this.gameObject.transform.GetChild(0).gameObject.GetComponent<Text>();
    text.text = model.itemName;

} 

コンポーネントを取得しているのは、GetChildメソッドだが引数で渡しているのは、親オブジェクトから見た子コンポーネントの要素だ。
例えば以下のようなオブジェクト構成の場合、Text0オブジェクトを取得するにはGetChild(0)、Text1オブジェクトを取得するにはGetChild(1)を指定する。
f:id:uuc1h:20210523103450p:plain

【Unity】オブジェクトのタグを取得する方法

よくUnityでは各オブジェクトにTagをセットする。プログラム内でこのタグを取得して、何かの判定をするというのはよくある実装。
今作っているゲームで、自オブジェクトのTagを取得して判定するという実装を組みたかったのだが、自オブジェクトのTagの取得方法を知らなかったので、調べたことをメモします。

// 自身のタグDを取得
tagId = int.Parse(this.gameObject.tag);


ちなみに、衝突判定でよく見られる実装で、衝突した相手のtagを取得する実装も載せておく。

private void OnTriggerEnter2D(Collider2D collision) {

    if(collision.gameObject.tag == "Player" || collision.gameObject.tag == "Missile") {

        Destroy(gameObject);

    }

}