Hello,
I am working on a VR app on Meta Quest 2 with the current goal to add LAN multiplayer. I thought it would be good enough to go for a “basic” host/client structure.
From a practical point of view, it allowed me to re-use most of the code from the Boss Room project (thank you very much for anyone who worked on that demo project).
The target use case is to have 1 router, 3-4 players with Quests 2 connected to it, one hosts the session and the rest join.
That seemed very straightforward to me because I had no problem doing the same thing already with test projects. Meaning I have already built host/client stuffs for 2 windows computers (one is 10, the other 11) connected to the same router. Since I didn’t struggle whatsoever, I thought the step for having 3-4 Quests connected together on the same router was going to be reasonnable.
During development, I tested with 2 clients on the local host 127.0.0.1 port 7777 with ParrelSync. I have RPCs, NetworkVariables, cutsom serialization and the usual stuff you can expect with NetCode for GameObjects. And everything eventually worked fine (well, it’s localhost…).
Now, for deployment tests, I built the app and installed the Apk file on one Quest. And, to have access to the debug console, I connect the second headset to Unity via Oculus LINK (USB 3.0 cable) I connect both Quests to the router via WiFi and so they have IP of the format 192.162.x.xxx.
In game, I have a menu to let the Host and other clients give the Target IP and Port information. That means, if the Quest that is about to host has an IP of, say, 192.168.2.2 then I type that in the dedicated field (I use a default value of 7777 for the port). Then click my “Host” button. There, it crashes. To avoid app freezing, I have it restart on 127.0.0.1.
/// <summary>
/// Initializes host mode on this client. Call this and then other clients
/// should connect to us!
/// Uses the IP and port registered in <see cref="m_Settings"/>.
/// </summary>
public void StartHost()
{
Debug.Log("NetManager call to Start host");
SetUnityTransport();
if (NetManager.IsHost)
{
Debug.Log("NetManager was already running so we are shutting down before re-launching");
StartCoroutine(Restart());
}
else
{
NetManager.StartHost();
}
}
public void SetUnityTransport()
{
UnityTransport unityTransport = NetworkManager.Singleton.gameObject.GetComponent<UnityTransport>();
unityTransport.SetConnectionData(m_Settings.IP, (ushort)m_Settings.port);
Debug.Log($"Setting up transport connection to {unityTransport.ConnectionData.Address}: {unityTransport.ConnectionData.Port}");
}
/// <summary>
/// Shuts down the current session and starts a new one as a host.
/// </summary>
IEnumerator Restart()
{
Debug.Log($"Shutting down");
NetManager.Shutdown();
yield return new WaitForEndOfFrame();
Debug.Log($"Restarting a host");
bool isHostStarted = NetManager.StartHost();
string msg;
if (!isHostStarted)
{
msg = "<color=red>Host couldn't be started: bind and listening to " + m_Settings.IP + ":" + m_Settings.port + " failed.\n" + "Falling back to 127.0.0.1:7777</color>";
SetConnectionSettings(m_Settings.playerName, "127.0.0.1", 7777, m_Settings.password);
StartHost();
yield return new WaitForSeconds(1f);
MultiplayerMenuManager.SetMessage(msg);
}
}
If it didn’t crash, I would type in the same IP and click the “Join” Button on the other Quest. Basically the equivalent of what I did for my tests on Windows machines and it worked just fine.
As you can see in the code above, the IP and Port info is set in UnityTransport Connection Data.
With the Debug.Log()
, I can confirm that my in-game menu works well and that there were no mistake when the IPs and Port were typped in.
Unfortunately, the server never manages to bind whichever Quest I try with (the one with the build nor the one connected to Unity); as it says with the “Server can’t bind” Debug.LogError()
that you can find in the ServerBindAndListen(NetworkEndPoint endPoint)()
method that is called by StartServer()
of UnityTransport.cs (All this coming from StartHost()
of NetworkManager).
My assumption was that starting a host on a Quest was not going to be any different from starting a host on a Windows machine despite the obvious differences in OS. But, after about 20 hours of searching with no progress I’m starting to think that I missing something obvious. I even started to try Port Forwarding even if that makes no sense for devices that are on the same router(…right? please, I’m starting to doubt everything)
So, is there anything different about hosting sessions on Android compared to Windows? Anyone with a suggestion on how to start debuging this? UnityTransport is apparently an immutable asset so I couldn’t try to Debug.Log() and see if there are some issues with Android on that side.