Skip to content

Instantly share code, notes, and snippets.

@togucchi
Last active July 25, 2019 14:54
Show Gist options
  • Save togucchi/7e14a8f3ff52baaf4e587140491834e9 to your computer and use it in GitHub Desktop.
Save togucchi/7e14a8f3ff52baaf4e587140491834e9 to your computer and use it in GitHub Desktop.
[Unity]非同期処理(Task)の利用例(UDP送受信,SerialPortのRead) ref: https://qiita.com/togucchi/items/45cf6e65c883e6f47d3d
using UnityEngine;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
public class UdpServer : MonoBehaviour
{
// UnityEventの引数指定用のダミークラス
public class ReceivedCallback : UnityEngine.Events.UnityEvent<string>
{
}
// データを受信したときに発火されるイベント
public static ReceivedCallback OnReceivedEvent = new ReceivedCallback();
[SerializeField]
int port = 22222;
static UdpClient udp;
Task receiveTask;
bool isRunning = false;
public bool IsRunning
{
get
{
return isRunning;
}
}
void Awake ()
{
udp = new UdpClient(port);
// udp.Client.ReceiveTimeout = 1000;
OpenServer();
}
void OnDisable()
{
CloseServer();
}
void OnEnable()
{
if(!isRunning)
{
OpenServer();
}
}
public void OpenServer()
{
if(isRunning) return;
isRunning = true;
receiveTask = DataReceiveTask();
}
public void CloseServer()
{
if(!isRunning) return;
isRunning = false;
// isRunningをfalseにするとTaskが止まるのでそれを待つ
if(receiveTask != null && receiveTask.Status == TaskStatus.Running)
{
receiveTask.Wait();
}
}
async Task DataReceiveTask()
{
await Task.Run(() =>
{
while(isRunning)
{
//Debug.Log("TEST");
IPEndPoint remoteEP = null;
byte[] data = udp.Receive(ref remoteEP);
string text = Encoding.ASCII.GetString(data);
// 登録したイベントを発火
OnReceivedEvent.Invoke(text);
}
});
}
}
using UnityEngine;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
public class UdpSender : MonoBehaviour
{
// broadcast address
public string host = "192.168.0.255";
public int port = 3333;
private UdpClient client;
bool isConnect = false;
void Start ()
{
client = new UdpClient();
}
public void ConnectClient(string host, int port)
{
if(isConnect)
{
return;
}
this.host = host;
this.port = port;
client.Connect(host, port);
}
public void CloseClient()
{
if(!isConnect)
{
return;
}
client.Close();
}
void Test_Send()
{
byte[] dgram = Encoding.UTF8.GetBytes("hello!");
SendData(dgram);
}
public async Task SendData(string json)
{
await Task.Run(() => {
byte[] dgram = Encoding.UTF8.GetBytes(json);
client.Send(dgram, dgram.Length);
});
}
public async Task SendData(byte[] dgram)
{
await Task.Run(() => {
client.Send(dgram, dgram.Length);
});
}
void OnDisable()
{
client.Close();
}
}
using UnityEngine;
using UnityEngine.Events;
using System.Collections;
using System.IO.Ports;
using System.Threading;
using System.Threading.Tasks;
public class SerialPortHandler : MonoBehaviour
{
[System.Serializable]
public class DataCallback : UnityEvent<string>
{
}
public static DataCallback OnDataReceived = new DataCallback();
// ボーレート (bit/sec)
public int baudRate = 115200;
public bool isDebug = false;
string currentPortName = null;
bool isRunning = false;
SerialPort serialPort;
Task task;
void Start()
{
// Debug用
if(isDebug && currentPortName != null)
{
Open(currentPortName);
}
}
void OnDestroy()
{
Close();
}
void OnEnable()
{
if(currentPortName != null && !isRunning)
{
Open(currentPortName);
}
}
void OnDisable()
{
Close();
}
// ポート名を指定してSerialPortを開く
public void Open(string portName)
{
if(isRunning) return;
currentPortName = portName;
serialPort = new SerialPort(portName, baudRate, Parity.None, 8, StopBits.One);
serialPort.Open();
isRunning = true;
task = ReadAsync();
}
public void Close()
{
if(!isRunning) return;
isRunning = false;
// タスクの終了待ち
if (task != null && task.Status == TaskStatus.Running)
{
task.Wait();
}
// タスクが終了してからSerialPortを閉じる
if (serialPort != null && serialPort.IsOpen)
{
serialPort.Close();
serialPort.Dispose();
}
}
async Task ReadAsync()
{
await Task.Run(() => {
while (isRunning && serialPort != null && serialPort.IsOpen)
{
try
{
string message = serialPort.ReadLine();
// Debug.LogWarning(message);
OnDataReceived.Invoke(message);
}
catch (System.Exception e)
{
Debug.LogWarning(e.Message);
}
}
});
}
}
using UnityEngine;
using UnityEngine.Events;
using System.Collections;
using System.IO.Ports;
using System.Threading;
using System.Threading.Tasks;
public class SerialPortHandler : MonoBehaviour
{
[System.Serializable]
public class DataCallback : UnityEvent<string>
{
}
public static DataCallback OnDataReceived = new DataCallback();
// ボーレート (bit/sec)
public int baudRate = 115200;
public bool isDebug = false;
string currentPortName = null;
bool isRunning = false;
SerialPort serialPort;
Task task;
void Start()
{
// Debug用
if(isDebug && currentPortName != null)
{
Open(currentPortName);
}
}
void OnDestroy()
{
Close();
}
void OnEnable()
{
if(currentPortName != null && isRunning)
{
Open(currentPortName);
}
}
void OnDisable()
{
Close();
}
// ポート名を指定してSerialPortを開く
public void Open(string portName)
{
if(isRunning) return;
currentPortName = portName;
serialPort = new SerialPort(portName, baudRate, Parity.None, 8, StopBits.One);
serialPort.Open();
isRunning = true;
task = ReadAsync();
}
public void Close()
{
if(!isRunning) return;
isRunning = false;
// タスクの終了待ち
if (task != null && task.Status == TaskStatus.Running)
{
task.Wait();
}
// タスクが終了してからSerialPortを閉じる
if (serialPort != null && serialPort.IsOpen)
{
serialPort.Close();
serialPort.Dispose();
}
}
async Task ReadAsync()
{
await Task.Run(() => {
while (isRunning && serialPort != null && serialPort.IsOpen)
{
try
{
string message = serialPort.ReadLine();
// Debug.LogWarning(message);
OnDataReceived.Invoke(message);
}
catch (System.Exception e)
{
Debug.LogWarning(e.Message);
}
}
});
}
}
using UnityEngine;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
public class UdpSender : MonoBehaviour
{
// broadcast address
public string host = "192.168.0.255";
public int port = 3333;
private UdpClient client;
bool isConnect = false;
void Start ()
{
client = new UdpClient();
}
public void ConnectClient(string host, int port)
{
if(isConnect)
{
return;
}
this.host = host;
this.port = port;
client.Connect(host, port);
}
public void CloseClient()
{
if(!isConnect)
{
return;
}
client.Close();
}
void Test_Send()
{
byte[] dgram = Encoding.UTF8.GetBytes("hello!");
SendData(dgram);
}
public async Task SendData(string json)
{
await Task.Run(() => {
byte[] dgram = Encoding.UTF8.GetBytes(json);
client.Send(dgram, dgram.Length);
});
}
public async Task SendData(byte[] dgram)
{
await Task.Run(() => {
client.Send(dgram, dgram.Length);
});
}
void OnDisable()
{
client.Close();
}
}
using UnityEngine;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
public class UdpServer : MonoBehaviour
{
// UnityEventの引数指定用のダミークラス
public class ReceivedCallback : UnityEngine.Events.UnityEvent<string>
{
}
// データを受信したときに発火されるイベント
public static ReceivedCallback OnReceivedEvent = new ReceivedCallback();
[SerializeField]
int port = 22222;
static UdpClient udp;
Task receiveTask;
bool isRunning = false;
public bool IsRunning
{
get
{
return isRunning;
}
}
void Awake ()
{
udp = new UdpClient(port);
// udp.Client.ReceiveTimeout = 1000;
OpenServer();
}
void OnDisable()
{
CloseServer();
}
void OnEnable()
{
if(isRunning)
{
OpenServer();
}
}
public void OpenServer()
{
if(isRunning) return;
isRunning = true;
receiveTask = DataReceiveTask();
}
public void CloseServer()
{
if(!isRunning) return;
isRunning = false;
// isRunningをfalseにするとTaskが止まるのでそれを待つ
if(receiveTask != null && receiveTask.Status == TaskStatus.Running)
{
receiveTask.Wait();
}
}
async Task DataReceiveTask()
{
await Task.Run(() =>
{
while(isRunning)
{
//Debug.Log("TEST");
IPEndPoint remoteEP = null;
byte[] data = udp.Receive(ref remoteEP);
string text = Encoding.ASCII.GetString(data);
// 登録したイベントを発火
OnReceivedEvent.Invoke(text);
}
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment