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

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

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

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

Unity

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

Q&A

解決済

2回答

1373閲覧

エラーの解決をしたい

UKAWATAKATO

総合スコア14

C#

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

Unity

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

0グッド

0クリップ

投稿2018/09/03 00:30

編集2018/09/03 06:12

Find can only be called from the main thread
とコンソールにエラーがでてきてしまうので
よろしければなぜエラーが出てしまうのか、解決策をアドバイスしてほしいです。
デバックは行いました。解決策に上司が
Startでテキストオブジェクトを参照しておいて、Updateで値を変更したら
できるといいましたが、よくわかりませんでした。
お願いしますよろしければ教えてもらえませんか。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using UnityEngine.UI; // <---- 追加1

public class UdpSocket : MonoBehaviour
{
private string _MulticastAddr = "224.0.23.0"; // マルチキャストアドレス
private string _RemoteHost = ""; // 送信相手アドレス
private int _SendPort = 3610; // 送信ポート
private int _RecvPort = 3610; // 受信ポート

private UdpClient _UdpClient; // UDP private IPEndPoint _IpEndPoint; // IPEndPoint private Thread _RecvThread; // 受信スレッド // 接続 public void Connect() { IPAddress grpAddr = IPAddress.Parse(_MulticastAddr); if (_IpEndPoint != null) _IpEndPoint = null; _IpEndPoint = new IPEndPoint(grpAddr, _RecvPort); // マルチキャストグループに参加 Disconnect(); _UdpClient = new UdpClient(_RecvPort); _UdpClient.JoinMulticastGroup(grpAddr); // 受信スレッド生成 _RecvThread = new Thread(ReceiveMulticastThread); _RecvThread.Start(); // ノードプロファイル通知送信 SendNodeProfile(); } // 切断 public void Disconnect() { if (_RecvThread != null) { _RecvThread.Abort(); _RecvThread = null; } if (_UdpClient != null) { IPAddress grpAddr = IPAddress.Parse(_MulticastAddr); _UdpClient.DropMulticastGroup(grpAddr); _UdpClient.Close(); _UdpClient = null; } } // ノードプロファイル通知送信 public void SendNodeProfile() { byte[] pack = BuildNodeProfileInfo(); SendPacket(pack, _MulticastAddr); } // 送信 public void SendPacket(byte[] packet, string host) { _UdpClient.Send(packet, packet.Length, host, _SendPort); } // 受信スレッド public void ReceiveMulticastThread() { byte[] packet; int i = 0; System.Text.StringBuilder s = new System.Text.StringBuilder(); while (true) { packet = _UdpClient.Receive(ref _IpEndPoint); if (packet != null) { // 受信できた! s.Remove(0, s.Length); for (i = 0; i < packet.Length; i++) { s.Append(System.Convert.ToString(packet[i], 16).PadLeft(2, '0')); } Debug.Log(s.ToString()); Text targetText; // <---- 追加2 GameObject _Object; _Object = GameObject.Find("Text"); targetText = _Object.GetComponent<Text>(); // <---- 追加3 targetText.text = "s.ToString()"; // <---- 追加4 } } } // ノードプロファイル通知パケット作成 private byte[] BuildNodeProfileInfo() { byte[] pack; pack = new byte[17]; pack[0] = 0x10; // EHD1 pack[1] = 0x81; // EHD2 pack[2] = 0x00; // pack[3] = 0x01; // ID pack[4] = 0x0E; // 送信元「ノードプロファイルクラス」 pack[5] = 0xF0; // EOJ = 0x0E F0 01 pack[6] = 0x01; // pack[7] = 0x0E; // 送信先「ノードプロファイルクラス」 pack[8] = 0xF0; // EOJ = 0x0E F0 01 pack[9] = 0x01; // pack[10] = 0x73; // ESV pack[11] = 0x01; // OPC pack[12] = 0xD5; // EPC pack[13] = 0x04; // PDC pack[14] = 0x01; // EDT pack[15] = 0x05; // pack[16] = 0xFF; // pack[16] = 0x01; // return pack; }

}

コード

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

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

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

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

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

guest

回答2

0

ベストアンサー

unityでは別スレッドからunity機能を使うことが出来ません。
ですので、受信スレッドで直接テキストをセットするのではなく
別の方法で行うようにしましょう。
申し訳ありませんが、私はunityについてほぼ知らないので具体的な
方法の提示ができません。

また、targetTextへTextをセットする部分はそれではダメです。
定数と変数の区別をつけましょう。

・追記

上司さんの案について
1.作成しているUdpSocketクラスにprivateなstring型の変数を作ります。
2.受信スレッドでは、受信したデータを直接Textに設定するのではなく、先ほどの変数へ格納するだけにします。
3.UdpSocketクラスにstartメソッドを作成し、そこにTextのインスタンスを取得するようにします。
4.UdpSocketクラスにupdateメソッドを作成し、そこに3で保持したTextのインスタンスに1の変数をセットします。

単純に書いたらこのような流れになるかと思います。

C#

1public class UdpSocket : MonoBehaviour 2{ 3 // いろいろ省略 4 private string RecvData = ""; 5 private Text targetText; 6 7 void Start () { 8 targetText = GameObject.Find("Text").GetComponent<Text>(); 9 } 10 11 void Update() { 12 targetText.text = RecvData; 13 } 14 15 // いろいろ省略 16

コードは適当に書いているので、考え方の参考程度にしてください。

投稿2018/09/03 00:46

編集2018/09/03 06:14
YAmaGNZ

総合スコア10222

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

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

UKAWATAKATO

2018/09/03 01:20

回答ありがとうございます。 テキストのところが駄目なことがわかったので一度調べて考えて見ます。 ありがこうございました!
YAmaGNZ

2018/09/03 01:33 編集

unityは別スレッドからGameObject.Findもできないはず(エラーメッセージにも書いてあるとおり)ですので、 テキストをセットするところだけがダメというわけではありません。
UKAWATAKATO

2018/09/03 02:53

回答ありがとうございます。 GameObject _Object; _Object = GameObject.Find("Text");これも直さないといけないのですね、、
UKAWATAKATO

2018/09/03 07:03

ありがとうございました! とっても的確な回答ですごくわかりやすかったです。 変数を同じものを使っているのでそれを変更したらいけると言われました。 本当にありがとうございました。
guest

0

targetText.text = "s.ToString()"; // <---- 追加4

GUIコンポーネントの表示回りは、メインスレッド上からでないと変更できません
「c# 別スレッド コントロール」でぐぐると、そこらへんの対処法が出てくるので読んでみてください

投稿2018/09/03 00:43

y_waiwai

総合スコア87719

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

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

UKAWATAKATO

2018/09/03 01:24

回答ありがとうございます。 ネットでその対処法を一度調べて見ます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問