com.unity.netcode.gameobjects
com.unity.netcode.gameobjects copied to clipboard
feat: Single player hosting in WebGL using RPC
Expose the ability to use RPC especially on WebGL to allow us to easily make a single player mode while still using netcode usually as a host.
Changelog
- Added: The ability to use RPC using a property in the Transport.
- Changed: Allowed the ability to host a game if using RPC in WebGL to allow us to easily create a single player mode.
Testing and Documentation
- No tests have been added.
- No documentation changes or additions were necessary.
@BenHamrick Where is the RPCNetworkInterface type defined? I tried to add this change but cannot find such a class in the entire codebase, not even in your fork, and not on the Internet at large.
@BenHamrick Where is the
RPCNetworkInterfacetype defined? I tried to add this change but cannot find such a class in the entire codebase, not even in your fork, and not on the Internet at large.
My bad! It's supposed to be IPCNetworkInterface
@BenHamrick You can opt to assign or create your own NetworkTransport that you switch to when running in a single player mode. You can make that implementation a "mock transport". You can see an example of a mock transport here. Since you don't need any network connectivity in single player (other than services possibly which doesn't use UTP), all netcode related scripts should work. If you feel that this is not enough could you provide a working example for this PR so we can review it?
@NoelStephensUnity I tried using the mock transport but it seems like NetworkManager.RealTimeProvider is private so the script won't work as is. Also seems a little extreme to require me to make a whole new transport to run my game in single player. Is there maybe a more complete example somewhere I can use without the private reference? I also fixed this branch to work now.
@NoelStephensUnity I tried using the mock transport but it seems like
NetworkManager.RealTimeProvideris private so the script won't work as is. Also seems a little extreme to require me to make a whole new transport to run my game in single player. Is there maybe a more complete example somewhere I can use without the private reference? I also fixed this branch to work now.
Ahhh... I meant to look at it as an example/reference.
In reality, you really should only need to do something like this:
/// <summary>
/// Add this component to the same GameObject as your NetworkManager
/// </summary>
public class GameModeHandler : MonoBehaviour
{
private NetworkManager m_NetworkManager;
private UnityTransport m_UnityTransport;
private UnityTransport.ConnectionAddressData m_Multiplayer;
private UnityTransport.ConnectionAddressData m_SinglePlayer;
private void Start()
{
m_NetworkManager = GetComponent<NetworkManager>();
if (m_NetworkManager)
{
m_UnityTransport = m_NetworkManager.NetworkConfig.NetworkTransport as UnityTransport;
if (m_UnityTransport)
{
m_Multiplayer = m_UnityTransport.ConnectionData;
}
// Single player would use the device's local/private loopback address
// (i.e. no external client on another device could connect to the session)
m_SinglePlayer.Port = 7777;
m_SinglePlayer.Address = "127.0.0.1";
m_SinglePlayer.ServerListenAddress = "127.0.0.1";
}
}
/// <summary>
/// Invoke this prior to starting NetworkManager
/// </summary>
public void ApplyGameMode(bool isSinglePlayer)
{
if (!m_UnityTransport)
{
Debug.LogError("Transport is not set.");
}
// Defines the transport for single or multiplayer use
m_UnityTransport.UseWebSockets = !isSinglePlayer;
m_UnityTransport.UseEncryption = !isSinglePlayer;
m_UnityTransport.ConnectionData = isSinglePlayer ? m_SinglePlayer : m_Multiplayer;
}
}
Where you just make the single player use the device's local loopback address, use the default port (7777), disable web sockets and encryption, and start the NetworkManager as a host. This would allow you to start a single player game using standard UDP.
The real issue is what builds are available. A WebGL build vs a device specific build... which I will need to look into that side of the equation... because a WebGL build will require the device to host the webservice to deliver the content via browser instance where a device specific build will allow you to launch the game from the device in question (could get tricky depending upon the device and could impact performance depending upon the device).
It might be the simplest answer is to make two builds...but I don't know the specifics of your game/project and if you are trying to provide a way to build upon something in single player and then use progress made in single player within a multiplayer WebGL instance.
@NoelStephensUnity Reason why I am even here is because a player of mine had something running on 7777 and so could not start a server. Probably a second instances of the game 🤷 , but that does not matter here. I would rather run it using IPC that is used for testing anyways so we know it works. I never want to run a server on a port locally, even just by accident, if someone wants to play singe player.
We have now released a SinglePlayerTransport in the 2.4.0 release, and will be bringing this transport into the next release we make for 1.x. Does this SinglePlayerTransport meet your needs?