- Home /
How can I change scenes with OSC input? Main thread?
I'm trying to advance to the next or previous level when I receive certain OSC input. I'm using OSC scripts from this tutorial, which all work fine until I try to change scenes and I get a "LoadLevelAsync can only be called from the main thread." error.
I'm new to Unity, so I think I'm missing something pretty basic here, but as far as I've been able to find on Google, as long as I call Application.LoadLevel from within a function I should be ok. I'm doing that, but it's not working.
Here's my OSCreceiver script (everything else is unmodified from this github repo). What am I doing wrong?
//You can set these variables in the scene because they are public
public var RemoteIP : String = "127.0.0.1";
public var SendToPort : int = 57131;
public var ListenerPort : int = 57130;
private var controller : Transform;
private var handler : Osc;
static var messages : Array = [0.0,0.0,0.0,0.0,1.0];
public function Start () {
//Initializes on start up to listen for messages
//make sure this game object has both UDPPackIO and OSC script attached
var udp : UDPPacketIO = GetComponent("UDPPacketIO");
udp.init(RemoteIP, SendToPort, ListenerPort);
handler = GetComponent("Osc");
handler.init(udp);
handler.SetAddressHandler("/3d/mod1", ListenEvent);
handler.SetAddressHandler("/3d/mod2", ListenEvent);
handler.SetAddressHandler("/3d/mod3", ListenEvent);
handler.SetAddressHandler("/3d/mod4", ListenEvent);
handler.SetAddressHandler("/3d/scenenext", ListenEvent);
handler.SetAddressHandler("/3d/sceneprev", ListenEvent);
// handler.SetAddressHandler("/3d/cam1", ListenEvent);
// handler.SetAddressHandler("/3d/cam2", ListenEvent);
// handler.SetAddressHandler("/3d/cam3", ListenEvent);
// handler.SetAddressHandler("/3d/cam4", ListenEvent);
// handler.SetAddressHandler("/3d/obj1next", ListenEvent);
// handler.SetAddressHandler("/3d/obj1prev", ListenEvent);
// handler.SetAddressHandler("/3d/obj2next", ListenEvent);
// handler.SetAddressHandler("/3d/obj2prev", ListenEvent);
// handler.SetAddressHandler("/3d/width", ListenEvent);
}
public function ListenEvent(oscMessage : OscMessage) : void {
switch(oscMessage.Address){
case "/3d/mod1": i = 0; messages[i] = oscMessage.Values[0]; break;
case "/3d/mod2": i = 1; messages[i] = oscMessage.Values[0]; break;
case "/3d/mod3": i = 2; messages[i] = oscMessage.Values[0]; break;
case "/3d/mod4": i = 3; messages[i] = oscMessage.Values[0]; break;
case "/3d/scenenext": nextScene(); break;
case "/3d/sceneprev": prevScene(); break;
// case "/3d/cam1": break;
// case "/3d/cam2": break;
// case "/3d/cam3": break;
// case "/3d/cam4": break;
// case "/3d/obj1next": break;
// case "/3d/obj1prev": break;
// case "/3d/obj2next": break;
// case "/3d/obj2prev": break;
// case "/3d/eyewidth": break;
}
}
function nextScene() {
Application.LoadLevelAsync(Mathf.Clamp(Application.loadedLevel + 1, 0, Application.levelCount - 1));
}
function prevScene() {
Application.LoadLevelAsync(Mathf.Clamp(Application.loadedLevel - 1, 0, Application.levelCount - 1));
}
Answer by ajm · Apr 05, 2013 at 10:45 AM
Answered it myself: because the listenEvent function runs asynchronously from the main thread, I need to set a variable there and then make an Update() function that checks that variable and then sets the scene.
//You can set these variables in the scene because they are public
public var RemoteIP : String = "127.0.0.1";
public var SendToPort : int;
public var ListenerPort : int = 57130;
private var controller : Transform;
private var handler : Osc;
static var messages : Array = [0.0,0.0,0.0,0.0,1.0];
private var nextSceneGo : boolean;
private var prevSceneGo : boolean;
private var whichCam : GameObject;
private var newCam : GameObject;
static var cam1 : GameObject;
static var cam2 : GameObject;
static var cam3 : GameObject;
static var cam4 : GameObject;
public function Start () {
cam1 = GameObject.Find("_Stereocam1");
cam2 = GameObject.Find("_Stereocam2");
cam3 = GameObject.Find("_Stereocam3");
cam4 = GameObject.Find("_Stereocam4");
whichCam = cam1;
newCam = cam1;
prevSceneGo = false;
nextSceneGo = false;
//Initializes on start up to listen for messages
//make sure this game object has both UDPPackIO and OSC script attached
var udp : UDPPacketIO = GetComponent("UDPPacketIO");
udp.init(RemoteIP, SendToPort, ListenerPort);
handler = GetComponent("Osc");
handler.init(udp);
handler.SetAddressHandler("/3d/mod1", ListenEvent);
handler.SetAddressHandler("/3d/mod2", ListenEvent);
handler.SetAddressHandler("/3d/mod3", ListenEvent);
handler.SetAddressHandler("/3d/mod4", ListenEvent);
handler.SetAddressHandler("/3d/scenenext", ListenEvent);
handler.SetAddressHandler("/3d/sceneprev", ListenEvent);
handler.SetAddressHandler("/3d/cam1", ListenEvent);
handler.SetAddressHandler("/3d/cam2", ListenEvent);
handler.SetAddressHandler("/3d/cam3", ListenEvent);
handler.SetAddressHandler("/3d/cam4", ListenEvent);
// handler.SetAddressHandler("/3d/obj1next", ListenEvent);
// handler.SetAddressHandler("/3d/obj1prev", ListenEvent);
// handler.SetAddressHandler("/3d/obj2next", ListenEvent);
// handler.SetAddressHandler("/3d/obj2prev", ListenEvent);
// handler.SetAddressHandler("/3d/width", ListenEvent);
}
public function Update() {
if(nextSceneGo == true) {
nextSceneGo = false;
nextScene();
}
if(prevSceneGo == true) {
prevSceneGo = false;
prevScene();
}
if(newCam != whichCam) {
switchCam(newCam);
whichCam = newCam;
}
}
public function ListenEvent(oscMessage : OscMessage) : void {
switch(oscMessage.Address){
case "/3d/mod1": i = 0; messages[i] = oscMessage.Values[0]; break;
case "/3d/mod2": i = 1; messages[i] = oscMessage.Values[0]; break;
case "/3d/mod3": i = 2; messages[i] = oscMessage.Values[0]; break;
case "/3d/mod4": i = 3; messages[i] = oscMessage.Values[0]; break;
case "/3d/scenenext": nextSceneGo = true; break;
case "/3d/sceneprev": prevSceneGo = true; break;
case "/3d/cam1": newCam = cam1; break;
case "/3d/cam2": newCam = cam2; break;
case "/3d/cam3": newCam = cam3; break;
case "/3d/cam4": newCam = cam4; break;
// case "/3d/obj1next": break;
// case "/3d/obj1prev": break;
// case "/3d/obj2next": break;
// case "/3d/obj2prev": break;
// case "/3d/eyewidth": break;
}
}
function switchCam(n) {
whichCam.SetActiveRecursively(false);
whichCam.active = true;
newCam.SetActiveRecursively(true);
}
function nextScene() {
Application.LoadLevelAsync(Mathf.Clamp(Application.loadedLevel + 1, 0, Application.levelCount - 1));
}
function prevScene() {
Application.LoadLevelAsync(Mathf.Clamp(Application.loadedLevel - 1, 0, Application.levelCount - 1));
}
Your answer
Follow this Question
Related Questions
The name 'Joystick' does not denote a valid type ('not found') 2 Answers
Fade to white after being killed - iPhone game 2 Answers
How to Make the Game Go to the Next Level When the Music Stops 2 Answers
Different scene depending on level completion time remaining? 1 Answer
Can't get simple script to work? 4 Answers