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

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

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

4299閲覧

【Unity】コルーチン内でコルーチンを連続して呼び出す【UniRx】

vuvu

総合スコア15

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2018/06/27 07:33

編集2018/06/28 01:24

前提・実現したいこと

現在UniRxで敵ユニットのAI部分を作っています。ゲーム内容はシミュレーションRPGのようなターン制で、
敵のターンに移ると敵ユニットが順番に行動をする予定です。

使用側は以下のような形で敵をActionAIコルーチンで行動させて、終わり次第終了処理をしてから次の敵のAIを起動したいと考えています。

C#

1/* EnemyManager */ 2Observable.FromCoroutine(_ => enemies[i].ActionAI()) 3 .Subscribe(_ => 4 { 5 // 敵行動終了時の処理 6 // その後、次の敵行動へ 7 });

発生している問題

敵AIは[移動]→[攻撃]という流れで行動させるつもりで、[移動]と[攻撃]は既に実装できました。
[移動][攻撃]はそれぞれアニメーションなどに合わせて終了を通知させたいのでコルーチンでの非同期処理にしました。
ですが、以下のようなコードでは[移動]の完了時にActionAiの終了通知が流れてしまい、一連のコルーチンの完了を通知できていません。(移動完了時点で次の敵が移動してしまう)
[攻撃]まで終了してからActionAIの終了を通知するにはどうすればいいでしょうか?

C#

1 public IEnumerator ActionAI() 2 { 3 // 移動 4 yield return Observable.FromCoroutine(_ => ExecuteMoveAI()) 5 .Do(_ => Debug.Log("移動完了")) 6 .ToYieldInstruction(); 7 8 // 攻撃 9 yield return Observable.FromCoroutine(_ => ExecuteAttackAI()) 10 .Do(_ => Debug.Log("攻撃完了")) 11 .ToYieldInstruction(); 12 }

UniRxもコルーチンについても無学なため、基本的な考え方から合っているかわかりません。
以上の問題について解決策、別の実装方などアイデアを頂ければ幸いです。よろしくお願いします。

補足情報

Unity Ver.2017.2.0f3

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

私もUniRxについて経験が浅いので自信がないのですが、EnemyManager中のFromCoroutineの第2引数publishEveryYieldがfalseなら、コルーチンが完了してからSubscribeに記述された敵行動終了時の処理が実行されるのではないかと思います。
publishEveryYieldはデフォルトでfalseなので、敵行動終了時の処理はご質問者さんの現状のコードで正しく実行されるような気がするのですが、それなのに次の敵が変なタイミングで行動を開始してしまうとなると、ご提示のコードでは省略されている、各敵の全行動完了を待機するロジックに何かトラブルがあるのではないでしょうかね...?
コード中の各段階で細かくLogを出力させてみたり、デバッガで動きを追ってみる必要があるかもしれません。

※試しにその全行動完了待機の部分をToYieldInstructionで作ったYieldInstructionをyield returnで返して待機させるようにして、Subscribeで記述していた敵行動終了時の処理はDoでやるようにしたところ、とりあえずちゃんとした順序で動いているように見えました。

Enemy

C#

1using System.Collections; 2using UniRx; 3using UnityEngine; 4 5public class Enemy : MonoBehaviour 6{ 7 public IEnumerator ActionAI() 8 { 9 yield return Observable.FromCoroutine(_ => this.ExecuteMoveAI()) 10 .Do(_ => Debug.LogFormat("ActionAI : {0} 移動完了", this.name)) 11 .ToYieldInstruction(); 12 13 yield return Observable.FromCoroutine(_ => this.ExecuteAttackAI()) 14 .Do(_ => Debug.LogFormat("ActionAI : {0} 攻撃完了", this.name)) 15 .ToYieldInstruction(); 16 } 17 18 private IEnumerator ExecuteMoveAI() 19 { 20 Debug.LogFormat("ExecuteMoveAI : {0} 移動開始", this.name); 21 22 yield return new WaitForSeconds(1.0f); 23 24 Debug.LogFormat("ExecuteMoveAI : {0} 移動終了", this.name); 25 } 26 27 private IEnumerator ExecuteAttackAI() 28 { 29 Debug.LogFormat("ExecuteAttackAI : {0} 攻撃開始", this.name); 30 31 yield return new WaitForSeconds(1.0f); 32 33 Debug.LogFormat("ExecuteAttackAI : {0} 攻撃終了", this.name); 34 } 35}

EnemyManager

C#

1using System.Collections; 2using UniRx; 3using UnityEngine; 4 5public class EnemyManager : MonoBehaviour 6{ 7 public Enemy[] enemies; 8 9 private IEnumerator Start() 10 { 11 Debug.Log("Start : 敵集団行動開始"); 12 13 yield return new WaitForSeconds(1.0f); 14 15 var enemyCount = this.enemies.Length; 16 17 for (var i = 0; i < enemyCount; i++) 18 { 19 var enemy = this.enemies[i]; 20 21 yield return Observable.FromCoroutine(_ => enemy.ActionAI()) 22 .Do(_ => Debug.LogFormat("Do : {0} 全行動終了、次の敵の行動に移る", enemy.name)) 23 .ToYieldInstruction(); 24 25 Debug.Log("Start : 次の敵の行動に移る"); 26 27 yield return new WaitForSeconds(1.0f); 28 } 29 30 Debug.Log("Start : 敵集団行動終了"); 31 } 32}

コンソールに出力された結果
コンソール

投稿2018/06/27 13:36

Bongo

総合スコア10807

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

vuvu

2018/06/28 01:41

回答ありがとうございます!わざわざ実行結果まで載せていただき大変分かりやすかったです! 今一度ソースコードを確認してみたところ、省略していたAttackAIのコルーチンでyield returnの記述が抜けていました… AttackAIを修正した所、無事にやりたかった挙動で実装できました! 丁寧に回答して頂いたのに基礎的な部分のミスで申し訳ないです… 非常に助かりました!ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問