🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C#

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

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

非同期処理

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

Unity

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

Q&A

解決済

1回答

1154閲覧

Unityスクリプトのスレッド処理について

gorogorosan

総合スコア6

C#

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

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

非同期処理

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

Unity

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

0グッド

0クリップ

投稿2019/12/05 06:39

前提・実現したいこと

unityのスクリプトで非同期処理をしています.
threadクラスを用いてサブスレッドの方でVideo()をメインスレッドの方でRealShadowMove()を実行しているのですがPlayボタンを押してアプリを実行するとEditorがフリーズしてしまいます
何が原因か教えていただけると助かります

該当のソースコード

言語はC#です

ソースコード using System.Collections; using System.Collections.Generic; using UnityEngine; using System.Threading; using OpenCvSharp; using OpenCvSharp.Blob; using System; using System.IO; public class sdaaasdf : MonoBehaviour { private Thread _thread; private int i = 0; private Mat gameview; private Camera ConvertCamera; private Vector3 ScreenPt =new Vector3(0f,0f,0f); private Vector3 WorldPoint; private Vector3 MousePoint; void Start() { ConvertCamera = Camera.main; _thread = new Thread(Video); _thread.Start(); _thread.Join(); RealShadowMove(); } void Video() { var frame = new Mat(); var frame2 = new Mat(); var gray = new Mat(); var gray2 = new Mat(); var binary = new Mat(); var binary2 = new Mat(); var diff = new Mat(); var find = new Mat(); var contours = new Mat[] { }; var hierarchy = new Mat(); var contours2 = new Mat[] { }; var video0 = new VideoCapture(0); // var video1 = new VideoCapture(1); while (true) { //webカメラ画像読み込み video0.Read(frame); //画像処理 binary = ImageProcessing(frame, 180); // ラベリング実行(必要な領域以外は排除) CvBlobs blobs = new CvBlobs(binary); blobs.FilterByArea(2000, 7000); for (int i = 1; i < blobs.Count; i++) { var cvContour = blobs[i].Contour; var L = cvContour.Perimeter(); var area = blobs[i].Area; var circularity = 4 * Math.PI * (area / (L * L)); if (0.4 < circularity && circularity < 0.9) { blobs.FilterByLabel(i); Debug.Log(circularity); } } // ラベリング結果の描画 var render = new Mat(frame.Rows, frame.Cols, MatType.CV_8UC3, 3); blobs.RenderBlobs(frame, render); //切り抜き CvBlob maxBlob = blobs.LargestBlob(); render = render[maxBlob.Rect]; //ここまでウェブカメラ画像の処理 //同様にしてゲームビュー画像の処理 binary2 = ImageProcessing(gameview, 50); CvBlobs blobs2 = new CvBlobs(binary2); var render2 = new Mat(gameview.Rows, gameview.Cols, MatType.CV_8UC3, 3); blobs2.RenderBlobs(gameview, render2); CvBlob maxBlob2 = blobs2.LargestBlob(); render2 = render2[maxBlob2.Rect]; //画像拡大縮小 Cv2.Resize(render, render, new OpenCvSharp.Size(render2.Width, render2.Height), 0, 0, InterpolationFlags.Cubic); //画像の差分計算 Cv2.Absdiff(render, render2, diff); //実影の認識 var binarydiff = ImageProcessing(diff, 150); CvBlobs diffblobs = new CvBlobs(binarydiff); var maxdiffblob = diffblobs.LargestBlob(); //var realshadow= diff[maxBlob.Rect]; //バウンディングボックス描画 binarydiff.FindContours(out contours, hierarchy, RetrievalModes.List, ContourApproximationModes.ApproxNone); for (int i = 0; i < contours.Length; i++) { var Rect = Cv2.BoundingRect(contours[i]); Cv2.Rectangle(binarydiff, new Point(Rect.X, Rect.Y), new Point(Rect.X + Rect.Width, Rect.Y + Rect.Height), Scalar.Blue, 2); } //比率変換の係数計算 var TransportWidth = (double)(Screen.width / binarydiff.Width); var TransportHeight = (double)(Screen.height / binarydiff.Height); Debug.Log("幅の比率:" + TransportWidth); Debug.Log("高さの比率:" + TransportHeight); Debug.Log(maxdiffblob.Area); if (maxdiffblob.Area > 10000) { var pt = maxdiffblob.Centroid; Debug.Log("実影の座標" + pt.X + "," + pt.Y); ScreenPt= new Vector3((float)(pt.X * TransportWidth), (float)(Screen.height - (pt.Y * TransportHeight)), 10.0f); } else { ScreenPt = new Vector3(-100f, -100f, -100f); Debug.Log("aaa"); } //結果の表示 using (new Window("binary", binary)) ; using (new Window("render", render)) ; using (new Window("render2", render2)) ; using (new Window("diff", diff)) ; using (var win = new Window("binarydiff", binarydiff)) ; //using (new Window("realshadow", realshadow)); //キー入力処理 int key = Cv2.WaitKey(100); if (key == 27) break; if (i == 1) { break; } } } //画像処理の関数(引数は画像,閾値k(0~255)) Mat ImageProcessing(Mat frame, int k) { var render = new Mat(frame.Rows, frame.Cols, MatType.CV_8UC3, 3); var gray = new Mat(); var binary = new Mat(); //グレースケール変換 Cv2.CvtColor(frame, gray, ColorConversionCodes.BGR2GRAY); //平滑化 Cv2.Blur(gray, gray, new Size(5, 5)); //二値化 binary = gray.Threshold(k, 255, ThresholdTypes.Binary); return binary; } //実影のオブジェクト移動,描画 void RealShadowMove() { while (true) { ScreenCapture.CaptureScreenshot("image4.png"); gameview = new Mat(@"image.png"); Vector3 MousePos = Input.mousePosition; MousePos.z = 10.0f; Debug.Log("マウスの位置" + MousePos); Debug.Log("screen画面での実影の座標" + ScreenPt); WorldPoint = ConvertCamera.ScreenToWorldPoint(ScreenPt); MousePoint = ConvertCamera.ScreenToWorldPoint(MousePos); WorldPoint.y *= -1; MousePoint.y *= -1; //this.gameObject.transform.position = MousePoint; this.gameObject.transform.position = WorldPoint; iTween.MoveTo(this.gameObject, WorldPoint, (float)0.1); Debug.Log("実影のワールド座標" + WorldPoint); Debug.Log("マウスのワールド座標" + MousePoint); if (i == 1) { break; } } } // Update is called once per frame void Update(){} private void OnApplicationQuit() { if (_thread != null) { i = 1; } } } ### 試したこと while分の中で無限ループを起こしている可能性が高いと思い,キー入力で抜けるようにもしてみましたがうまくいかない状況です ### 補足情報(FW/ツールのバージョンなど) OS:win10,Unity:2018.2.2f1 ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答1

0

ベストアンサー

まず問題を切り分けてください。例えばRealShadowMoveは呼ばずにThreadだけを動かす、またはその逆など。
まぁ今回はRealShadowMoveが原因だとは思います。(Thread側はちゃんと読んでないので「両方」が原因かもしれませんが)


変数iが1になる部分がどこにもないので、RealShadowMoveのwhileが無限ループしてます。

もしもキーで停止させる機能を入れたとしてもCPUが許す限りの速度でブン回るので多分先にフリーズします。
そもそもRealShadowMoveが終わるまではStartも終わらず、よってUpdateも始まらないのでInput.〜は更新されません。

なので「RealShadowMoveをコルーチンにしてwhileの中にyield return null;でも入れる」または「whileを消してStartではなくUpdateから呼ぶ」かのどちらかにする必要があるかと思います。
(どちらの場合も「毎フレーム処理をする」という動きになります)

投稿2019/12/05 08:00

sakura_hana

総合スコア11427

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

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

gorogorosan

2019/12/05 08:40

色々見落としてました 的確なご指摘ありがとうございます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問