#Running Multiple Servers

95 messages · Page 1 of 1 (latest)

granite oyster
#

What would be the best way to have different servers for different zones and have players be able to move through them in an MMO environment. So the servers would need to be able to communicate with each other to check that a player entering the zone arrived legitimately. Also would be nice for players to be able to message each other whilst in different zones etc.

#

@meager juniper I'm not sure if many people will have the answers to this other than you tbh

meager juniper
#

Web service would handle all authentication, and spinning up of game server instances, each of which would make API calls back to the web service letting it know it's up, going down, or needs to authenticate or transfer a client

#

Clients get tokens and connection endpoint from web service as part of authentication response, client connects as instructed with token, game server calls API with token to get player details it needs, accepts player to join that server

#

At some point, e.g. a portal or w/e, server determines client needs to be transferred, calls API with token and which Zone client needs to go to in a TransferRequest, response has new connection details, which are sent to client in a NetworkMessage to Transfer with those details. Web service updates itself / db as to which server / zone player is allowed into. Client disconnects and reconnects as instructed, same token API call process as before.

#

All that can be automated so it's frictionless, but takes a few seconds, because client needs to change scenes along the way, so a fade out > fade in would probably be needed with either a splash UI or just a black UI to cover the transition.

#

If you offload "chat" to a separate service that all clients connect to (again with token from web service) via some simple TCP Secure Client, then that would satisfy your cross-talk requirement. and keep chat traffic off the game network.

#

maybe even Discord could provide that...dunno.

granite oyster
#

Thanks for the response. I hadn't thought of using my database to validate for some reason for this problem, even though I use it for all the others. I wonder if anyone has made any chat functions that are kept off unity. That would be good

granite oyster
#

@meager juniper Would running multiple servers locally be possible for testing?

granite oyster
#

@meager juniper Once I figure out how to get 2 instances of Unity running in server mode which I'm hoping I can manage myself I wonder how my client will differentiate between them when swapping between them. The servers I run on AWS will have different IPs so that should be no problem.

meager juniper
#

maybe I misunderstood between multiple instances of the game server app on one server machine, vs separate server machines each with one server app running

granite oyster
#

Ah ok Thanks I'll look into this!

granite oyster
#

@meager juniper Would simply referencing the transport and changing the value be a clean way to handle different ports?

granite oyster
#

Telepathy

#

It has a field, port = 7777. If I change to 7776 then start server, then have my client have it on 7776 when he starts client. Would this work fine?

meager juniper
#

((TelepathyTransport)Transport.active).port = 7776;

granite oyster
#

Oh Ok I'll look for this

meager juniper
#

for your headless server, you can pass command line args to it to tell it what port to listen to

#

e.g. MyGame.exe /p:7776

meager juniper
# granite oyster Oh Ok I'll look for this

In your custom Network Manager, override Awake...

    public override void Awake()
    {
        // This will set the singleton and Transport.active
        base.Awake();

#if UNITY_SERVER
        foreach (string arg in Environment.GetCommandLineArgs())
        {
            // Get the port from the cmd line...default is 7777
            if (arg.StartsWith("/p:", StringComparison.InvariantCultureIgnoreCase))
                if (ushort.TryParse(arg.Remove(0, 3), out ushort port))
                    ((TelepathyTransport)Transport.active).port = port;
        }
#endif
    }
granite oyster
#

@meager juniper When I connect to Mirror from an offline screen it creates a player prefab. When I connect to another server whilst being online it doesnt.

#

If I try to StopClient(), wait till im disconnected, then StartClient() to another server that doesnt work.

#

How would you handle sending a player from one server to another? Can it all be done by the server?

meager juniper
#

also inspector of your custom Network Manager

granite oyster
#

So this code works if you just have it ran seperately

#

but when i stopclient the rest of the code wont run

#

and if i remove stop client the player prefab doesnt spawn in

#

@meager juniper

granite oyster
meager juniper
meager juniper
# granite oyster https://pastie.io/rvdhdc.cs

not enough context, really. If there's an offline scene, StopClient will switch the client to the offline scene automatically, which is probably not what you want, since the offline scene will likely have content suitable for an offline client just starting the app.

