#Error to change scene in static function

1 messages · Page 1 of 1 (latest)

dusky heart
wintry atlas
#

LoadScene will occur on the next frame, not immediately

#

(I'm not sure if that's the problem, just pointing that out)

dusky heart
#

Never change it

wintry atlas
#

Also, LoadScene will only work if the scene has been added to the list in build settings

#

File -> Build Settings

dusky heart
#

Is added too if i change LoadScena to function not static work

wintry atlas
#

swapScene isn't a static function in the example you posted above

#

It's an instance function on an object that you have stored in a static field

dusky heart
#

Not buy i call of a static reference of the class

wintry atlas
#

Yeah

dusky heart
#

and i thing this is the problem

#

But cant find nothing

#

i try to make static swapScene() and call it direcly out statiic reference but same result

wintry atlas
#

As in:

public static void SwapScene()
{
    Debug.Log("A");
    SceneManager.LoadScene("Lobby");
    Debug.Log("B");
}
HomeManager.SwapScene();

?

dusky heart
#

Yes

#

and same result i see debug of A and dont change scene and B dont apear

wintry atlas
#

And there are no errors?

dusky heart
#

No, i dont have errors

#

xD

wintry atlas
#

That's... really strange, the B log should appear

#

If it doesn't, the game should hang

dusky heart
#

It doesn't hang either, I can click on other buttons and so on

wintry atlas
#

What does the code calling SwapScene look like?

dusky heart
#
using System.Net;
using UnityEngine;
using WebSocketSharp;
public class SockedManager
{
    private static IPEndPoint server_endpoint = new IPEndPoint(ServerConfig.SERVER_IP, ServerConfig.SERVER_PORT);
    private static WebSocket ws = new WebSocket("ws://" + server_endpoint.ToString());

    public static void connect()
    {
        ws.Connect();
        ws.OnMessage += (sender, e) =>
        {
            eventManager(e.Data);
        };
    }
    public static void createRoom()
    {
        EventBase createRoom = new EventBase(ProtocolType.CreateRoom);
        ws.Send(JsonUtility.ToJson(createRoom));
    }

    public static void joinRoom(string roomId)
    {
        EventBase joinRoom = new EventBase(ProtocolType.JoinRoom, roomId);
        ws.Send(JsonUtility.ToJson(joinRoom));
    }

    private static void eventManager(string data)
    {
        EventBase eventIn = JsonUtility.FromJson<EventBase>(data);
        Debug.Log(data);
        switch (eventIn.type)
        {
            case ProtocolType.CreateRoom:
                DataClass.ROOM_ID = eventIn.roomId;
                DataClass.INSTANCE_HOME_MANAGER.swapScene();
                DataClass.IS_OWNER = true;
                break;
            case ProtocolType.JoinRoom:
                DataClass.ROOM_ID = eventIn.roomId;
                if (eventIn.user.id.Equals(DataClass.USER_ID))
                {
                    DataClass.INSTANCE_HOME_MANAGER.swapScene();
                }
                else
                {
                     DataClass.INSTANCE_LOBBY_MANAGER.userConnect(eventIn.user.name);
                }

                break;
            default:
                break;
        }
    }
}
#

Like thiis xD

wintry atlas
#

Okay yeah that is... really odd

dusky heart
#

my code or the problem?

wintry atlas
#

The problem

dusky heart
#

xD

wintry atlas
#

There doesn't seem to be any obvious cause

dusky heart
#

I hace same problem with DataClass.INSTANCE_LOBBY_MANAGER.userConnect(eventIn.user.name);

#

is called but dont work code in

#

xD

#

for this my focus is in static

#

im not sure

#

i restart unity and pc and nothing is not Unity bug

#

too

wintry atlas
#

The strange part is that the B log doesn't appear. If LoadScene is failing you should get an error, if there's no error then the code should continue, but it seems to just... stop?

#

But this isn't a coroutine or an async function so it shouldn't be possible for that to happen

dusky heart
#

yhea

wintry atlas
#

Just as a test, what if you do LoadSceneAsync?

dusky heart
#

Okey try now

#

same xD

wintry atlas
#

I think your PC might be haunted lol

dusky heart
#

hahaha

#

i was working with sockets and they are the trigger off this calls

#

but i thing this is not a problem when logs apear

wintry atlas
#

Hmm, maybe do you have errors hidden by accident?

dusky heart
#

no xD

wintry atlas
#

Like these buttons

dusky heart
#

i have all enable

wintry atlas
#

Okay yeah that's weird then lol

#

What on earth

dusky heart
#

i open same thread in other comunitys and nothing

#

tbh none body response me xD

wintry atlas
#

Hmm actually

#

Can you try this:

