Monday, August 05, 2019
Set up OSC in Unity to send and receive data.
To test my code I send OSC data from a small python script on my Mac across the local network. I have to open a port in the Windows firewall before I can receive the message.
Here is the C# script:
using System.Collections;
using UnityEngine;
/// <summary>
/// This class uses https://github.com/thomasfredericks/UnityOSC
/// </summary>
public class PythonOSC : MonoBehaviour
{
[SerializeField]
private OSC _osc;
void Start()
{
_osc.SetAddressHandler("/hello", OnHello); //simple 'hello world' test path
_osc.SetAllMessageHandler(OnAnyMessage); //handle any message
StartCoroutine(DelaySendMessage()); //Test sending a message
}
/// <summary>
/// Will send an OSC message to address "/hello" with
/// a single float parameter after 2 seconds
/// </summary>
/// <returns></returns>
private IEnumerator DelaySendMessage()
{
yield return new WaitForSeconds(2);
var msg = new OscMessage {address = "/hello"};
msg.values.Add(0.1f);
_osc.Send(msg);
}
/// <summary>
/// Will handle all OSC messages arriving on the incoming port
/// </summary>
/// <param name="oscm"></param>
private void OnAnyMessage(OscMessage oscm)
{
Debug.Log("any message received");
}
/// <summary>
/// Handler for the "/hello" address
/// Parse the float from the message
/// </summary>
/// <param name="oscm"></param>
private void OnHello(OscMessage oscm)
{
var str = oscm.GetFloat(0);
Debug.Log($"Said Hello {str}");
}
}
And the python script:
"""Small example OSC client
This program sends 10 random values between 0.0 and 1.0 to the /filter address,
waiting for 1 seconds between each value.
"""
import argparse
import random
import time
from pythonosc import osc_message_builder
from pythonosc import udp_client
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--ip", default="localhost",
help="The ip of the OSC server")
parser.add_argument("--port", type=int, default=3001,
help="The port the OSC server is listening on")
args = parser.parse_args()
client = udp_client.SimpleUDPClient(args.ip, args.port)
for x in range(10):
val = random.random();
print(args.ip, args.port,val);
client.send_message("/hello", val)
time.sleep(1)
I also create a receiver in ChucK to handle the value sent from Unity:
//osc.ck
// create our OSC receiver
OscRecv oscin;
3001 => oscin.port;
// start listening (launch thread)
oscin.listen();
// ..or listen to all messages
//oscin.listenAll();
// create an address in the receiver
// and store it in a new variable.
oscin.event("/hello,f") @=> OscEvent HelloEvent;
while ( true ){
HelloEvent => now;
while ( HelloEvent.nextMsg() != 0 ){
HelloEvent.getFloat() => eventBus.hrmEvent.val;
eventBus.hrmEvent.broadcast();
}
}
This completes the testing for OSC messaging to and from Unity. I’ll deal with sending OSC over wifi from the Arduino Feather later..