- Home /
[Multiplayer] Lobby/Staging/Matchmaking flow: Quickstart using NetworkLobbyManager?
12/5 Ditching this post as it's getting confusing and it's more-or-less turned into a journal. QA said "We can't force the devs to answer", so I have a feeling no one knows (or maybe 1 busy person) O__o if you find this on Google, look here for a cleaner post with a more-likely answer.
11/29: Still awaiting an answer -- trial and error can only go so far :/
11/24/2016 Added a question at the bottom (#2: How to access lobbyMgr.OnCallbacks()
?). Also added testing results.
11/23/2016 Added TL;DR @ bottom in answers
11/22/2016: Added CreateMatch/OnCreateMatch and JoinMatch/OnJoinMatch.
11/20/2016: I decided to revamp everything based on my research to make this less confusing.
TL;DR: The API docs for staging, matchmaking, lobby, and anything to do with the NetworkLobbyManager component are abysmal (@Unity I know it's new -- and all your other API docs rock, so I know IN TIME, it will be awesome, it's np -- However, for now, hopefully this thread can help clarify some things for myself and others). Here is my flow to create and join a matchmaking match with lobby. Unity Staff: Please let me know where I'm wrong:
STEP I: EDITOR
Create a LobbyMgr gameObj >> add NetworkLobbyManager component >> Add a NetworkManagerHUD (for testing only).
Create a LobbyPlayer gameObj >> add NetworkLobbyPlayer component. Ensure "Show Lobby GUI" is checked (for testing only). Save as prefab. Delete the gameObj.
Drag the LobbyPlayer prefab into NetworkLobbyManager component.
Create a GamePlayer prefab >> add GamePlayer component. Save as prefab. Delete the gameObj.
Drop GamePlayer prefab into NetworkLobbyManager component.
Create arbitrary named LobbyMain.cs and drop it in NetworkLobbyManager component.
Create a btnMM for matchmaking later. We don't want to use the LobbyGUI by the end of this.
STEP II: SCRIPTING Open up LobbyMain.cs
public class Lobby2 : MonoBehaviour
....
[SerializeField]
private NetworkLobbyManager lobbyMgr;
@Unity - QUESTION: If this inherits from MonoBehaviour, how can I possibly override events such as OnMatchList() and OnMatchCreate()?
Go back to editor >> Drop in your NetworkLobbyManager component.
Now let's add a void for our button click to StartMatchmaker and to list the matches:
public void MMStart()
{
Debug.Log("@ startMM");
lobbyMgr.StartMatchMaker();
MMListMatches();
}
We now have the code to start matchmaker with some TODO's for later.
Let's start with listing - MM is faster if you join a game instead of create your own:
public void MMListMatches()
{
Debug.Log("@ MMListMatches");
int startPageNumber = 0;
int resultPageSize = 10;
string matchNameFilter = "*";
bool filterOutPrivateMatchesFromResults = true;
int eloScoreTarget = 0;
int requestDomain = 0;
lobbyMgr.matchMaker.ListMatches(startPageNumber, resultPageSize, matchNameFilter, filterOutPrivateMatchesFromResults,
eloScoreTarget, requestDomain, OnMatchList);
}
void OnMatchList(bool success, string extendedInfo, List<MatchInfoSnapshot> matchList)
{
Debug.Log("@ OnMatchList");
if (success && matchList.Count > 0)
{
// Join 1st one found? Is this ordered by relevance?
// Is this ordered by players? Is there any order at all?
MMJoinMatch(matchList[0]);
}
else
MMCreateMatch();
lobbyMgr.OnMatchList()
is recommended to use in the API doc examples, however, we cannot override the void (can't do override void lobbyMgr.OnMatchList
). We also can't change our lobby script from Mono (our script HAS to be mono - we can't have 2 LobbyManager classes or they'll conflict). instead, our own callbacks are used - not sure if this is intended or a workaround (docs are a bit conflicting throughout).
So if there was something in the list, we join then callback:
public void MMJoinMatch(MatchInfoSnapshot matchToJoin)
{
Debug.Log("@ MMJoinMatch");
NetworkID netId = matchToJoin.networkId;
string matchPassword = "";
string publicClientAddress = Network.player.externalIP;
string privateClientAddress = Network.player.ipAddress;
int eloScoreForClient = 0;
int requestDomain = 0;
lobbyMgr.matchMaker.JoinMatch(netId, matchPassword, publicClientAddress, privateClientAddress,
eloScoreForClient, requestDomain, OnMatchJoined);
}
public void OnMatchJoined(bool success, string extendedInfo, MatchInfo matchInfo)
{
Debug.Log("@ OnMatchJoined");
if (success && matchInfo != null)
{
Debug.Log("[Match] First Game Sample: " + matchInfo);
}
else
{
currentStatus = mmStatus.stopped;
Debug.Log("[MM] FAILED to join match: " + extendedInfo);
// TODO: Re-join queue..?
}
}
....or if a game wasn't found, create one:
public void MMCreateMatch()
{
Debug.Log("@ CreateMatch");
currentStatus = mmStatus.creating;
string matchName = lobbyMgr.matchName != null ? lobbyMgr.matchName : "MM";
uint matchSize = lobbyMgr.matchSize != null ? lobbyMgr.matchSize : 15;
bool matchAdvertise = true;
string matchPassword = "";
string publicClientAddress = Network.player.externalIP;
string privateClientAddress = Network.player.ipAddress;
int eloScoreForMatch = 0;
int requestDomain = 1;
lobbyMgr.matchMaker.CreateMatch(matchName, matchSize, matchAdvertise, matchPassword, publicClientAddress,
privateClientAddress, eloScoreForMatch, requestDomain, OnMatchCreate);
Debug.Log("[MM] Creating match..");
}
public void OnMatchCreate(bool success, string extendedInfo, MatchInfo matchInfo)
{
Debug.Log("@ OnMatchCreate");
if (success && matchInfo != null)
{
currentStatus = mmStatus.created;
Debug.Log("[MM] Created Match!"];
}
else
{
Debug.Log("[MM] FAILED to create match: " + extendedInfo);
// TODO: Re-join queue?
}
}
What happens when I test this so far?
A clicks matchmaking button
In the background, it lists a match. List callbacks. Nothing there, so create instead of join.
Game is created. Waiting....
B clicks matchmaking button 5. In the background, it SHOULD list a match and join the first[0] match - however, it detects no games in the list and simply creates a game.
Both A and B awkwardly wait for each other - but both CREATED a game. Nothing happens from here.
In the meantime, PlayersGUI shows nothing (because the other didn't join - both created).
Questions/Not Clear:
The OnGUI "Show Lobby GUI", part of the Network Lobby Manager -- it's not even mentioned in the UNetLobby API docs, or anywhere. How can we make our own? I can't find a template/snippet/bitbucket anywhere. EDIT: Found a bitbucket after all, woot :) could use a simplified version in the docs somewhere, though using the new techniques.
[11/24/2016] Even though I keep reading my LobbyScript (attached to the NetworkLobbyManager component) to be Mono, but I still am having trouble with callbacks/sync: For example, it's recommended that I handle callbacks through the lobbyMgr
lobbyMgr.OnMatchList
instead of my own, such asOnMatchListCustom
-- whenever I test it, there's never a game showed up on the LIST, even though it was definitely created! I have a feeling that using my own callback makes things out-of-sync..
So the big question is: Can my LobbyScript.cs derive from NetworkLobbyManager without causing a ton of conflicts and weirdness? -- I tested this and sure, I can now override void OnMatchList()
BUT it never gets fired! Probably because it's on "the other lobby manager (component)?
The bigger question is: HOW can I override the callback of lobbyMgr's OnMatchList? I can't do override void lobbyMgr.OnMatchList
because it's a syntax error. I can't do it with Mono script because it's out of scope. I can't do it with NetworkLobbyManager script because, although it's syntax-free, it's the wrong instance or something - it doesn't fire. 100% of the demos just use 1 giant script instead of the NetworkLobbyManager component, so I'm confused :)
12/5/2016 - I realized that I can lobby$$anonymous$$gr.lobbyPlayerPrefab. and lobby$$anonymous$$gr.gamePlayerPrefab.
Does this mean I should consolidate pre-spawn events with lobby$$anonymous$$gr.lobbyPlayerPrefab, etc? Originally I had a small script. Just a thought. Still testing.
Answer by MrLucid72 · Dec 05, 2016 at 06:15 AM
The answer is .... there is no answer (this page eventually became a journal of notes - confusing now). The docs, demos, and even their bitbucket are all outdated and no Unity staff seems to actually know the answer - Direct support tickets don't even have an answer. The answer is to
1) Wait for an update, which will eventually come (their docs/demos are all AWESOME... except for matchmaking and lobby). Hell, it could even be a bug -- we don't know because there's no communication about this :/
2) If you found this from Google hoping for an answer -- For a cleaner, more-likely updated Q+A, Look here (I started to pay for an answer): https://forum.unity3d.com/threads/25-bounty-using-the-networklobbymanager-component-how-do-i-create-list-matches.444436/
Answer by isidro02139 · Nov 16, 2016 at 02:21 AM
Hey man, for what it's worth I have also been struggling with seemingly simple unet things (for the past year...). Part of this is because the unet HLAPI is a general framework and so there is more inherent flexibility, i.e. it's hard to show someone directly how to use it because there are so many different possible goals. In addition, networking code is inherently more complex as you will have two machines executing Unity logic in separate "threads" (a crude analogy, but still) and latency can be highly variable, depending on your setup and network conditions, making repeatability difficult. Testing takes longer too, just from a compiling and running two apps simultaneously perspective.
I found that reading the source really helped me fill in the gaps in the documantation and examples; be careful though, for whatever reasons the bitbucket source isn't always up-to-date with the latest release: https://bitbucket.org/Unity-Technologies/networking/src/e998e3faafcb/Runtime/?at=5.4
For example, you can see at a glance that NetworkLobbyManager inherits from NetworkManager and they both implement a singleton-ish pattern, so you would never need both scripts on the same Lobby object.
Hope this helps, and good luck!
p.s. there is a Slack channel that you may want to join, I find it much more helpful than these forums: unitydevs.slack.com #network
11/23/2016: Added Create$$anonymous$$atch/OnCreate$$anonymous$$atch and Join$$anonymous$$atch/OnJoin$$anonymous$$atch
I will update this potential answer as I update my main thread. The top is detailed, while the potential answer is what I originally was asking about -- the flow. Below is the "official" flow, so far, of what I have working:
STEP I: EDITOR
Create a Lobby$$anonymous$$gr gameObj >> add NetworkLobby$$anonymous$$anager component >> Add a Network$$anonymous$$anagerHUD (for testing only).
Create a LobbyPlayer gameObj >> add NetworkLobbyPlayer component. Ensure "Show Lobby GUI" is checked (for testing only). Save as prefab. Delete the gameObj.
Drag the LobbyPlayer prefab into NetworkLobby$$anonymous$$anager component.
Create a GamePlayer prefab >> add GamePlayer component. Save as prefab. Delete the gameObj.
Drop GamePlayer prefab into NetworkLobby$$anonymous$$anager component.
Create arbitrary named Lobby$$anonymous$$ain.cs and drop it in NetworkLobby$$anonymous$$anager component.
Create a btn$$anonymous$$$$anonymous$$ for matchmaking later. We don't want to use the LobbyGUI by the end of this.
STEP II: SCRIPTING
Serialize
NetworkLobby$$anonymous$$anager lobby$$anonymous$$gr
and drop your gameObj with the NetworkLobby$$anonymous$$anager component in.Add a function to be called from a button to ultimately call
lobby$$anonymous$$gr.Start$$anonymous$$atch$$anonymous$$aker()
, followed by$$anonymous$$$$anonymous$$List$$anonymous$$atches()
void call.In
void $$anonymous$$$$anonymous$$List$$anonymous$$atches()
, calllobby$$anonymous$$gr.match$$anonymous$$aker.List$$anonymous$$atches(startPageNumber, resultPageSize, matchNameFilter, filterOutPrivate$$anonymous$$atchesFromResults, eloScoreTarget, requestDomain, On$$anonymous$$atchList);
$$anonymous$$ake the callback
void On$$anonymous$$atchList(bool success, string extendedInfo, List<$$anonymous$$atchInfoSnapshot> matchList) 5. Inside
On$$anonymous$$atchList()`, check forif (success && matchList.Count > 0)
to ensure there's at least 1 match.IF $$anonymous$$ATCH, call
$$anonymous$$$$anonymous$$Join$$anonymous$$atch(matchList[0])
to join the first match on the list. Optionally validate here ins$$anonymous$$d of the first match. We pass this match as param.IF $$anonymous$$ATCH, inside
void $$anonymous$$$$anonymous$$Join$$anonymous$$atch($$anonymous$$atchInfoSnapshot matchToJoin)
, calllobby$$anonymous$$gr.match$$anonymous$$aker.Join$$anonymous$$atch(netId, matchPassword, publicClientAddress, privateClientAddress, eloScoreForClient, requestDomain, lobby$$anonymous$$gr.On$$anonymous$$atchJoined);
IF $$anonymous$$ATCH, call the callback
OnJoin$$anonymous$$atch(bool success, string extendedInfo, $$anonymous$$atchInfo matchInfo)
.IF $$anonymous$$ATCH, inside check for success
if (success && matchInfo != null)
then success! ( @Unity: Now what? )If no match (forked from #5), create
void $$anonymous$$$$anonymous$$Create$$anonymous$$atch()
Inside
$$anonymous$$$$anonymous$$Create$$anonymous$$atch()
void, call lobby$$anonymous$$gr.match$$anonymous$$aker.Create$$anonymous$$atch(matchName, matchSize, matchAdvertise, matchPassword, publicClientAddress, privateClientAddress, eloScoreFor$$anonymous$$atch, requestDomain, On$$anonymous$$atchCreate2);Create the callback void
void On$$anonymous$$atchCreate(bool success, string extendedInfo, $$anonymous$$atchInfo matchInfo)
Inside
On$$anonymous$$atchCreate()
void, check for successif (success && matchInfo != null)
then success! ( @Unity: Now what? )ShowLobbyGUI?
11/29: Still awaiting an answer -- trial and error can only go so far :/
Tried inheriting my lobbyScript from NetworkLobby$$anonymous$$anager:
On$$anonymous$$atchList() never fires. It probably does fire, but fires on the lobby$$anonymous$$gr's On$$anonymous$$atchList() (different instance?)