0
\$\begingroup\$

I'm stuck inside an Action :

socket.On("login", data => {
            Debug.Log("1");
            Debug.Log("2?");
            Debug.Log(gameObject);
            Debug.Log("1^^");
        });

All I get is 1 and 2? on console. After calling the gameObject it freezes. Although other functions work, as they should. But if I just remove that gameObject, it works fine.

I've called gameObject from many different places, they simply log GameObject.

And the method it's referring to, its definition looks something like this :

    public Emitter On(string eventString, Action<object> fn) {
      ListenerImpl listenerImpl = new ListenerImpl(fn);
      return this.On(eventString, (IListener) listenerImpl);
    }

And this is type of System.Action.

Now my question is how can I access gameObject inside Action.

The socket.io library I'm using : https://github.com/Rocher0724/socket.io-unity

And logging outside the closure, it just logs. But when logging inside the library, I get :

UnityEngine.Debug:Log(Object)
<>c__DisplayClass3_0:<ActivePalyerCountStomp>b__0(Object) (at Assets/Scripts/Home.cs:26)
Socket.Quobject.EngineIoClientDotNet.ComponentEmitter.ListenerImpl:Call(Object[]) (at Assets/Socket/Quobject/EngineIoClientDotNet/ComponentEmitter/ListenerImpl.cs:26)
Socket.Quobject.EngineIoClientDotNet.ComponentEmitter.Emitter:Emit(String, Object[]) (at Assets/Socket/Quobject/EngineIoClientDotNet/ComponentEmitter/Emitter.cs:17)
Socket.Quobject.SocketIoClientDotNet.Client.QSocket:OnEvent(Packet) (at Assets/Socket/Quobject/SocketIoClientDotNet/Client/QSocket.cs:207)
Socket.Quobject.SocketIoClientDotNet.Client.QSocket:OnPacket(Packet) (at Assets/Socket/Quobject/SocketIoClientDotNet/Client/QSocket.cs:178)
Socket.Quobject.SocketIoClientDotNet.Client.QSocket:<SubEvents>b__21_0(Object) (at Assets/Socket/Quobject/SocketIoClientDotNet/Client/QSocket.cs:59)
Socket.Quobject.EngineIoClientDotNet.ComponentEmitter.ListenerImpl:Call(Object[]) (at Assets/Socket/Quobject/EngineIoClientDotNet/ComponentEmitter/ListenerImpl.cs:26)
Socket.Quobject.EngineIoClientDotNet.ComponentEmitter.Emitter:Emit(String, Object[]) (at Assets/Socket/Quobject/EngineIoClientDotNet/ComponentEmitter/Emitter.cs:17)
Socket.Quobject.SocketIoClientDotNet.Client.Manager:OnDecoded(Packet) (at Assets/Socket/Quobject/SocketIoClientDotNet/Client/Manager.cs:233)
Socket.Quobject.SocketIoClientDotNet.Client.Manager:<OnOpen>b__50_1(Object) (at Assets/Socket/Quobject/SocketIoClientDotNet/Client/Manager.cs:217)
Socket.Quobject.EngineIoClientDotNet.ComponentEmitter.ListenerImpl:Call(Object[]) (at Assets/Socket/Quobject/EngineIoClientDotNet/ComponentEmitter/ListenerImpl.cs:26)
Socket.Quobject.EngineIoClientDotNet.ComponentEmitter.Emitter:Emit(String, Object[]) (at Assets/Socket/Quobject/EngineIoClientDotNet/ComponentEmitter/Emitter.cs:17)
Socket.Quobject.SocketIoClientDotNet.Parser.Decoder:Add(String) (at Assets/Socket/Quobject/SocketIoClientDotNet/Parser/Parser.cs:120)
Socket.Quobject.SocketIoClientDotNet.Client.Manager:OnData(String) (at Assets/Socket/Quobject/SocketIoClientDotNet/Client/Manager.cs:225)
Socket.Quobject.SocketIoClientDotNet.Client.Manager:<OnOpen>b__50_0(Object) (at Assets/Socket/Quobject/SocketIoClientDotNet/Client/Manager.cs:209)
Socket.Quobject.EngineIoClientDotNet.ComponentEmitter.ListenerImpl:Call(Object[]) (at Assets/Socket/Quobject/EngineIoClientDotNet/ComponentEmitter/ListenerImpl.cs:26)
Socket.Quobject.EngineIoClientDotNet.ComponentEmitter.Emitter:Emit(String, Object[]) (at Assets/Socket/Quobject/EngineIoClientDotNet/ComponentEmitter/Emitter.cs:17)
Socket.Quobject.EngineIoClientDotNet.Client.Socket:OnPacket(Packet) (at Assets/Socket/Quobject/EngineIoClientDotNet/Client/Socket.cs:236)
Socket.Quobject.EngineIoClientDotNet.Client.EventPacketListener:Socket.Quobject.EngineIoClientDotNet.ComponentEmitter.IListener.Call(Object[]) (at Assets/Socket/Quobject/EngineIoClientDotNet/Client/Socket.cs:490)
Socket.Quobject.EngineIoClientDotNet.ComponentEmitter.Emitter:Emit(String, Object[]) (at Assets/Socket/Quobject/EngineIoClientDotNet/ComponentEmitter/Emitter.cs:17)
Socket.Quobject.EngineIoClientDotNet.Client.Transport:OnPacket(Packet) (at Assets/Socket/Quobject/EngineIoClientDotNet/Client/Transport.cs:115)
Socket.Quobject.EngineIoClientDotNet.Client.Transport:OnData(String) (at Assets/Socket/Quobject/EngineIoClientDotNet/Client/Transport.cs:105)
Socket.Quobject.EngineIoClientDotNet.Client.Transports.WebSocket:ws_MessageReceived(Object, MessageReceivedEventArgs) (at Assets/Socket/Quobject/EngineIoClientDotNet/Client/Transports/WebSocket.cs:64)
Socket.WebSocket4Net.Default.WebSocket:FireMessageReceived(String) (at Assets/Socket/WebSocket4Net/Default/WebSocket.cs:295)
Socket.WebSocket4Net.Command.Text:ExecuteCommand(WebSocket, WebSocketCommandInfo) (at Assets/Socket/WebSocket4Net/Command/Text.cs:5)
Socket.WebSocket4Net.Default.WebSocket:ExecuteCommand(WebSocketCommandInfo) (at Assets/Socket/WebSocket4Net/Default/WebSocket.cs:389)
Socket.WebSocket4Net.Default.WebSocket:OnDataReceived(Byte[], Int32, Int32) (at Assets/Socket/WebSocket4Net/Default/WebSocket.cs:399)
Socket.WebSocket4Net.Default.WebSocket:client_DataReceived(Object, DataEventArgs) (at Assets/Socket/WebSocket4Net/Default/WebSocket.cs:201)
Socket.WebSocket4Net.SuperSocket.ClientEngine.ClientSession:OnDataReceived(Byte[], Int32, Int32) (at Assets/Socket/WebSocket4Net/SuperSocket.ClientEngine/ClientSession.cs:114)
Socket.WebSocket4Net.SuperSocket.ClientEngine.AsyncTcpSession:ProcessReceive(SocketAsyncEventArgs) (at Assets/Socket/WebSocket4Net/SuperSocket.ClientEngine/AsyncTcpSession.cs:62)
Socket.WebSocket4Net.SuperSocket.ClientEngine.AsyncTcpSession:SocketEventArgsCompleted(Object, SocketAsyncEventArgs) (at Assets/Socket/WebSocket4Net/SuperSocket.ClientEngine/AsyncTcpSession.cs:25)
System.Threading._ThreadPoolWaitCallback:PerformWaitCallback()