public void swapScene()
{
    try
    {
        Debug.Log("A");
        SceneManager.LoadScene(sceneName: "Lobby");
        Debug.Log("B");
    }
    catch (Exception ex)
    {
        Debug.LogException(ex);
        throw;
    }
}
#

I think I know what's going on now

#

and if I'm right, you will get an error when you try that

dusky heart
#

Yes i get error 🙂

wintry atlas
#

Okay, I know what's wrong then

#

So, you're calling this in a callback from a web socket right?

#

That means this function isn't being called on Unity's main thread, it's being called from a separate background thread

dusky heart
#
UnityException: LoadSceneAsyncNameIndexInternal can only be called from the main thread.
Constructors and field initializers will be executed from the loading thread when loading a scene.
Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function.
UnityEngine.SceneManagement.SceneManagerAPIInternal.LoadSceneAsyncNameIndexInternal (System.String sceneName, System.Int32 sceneBuildIndex, UnityEngine.SceneManagement.LoadSceneParameters parameters, System.Boolean mustCompleteNextFrame) (at <ab7de6937a4448b0a6ccd59e9820599a>:0)
UnityEngine.SceneManagement.SceneManagerAPI.LoadSceneAsyncByNameOrIndex (System.String sceneName, System.Int32 sceneBuildIndex, UnityEngine.SceneManagement.LoadSceneParameters parameters, System.Boolean mustCompleteNextFrame) (at <ab7de6937a4448b0a6ccd59e9820599a>:0)
UnityEngine.SceneManagement.SceneManager.LoadSceneAsyncNameIndexInternal (System.String sceneName, System.Int32 sceneBuildIndex, UnityEngine.SceneManagement.LoadSceneParameters parameters, System.Boolean mustCompleteNextFrame) (at <ab7de6937a4448b0a6ccd59e9820599a>:0)
UnityEngine.SceneManagement.SceneManager.LoadSceneAsync (System.String sceneName, UnityEngine.SceneManagement.LoadSceneParameters parameters) (at <ab7de6937a4448b0a6ccd59e9820599a>:0)
UnityEngine.SceneManagement.SceneManager.LoadSceneAsync (System.String sceneName) (at <ab7de6937a4448b0a6ccd59e9820599a>:0)
HomeManager.swapScene () (at Assets/Scrips/Managers/Scenes/HomeManager.cs:39)
UnityEngine.Debug:LogException(Exception)
HomeManager:swapScene() (at Assets/Scrips/Managers/Scenes/HomeManager.cs:44)
SockedManager:eventManager(String) (at Assets/Scrips/Connections/SockedManager.cs:37)
<>c:<connect>b__2_0(Object, MessageEventArgs) (at Assets/Scrips/Connections/SockedManager.cs:14)

wintry atlas
#

You can only use the Unity API on the main thread

#

Yup

#

So you need to dispatch the function to the main thread

#

I have some code for this you can use

#

and then instead of DataClass.INSTANCE_HOME_MANAGER.swapScene();

#

you can do

#
MainThread.Send(_ =>
{
    DataClass.INSTANCE_HOME_MANAGER.swapScene();
}, null);
#

You can also do MainThread.Send(_ => DataClass.INSTANCE_HOME_MANAGER.swapScene(), null); if you prefer one line

dusky heart
#

xD

#

i make it online im traying

#

this work 🙂

#

Ty man

wintry atlas
#

Awesome

#

So yeah, the problem was that the code wasn't running on the main thread

#

And Unity won't show errors from other threads in the console

dusky heart
#

Is there any way to know if I'm on the main thread?

wintry atlas
#

if (Thread.CurrentThread == MainThread.Instance)

dusky heart
#

🙂

wintry atlas
#

Hope that was helpful!

dusky heart
#

public abstract class ApplicationCommand 
{
  public abstract void Execute();
}

public class ApplicationCommandBuffer : MonoBeahviour
{
  public static ApplicationCommandBuffer Instance { get; private set; }
  private Queue<ApplicationCommand> _commands { get; } = new Queue<ApplicationCommand>();

  private void Awake() => Instance = this;  
  public void Execute(ApplicacionCommand command) => _commands.Enqueu(command);
  private void Update() => while(_commands.Count > 0) _commands.Dequeu().Execute();

}
 
public class SwapSceneApplicacionCommand : ApplicationCommand
{
  private string _sceneName { get; }

  public SwapSceneApplicacionCommand (string sceneName) => _sceneName = sceneName;

  public override void Execute() => SceneManager.LoadScene(_sceneName);
}
#

in other thread tell me this too

wintry atlas
#

There's also if (Environment.CurrentManagedThreadId == MainThread.ManagedThreadId)

#

Which is probably the best way

wintry atlas