,how can I reference C# function and js function from each other

I have a module for client socketing, it’s written in c#, to send messages and handle messages. I need to call this C# send message from js file. and that’s fine. I have a reference of this C# object in the js file.

but my problem is when I received messages from remote and need to call some different js functions from C# to handle different messages, I don’t know how to do this.

I can’t have a reference of js file in my C# file.
I use GameObject.SendMessage to call some function I got a error:“ToString can only be called from the main thread” .

any one can help me here?

So you’ve got two problems:

  • You can call JS from C# or you can call C# from JS but you can’t do both with the same script as you’ve realised - you can’t order the scripts to make both work, because of compiling order. (One of them has to be a plugin or a standard asset, the other has to be in a later compiled script - check out the compilation order.
  • Your socket reception appears to not be happening on the main thread - no idea what the ToString is about as I can’t see your code.

So the only answer is the to do something on the main thread, invoked from the socket thread.

I do that using the script below:

#Loom.cs#

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using System.Threading;
using System.Linq;
		
public class Loom : MonoBehaviour
{
	private static Loom _current;
	private int _count;
	
	public static Loom Current
	{
		get
		{
			if (_current == null)
			{
				var g = new GameObject("Loom");
				_current = g.AddComponent<Loom>();
			}
					
			return _current;
		}
	}
	
	private List<Action> _actions = new List<Action>();
	public class DelayedQueueItem
	{
		public float time;
		public Action action;
	}
	private List<DelayedQueueItem> _delayed = new  List<DelayedQueueItem>();
			
	public static void QueueOnMainThread(Action action, float time = 0f)
	{
		if (time != 0)
		{
			lock (Current._delayed)
			{
				Current._delayed.Add(new DelayedQueueItem { time = Time.time + time, action = action});
			}
		}
		else
		{
			lock (Current._actions)
			{
				Current._actions.Add(action);
			}
		}
	}
			
	public static void RunAsync(Action a)
	{
		var t = new Thread(RunAction);
		t.Priority = System.Threading.ThreadPriority.AboveNormal;
		t.Start(a);
	}
			
	private static void RunAction(object action)
	{
		((Action)action)();
	}
			
	void OnDisable()
	{
		if (_current == this)
		{
					
			_current = null;
		}
	}
			
	// Update is called once per frame
	void Update()
	{
		var actions = new List<Action>();
		lock (_actions)
		{
			actions.AddRange(_actions);
			_actions.Clear();
		}
		foreach (var a in actions)
		{
			a();
		}
		var delayList = new List<DelayedQueueItem>(); 
		lock (_delayed)
		{
			delayList.AddRange(_delayed);
		}
		foreach (var delayed in delayList.Where(d=>d.time <= Time.time).ToList())
		{
			lock (_delayed)
			{
				_delayed.Remove(delayed);
			}
			delayed.action();
		}
				
				
				
	}
}

And use it by calling this (you’d put it in your socket reception code):

   Loom.QueueOnMainThread( ()=>{
         //Your send message here
   });

Hi,

You are likely mixing classes that do not extends monobehavior and classes that do, and I had the same problem. the issue was the following
It turned in my case that I was debugging a class, and so the ToString() was called internaly, so I removed my debug.Log() and it was better. the other issue I had then ( it’s all related I feel), is that I can comparing a class against null to see if it existed ( myClass != null) and that was also an issue in the same “stack of call”, so removed that and it now all works fine.

Hope it helps,

Jean