質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.91%

Unity(C#)のIEnumeratorを使って同時に2種類の動作を実現したい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 2,619

Yamaimo_Misoni

score 11

前提・実現したいこと

Unity5.5.1(C#)を使ってアプリを作っています。
Update()内で同時に2種類の動作を実現するため、IEnumeratorを使い、コルーチン(マイクロスレッド?)を実装したいのですが、うまくいっていません。
IEnumeratorの使い方をお教えいただけると幸いです。

発生している問題・エラーメッセージ

エラーメッセージは1フレームに1回出ているようです。

NullReferenceException
UnityEngine.MonoBehaviour.StartCoroutine (IEnumerator routine) (at C:/buildslave/unity/build/artifacts/generated/common/runtime/MonoBehaviourBindings.gen.cs:54)
Manager.Update () (at Assets/Scripts/Manager.cs:80)


Manager.csの80行目には下記ソースの
StartCoroutine(panelChange());
が書かれています。

該当のソースコード

    int loop = 0;
    public void Update() {
        if(loop == 0) {
            StartCoroutine(secondTask());
        }
        ……他の処理……
        loop++;
    }

    IEnumerator secondTask() {
        while (true) {
            //ここに他の処理が書きたい
            yield return null;
        }
    }

試したこと

secondTaskを一度呼べばいいと思ったので、UpdateではなくStart内で始める手も試しましたが、同様にエラーが発生しました。

追記

更に調べてみたところ、どうやらこのScriptをGameObjectにアタッチせず、他のScript(こちらはアタッチされている)からnewで呼び出しているのが原因かもしれないとわかってきました。
しかし、このScriptは引数を持つのですが、単純に新しいGameObjectをつくり、AddComponentでアタッチするのでは引数が渡せません。

質問内容は異なりますが、こちらの方法を試してみるため、適切なやり方を教えていただけないでしょうか。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

Manager.cs内でStartCoroutine(panelChange());している
とありますが、これだと
「Manager.cs内のpanelChangeメソッド」を呼ぼうとします。
Manager.cs内にpanelChangeメソッドが無い場合、当然エラーを返します。

もし「該当のソースコード」に当たるCSファイルが別にあり、そのメソッドを呼ぼうとしているならば
StartCoroutine(該当のソースコードクラスのインスタンス.panelChange());
のような形にしないと呼び出されません。
(「該当のソースコード」に当たるCS内にpanelChangeメソッドが存在する必要があります)
(ここが解決されればStart内でも呼べるはずです)

何をしたいのかよく分かりませんが、
AddComponentでアタッチしたスクリプトへ変数を渡したいなら、以下の方法で可能です

//呼び出し側(Manager.cs)----------------------
void CallHoge () {
    Hoge hoge = gameObject.AddComponent( typeof(Hoge) ) as Hoge;
    hoge.aaa = 1;    //public変数に入れてから
    hoge.DoAAA();    //メソッドを呼び出すとか
    hoge.DoBBB (2);    //メソッドで引数を渡せるようにするとか
}

//呼び出され側(Hoge.cs)------------------------
public int aaa = 0;

public void DoAAA() {
    Debug.Log(aaa);
    //渡された変数を使った処理
}

public void DoBBB (int num) {
    Debug.Log(num);
    //渡された変数を使った処理
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/04/03 10:46

    オブジェクトにアタッチされているMain.csがあり、
    Main.csでまず
    Manager manager = new Manager(**ここにコンストラクタの引数を入れている**);
    としておいてコンストラクタを呼び出し、
    Main.csのUpdateにおいて
    manager.Update();
    とすることで擬似的にUpdateを実現しています。
    実際にはManager1,Manager2,…とManagerがたくさんあり、これを切り替えつつ動かしたいと思ったので、このような形にしていました。
    警告として
    You are trying to create a MonoBehaviour using the 'new' keyword. This is not allowed. MonoBehaviours can only be added using AddComponent(). Alternatively, your script can inherit from ScriptableObject or no base class at all
    と出ていましたが(ManagerはMonoBehaviorを継承しています)、動作はしていたのでそのままにしていました。
    しかし、Manager.csの(擬似的な)Update内で上のようなIEnumeratorを呼ぼうとすると、NullReferenceExceptionでエラーが出た……という結果です。

    キャンセル

  • 2017/04/03 11:12

    警告にある通り、MonoBehaviorを継承しているクラスはnewできません。
    つまりmanagerはインスタンスされていない状態になります。
    (この状態でそもそも何故Manager.csのUpdateが呼ばれているのが不思議ではありますが)

    恐らくですが、StartCoroutineやIEnumeratorはMonoBehaviorに依存するメソッドなので、
    MonoBehaviorとしてインスタンスされていない=IEnumeratorメソッドが存在しない
    扱いになるのではないかと思います。

    なので警告にある通り、大人しくAddComponentするか、Main.cs内で動作させる方法を考えた方がいいです。

    キャンセル

  • 2017/04/03 13:49

    AddComponentしてうまく動くような道を探ろうと思います。
    多くの質問にお付き合い頂き、ありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.91%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る