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

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

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

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

非同期処理

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

Unity

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

1787閲覧

UnityでPythonを非同期で実行させたあとに別の処理をさせたい

Strix9289

総合スコア2

C#

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

非同期処理

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

Unity

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2020/08/25 09:19

前提・実現したいこと

UnityでC#のProcessを用いて非同期でPythonを実行させたあとに"r.Rotate()"という処理をさせたいです。
Pythonを実行することはできたのですが、非同期処理が終了した後にUnityのコンポーネントを操作するプログラムを実行されることができません。該当スクリプトでは、OutputDataReceived及びp_Exited外ではr.Rotate()が実行できました。(ただその場合、Python()を実行させた直後に動作してしまいます。)わかりずらい文章で申し訳ありませんが解決方法を教えていただけると幸いです。

該当のソースコード

C#

1using System.Collections; 2using System.Collections.Generic; 3using System.Diagnostics; 4using System.IO; 5using System.Runtime.CompilerServices; 6using System.Text; 7using System; 8using System.ComponentModel; 9using UnityEngine; 10 11public class CsPy : MonoBehaviour 12{ 13 //pythonがある場所 14 private string pyExePath = @"~python.exe"; 15 16 //実行したいスクリプトがある場所 17 private string pyCodePath = @"C:(実行したいファイル).py"; 18 19 //非同期処理後に操作したいオブジェクト 20 GameObject gameObject; 21 22 public void Python() 23 { 24 //Hierarchy上のImageを取得し、アタッチされているスクリプトのクラスをrとする 25 gameObject = GameObject.Find("Image"); 26 RotateImage r = gameObject.GetComponent<RotateImage>(); 27 28 //外部プロセスの設定 29 ProcessStartInfo processStartInfo = new ProcessStartInfo() 30 { 31 FileName = pyExePath, //実行するファイル(python) 32 UseShellExecute = false,//シェルを使うかどうか 33 CreateNoWindow = true, //ウィンドウを開くかどうか 34 RedirectStandardOutput = true, //テキスト出力をStandardOutputストリームに書き込むかどうか 35 Arguments = pyCodePath, //実行するスクリプト 引数(複数可) 36 StandardOutputEncoding = Encoding.GetEncoding("shift_jis"), 37 }; 38 39 //外部プロセスの開始 40 Process process = Process.Start(processStartInfo); 41 42 process.OutputDataReceived += dataReceived; 43 process.BeginOutputReadLine(); // 非同期ストリーム読み取りの開始 44 45 46 // OutputDataReceivedイベントハンドラ.行が出力されるたびに呼び出される 47 void dataReceived(object sender, DataReceivedEventArgs e) 48 { 49 string str = e.Data; 50 51 if (str!=null && str.Length > 0) 52 { 53 UnityEngine.Debug.Log(str); 54 } 55 else 56 { 57 UnityEngine.Debug.Log("終了"); //このデバックはpythonスクリプト実行後に出力されました。 58 } 59 } 60 61 // プロセスが終了したときに Exited イベントを発生させる 62 process.EnableRaisingEvents = true; 63 // イベントハンドラがフォームを作成したスレッドで実行されるようにする 64 process.SynchronizingObject = (ISynchronizeInvoke)this; 65 //イベントハンドラの追加 66 process.Exited += p_Exited; //new EventHandler(p_Exited); 67 68 void p_Exited(object sender, EventArgs e) 69 { 70 UnityEngine.Debug.Log("終了"); //同様にこのデバックはpythonスクリプト実行後に出力されました。 71 //プロセスが終了したときに実行されてほしい 72 r.Rotate(); 73 } 74 75 //ここでr.Rotate()とするとこのプログラム実行直後に動作してしまいます。 76 } 77}

試したこと

process.Exit一連を削除して、dataReceived関数中のDebug.Log("終了")の後にr.Rotate()を入れるとエラーもなく無視されました。一方で、p_Exited()の中でr.Rotateとすると以下のエラーメッセージが出力され、r.Rotateが実行されないままpythonスクリプトは問題なく実行されました。

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

InvalidCastException: Specified cast is not valid. CsPy.Python () (at Assets/Script/CsPy.cs:76) UnityEngine.Events.InvokableCall.Invoke () (at <2feaf16e80004e0cadae3f2e05f2a3fa>:0) UnityEngine.Events.UnityEvent.Invoke () (at <2feaf16e80004e0cadae3f2e05f2a3fa>:0) UnityEngine.UI.Button.Press () (at C:/GAMES/2019.4.8f1/Editor/Data/Resources/PackageManager/BuiltInPackages/com.unity.ugui/Runtime/UI/Core/Button.cs:68) UnityEngine.UI.Button.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at C:/GAMES/2019.4.8f1/Editor/Data/Resources/PackageManager/BuiltInPackages/com.unity.ugui/Runtime/UI/Core/Button.cs:110) UnityEngine.EventSystems.ExecuteEvents.Execute (UnityEngine.EventSystems.IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at C:/GAMES/2019.4.8f1/Editor/Data/Resources/PackageManager/BuiltInPackages/com.unity.ugui/Runtime/EventSystem/ExecuteEvents.cs:50) UnityEngine.EventSystems.ExecuteEvents.Execute[T] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.ExecuteEvents+EventFunction`1[T1] functor) (at C:/GAMES/2019.4.8f1/Editor/Data/Resources/PackageManager/BuiltInPackages/com.unity.ugui/Runtime/EventSystem/ExecuteEvents.cs:261) UnityEngine.EventSystems.EventSystem:Update() (at C:/GAMES/2019.4.8f1/Editor/Data/Resources/PackageManager/BuiltInPackages/com.unity.ugui/Runtime/EventSystem/EventSystem.cs:377)

補足情報(FW/ツールのバージョンなど)

Windows10
unityのバージョンは2019.4.8f1です。

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2020/08/27 07:56

Unityはよく知らないし今はインストールもしていません。原因とは関係ないと思いますが、とりあえず、イベントハンドラはイベントが発生する可能性が出てくる前に登録しないとダメです。 process.EnableRaisingEvents process.SynchronizingObject process.Exited の設定はProcess.Startより前でないといけないという意味です。
guest

回答1

0

自己解決

同じことで困っている人がいるかどうかわかりませんが、自己解決方法を記録しておこうと思います。
プロセスを非同期で実行した後、そこで得られたPythonからのアウトプットをC#で読み込みOutputに格納。Update関数でOutputの状態を常に監視し、Outputが空でなくなったら実行することで、Python非同期処理→C#の処理という形で実現しました。

C#

1 2//出力されたデータを保存する 3 private StringBuilder output = new StringBuilder(); 4 5public void Python() 6 { 7 //新規プロセスの立ち上げ 8 var p = new Process(); 9 //プロセスの設定 10 p.StartInfo.FileName = pyExePath; 11 p.StartInfo.UseShellExecute = false; 12 p.StartInfo.CreateNoWindow = true; 13 p.StartInfo.RedirectStandardOutput = true; 14 p.StartInfo.Arguments = pyCodePath; 15 p.StartInfo.StandardOutputEncoding = Encoding.GetEncoding("shift_jis"); 16 17 //イベントハンドラの設定 18 p.OutputDataReceived += new DataReceivedEventHandler((sender, e) => 19 { 20 string str = e.Data; 21 22 if (!String.IsNullOrEmpty(str)) 23 { 24 UnityEngine.Debug.Log(str); 25 output.Append(str+"\n"); 26 } 27 28 }); 29 p.Start(); 30 31 UnityEngine.Debug.Log("プロセス実行中に非同期で開始されます"); 32 33 34 } 35 36 void Update() 37 { 38 if(output.Length != 0){ 39 UnityEngine.Debug.Log("プロセスが完了した後実行されます"); 40 output.Length = 0 ; 41 } 42 } 43} 44

投稿2020/08/29 12:43

Strix9289

総合スコア2

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問