#

Additionally, when Mirror switches to the offline scene, Network Manager is pushed out of DDOL and destroyed so you get a whole new one in the Offline scene where it originates.

#

So you'll need to do a few extra things for transfers....

#
  1. when server tells client to transfer, the code to handle that should be within your custom network manager, because that will be the most convenient, and that's already in DDOL.
#
  1. When a transfer message comes to client, set offlineScene to null (prevents the switch), but you'll need to keep a ref to that so you can set it back before calling StartClient again (in case new server tells to to buzz off)
granite oyster
#

Ah ok thanks ill give that a go now

meager juniper
#

Then set new endpoint in networkAddress. You still have NetworkAuthenticator, so you still have your token, which will be sent to the new server

#

Then you can call StopClient, yield a frame or two, then re-assign the offlineScene and call StartClient

#

@granite oyster

#

New server will automatically tell client what scene to load (which will be whatever server has for active scene at the time)

granite oyster
meager juniper
granite oyster
#

yield return new WaitForEndOfFrame();

#

Just to let it all finish before moving on?

meager juniper
#

yield return null;

#

Under the hood there's a round trip to the transport and some cleanup that happens in the transport and events raised by the transport

#

user will never notice a frame or 2 being skipped

#

especially given the need to load a new scene, all probably happening behind a cross-fade

granite oyster
#

Maybe yield return new WaitForSeconds(0.5f)?

#

the yield return null would stop everything beneath from running?

meager juniper
#

won't need that long.. 1 or 2 frames will do

granite oyster
#

really?

#

oh ok so null just waits till next frame then continues?

meager juniper
#

yield return null; just skips to the next frame before proceeding

granite oyster
#

oh right, so just post 2 of them beneath StopClient?

meager juniper
#

at least 1, and make a note that you might need 2 if you see glitchy behaviour

granite oyster
#

Well I'd been using yield return null as the same as return in my scripts and had never noticed issues xD

meager juniper
#

This is not at all right 🙂

yield return null as the same as return

granite oyster
#

xD

meager juniper
#

How's your custom Network Manager shaping up?

pastel pendant
#

@granite oyster Without knowing how you'd integrate it into the client itself I think Redis pub/sub is a quite nice tech for a game chat. But like I said, I'm not sure how you integrate it, maybe you wrap it with a barebones websocket API(maybe at that point you just build it around a normal database instead)? Just throwing ideas out there.

granite oyster
granite oyster
#

Have the scene interest management for all the menus which will be on my main server

#

then each zone will have its own server running it

meager juniper
granite oyster
#

Yeah I'm using it with my own visuals it's very useful

meager juniper
#

if you're doing a cross-fade with the transfer, you can yield return FadeIn(); after StopClient...the fade time will cover the transfer and scene change

granite oyster
#

Yeah that's likely what I'll go for

meager juniper
granite oyster
#

Otherwise the player will see their character loading all his weapons and looks 😄

#

Yeah I'll be doing a bit of both

#

Maybe have a single server handle a few scenes together

meager juniper
#

scene interest management requires additive scenes

granite oyster
#

yeah I was thinking for the server running 'zone 2' for example I will have anyone who enters the server be sent there right away. All servers will have all of the zones so it will be like its just using additive scenes

#

Gives me a bit of flexibility. I could have a few zones on a single server or separate servers this way i figure

#

So you connect to the server, it will check the database for where you should be and what character. Then move you to it

meager juniper
#

Just send the scene message with the additive sceneOperation before you instantiate > move > spawn the player

granite oyster
#

@meager juniper If I have a While loop running in a coroutine and I want to leave the coroutine after lets say a number of times. If yield return null just waits a frame how do you do the 'return' to get out of the loop and out of the coroutine?

#

@meager juniper When I load into a new server with a new port can I prevent the online scene loading?

#

So that I can load only the scene I want

meager juniper
meager juniper
#

so your online scene is mostly empty...think of it as a container, generally, and then you load additives on top of that

granite oyster
meager juniper
granite oyster
meager juniper
#

I ask because the Additive Levels network manager has 2 methods in "Server System Callbacks" region you should take a look at for getting the player into the game