And this socket.on is being called from Start() directly. No additional context.

Main purpose of this is to get some component of that gameobject :

        string playerRoute = Defaults.baseApi + "/player/count";
        JsonRestClient restClient = GetComponent<JsonRestClient>();
        restClient.Get<BaseDto>(playerRoute, "onSuccess", "onError");
\$\endgroup\$
5
  • 1
    \$\begingroup\$ This is telling you that you're trying to access the game object outside of the main thread, which is not something that Unity supports. If you have an actual application to serve, you can ask how to serve that application and we can suggest thread-safe ways to do that. \$\endgroup\$
    – DMGregory
    Jun 3, 2021 at 5:53
  • \$\begingroup\$ @DMGregory then I'm making some network call, but for that first I need reference to that gameobject. Then I can do other stuffs. So, can you suggest me some way now ? Added details on question... \$\endgroup\$ Jun 3, 2021 at 5:57
  • 2
    \$\begingroup\$ One common approach with networked games is to have something like a ConcurrentQueue where you put the incoming messages (e.g. the data you're receiving). Then on the main thread you consume the queue. \$\endgroup\$
    – Saturn
    Jun 3, 2021 at 6:44
  • \$\begingroup\$ @Oxide I'd say that's worth posting as an answer, especially if you can show a sample of how to set up such a producer-consumer queue. \$\endgroup\$
    – DMGregory
    Jun 3, 2021 at 10:39
  • \$\begingroup\$ that worked... @Oxide thanks ... and here is the linked i got... and someone else also suggested this on discord : stackoverflow.com/a/53818416/10305444 \$\endgroup\$ Jun 3, 2021 at 10:43

1 Answer 1

0
\$\begingroup\$

I have been using this solution to this problem. Create a script with this code and attach it to a Game Object:

using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using UnityEngine;

public class ExecuteOnMainThread : MonoBehaviour {

    public static readonly ConcurrentQueue<Action> RunOnMainThread = new ConcurrentQueue<Action>();
        
    void Update()
    {
        if(!RunOnMainThread.IsEmpty)
        {
           while(RunOnMainThread.TryDequeue(out var action))
           {
             action?.Invoke();
           }
        }
    }
}

Then when you need to call something on the main thread and access the Unity API from any other function in your application:

ExecuteOnMainThread.RunOnMainThread.Enqueue(() => {

    // Code here will be called in the main thread...

});

Solution from: https://stackoverflow.com/a/53818416/10305444

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .