#archived-networking
1 messages · Page 36 of 1
public bool gameStarted = false;
void Update()
{
tagged_players_inspector = new List<Player>(tagged_players);
if (!gameStarted && Input.GetKey(KeyCode.K))
{
if (NetworkManager.Singleton.IsServer)
{
print("starting");
startGameServerRpc();
}
}
}
[ServerRpc]
void startGameServerRpc()
{
print("baa");
int randomIndex = UnityEngine.Random.Range(0,PlayerManager.playerObjects.Count);
Player taggedPlayer = PlayerManager.playerObjects[randomIndex].GetComponent<Player>();
tagged_players.Add(taggedPlayer);
taggedPlayer.setTaggedClientRpc();
gameStartTime = Time.time;
startGameClientRpc();
}```
i have this update on my gamemanager object with a server rpc, when i load into the scene it runs fine. when i load into a different scene and then load the scene this code is in again it suddenly doesnt run the server rpc anymore, why is that?
hello, not sure where to ask this but i have plans to make a simple fps shooter with mulitplayer just to get a grasp on lot of things. not going overboard just a simple 1v1. but my main question is that for my player do i make the whole body be visible or only the hands? and if only the hands how can the other player see my player? they cannot no? and is there any good guides or tutorials for making the player and hands and rigging them and importing them to the engine?
for your first game just keep the full body no real need to make it any more complicated than necessary
But you can have a firstperson model and a 3rd person model in the same prefab. There are assets that are just firstperson arms that you can check out
alright, thank you
Using UNET for GO, when the server is running in host mode, is it possible to separate the host client-side from the host server-side logic from running as in the same instance? Like it was running in a dedicated server.
Im having issues with server systems that interferes with client systems and I need them to work independent of each other.
If you mean Netcode for GameObjects, not really. The host is both at the same time. So IsServer and IsClient both will return true. You can check for IsHost and then run only one of the systems
but then it will skip one of them right?
Like, for example if I have a static field that will initialize on awake with a GetComponent<>();
For the server I get that reference from Object A, while for the client(host) I get it from Object B,
If using IsServer first to initialize the reference, then IsClient, this last check will override the first one, and viceversa, using IsHost wouldnt fix it I think, or at least Im unable to see it.
You shouldn't have to use two instances to accomplish this. You can try using IsHost, but if you're properly using IsServer/IsClient throughout your logic, the host's client should be no different than any other client.
How would you do it? For a clearer example lets say the server controls an AI, and the client controls the Player, however both of them have a Damageable behaviour that must be initialialized at runtime from x data, I need to have the server reference the AI damageable and the client(host) reference the Player damageable
Its a closer situation example to the issue im having
I can’t really speak to specifics about your situation without more detail or code. You just mentioned that server systems are interfering with client systems - the host’s client should not use different logic or access different references than any other client. Which usually means going through RPC and NetworkVariables just like any other client would.
Yeah but when running in host mode, server and client flow is present in the same instance context
Right. But you should be making the separation from a logic perspective.
If the client (who also happens to be the host) wants to do something any other player would want to do, they should be using the same systems a normal client would.
they do, the thing is that the host is also the server so its performing both tasks wich interfer with each other at that point
I know that theorically with a proper structure they shouldnt ever get to mix or get close but Im deep down the hole and cannot go back, when we started this project we had no idea of how netcode worked so its way late to rebuild everything, the deadline is next friday, now I just need to fix the problem, Ill implement a better solution for next projects.
So its clear that I cannot have 2 instances, and I dont see how using IsHost would work around it, whats the next step?
I mean, you can have two instances if you want. Run a standalone server instance and connect clients to it.
Wait, really? without needing a dedicated server?
and what if at some point instead of player A being the host, is player B who takes their role?
A dedicated server is just a machine dedicated to running a server instance. There's no reason you can't just run one on your own machine
Just usually inconvenient to maintain, especially if you're distributing to players playing on their own outside of a controlled environment where you're there to fire up the server instance
thats the thing, I need players to be able to host their own sessions
hi guys, quick question, how do I make a client that sends data at all frames ?
I have a client that seems to work (connects to server, sends data), but it sends data only once. I would like to send my coordinates all the time to the server
should there just be some sendmessage() function inside the update block and that should work? For some reason it works only once
To sync movement you should use NetworkTransform
If you need the exact coordinates of the player for some extra logic u still can get them from the NetworkTransform
You really should not want to send data every frame. That is 60 times a seconds. Normal gameplay data is not changing that often
ok, but assuming that I have the coordinates (and I know they update), would that function just not be enough to send it to the server each time coordiantes change ?
ok, my goal is only to log data for now, I just want to see how accurate the coordinate tracking of the quest is
even if it was every second (I don't know how to do this though), right now it just works only once when the application is started bu then nothing more
Sure you can a RPC for that
I wouldn't think your AI damageable and Player Damageable would be any different logically. That's the whole point of using a Damageable Interface
its an example
thanks, how does it work exactly? I have one script called "displaycoords" that just finds and log and displays coordinates on the headset, with global variables that I use in the tcp client script to send to the server. how do I set up a RPC ? In the update block, isn't this block called every step, so if I put the send function there, shouldnt it send every time step ?
Dunno what network library you're using. But here are the docs for NGO
https://docs-multiplayer.unity3d.com/netcode/current/advanced-topics/message-system/rpc/
Any process can communicate with any other process by sending a remote procedure call (RPC). As of Netcode for GameObjects version 1.8.0, the Rpc attribute encompasses server to client RPCs, client to server RPCs, and client to client RPCs. The Rpc attribute is session-mode agnostic and can be used in both client-server and distributed authority...
thanks! I have another question, now I could make it work, however I have some problems in that sometimes the packets received by the server are not formatted correctly
I use a particular format for the packet, they work pretty much well but once in a while there is a message that has either some characters missing or too many characters from the next message
I use that function to send: stream.Write(clientMessageAsByteArray, 0, clientMessageAsByteArray.Length);
Are you using Unity Tranport or raw sockets? If the message is not being sent reliably then you'll run into those issues.
I am using using System.Net.Sockets;
using System.Text;
using System.Threading;
does it mean I use raw sockets ?
I thought that the protocol for communication was that if data is badly sent it would be resent?
That is what a network library does for you
Today I had a DREAM about watching a tutorial which had the exact information I needed to get my multiplayer working
What game development does to a mf
Crazy
Hey guys I was just wondering if anyone had any information on the PlayerProperties that can be passed through when joining a session, there seems to be no way to access them by client ID or anything
i had to resort to looping through all connected clients and returning out when the ids match, but thats obviously not ideal, I couldn't find any way to return out the player properties in any way at all, really confusing why this would be so restricted
id like to use playerproperites to pass through data like the players selected character type to represent them in game, I supposed I could pass through additional information once the player joins the lobby and store that in my own dictionary keyed by the clients ID, but this player property seemed like an easier solution to this, but maybe not
sorry heres how im currently retrieving property data
which just seems rediculous I know, but there doesnt seem to be any other way, maybe im misunderstanding playerproperties completely
even the event ISession.OnPlayerPropertiesChanged does not return the player ID or the player properties, it seems so useless
session.Players is just a List of Players. loop through is the only way. You could use Linq to pull out the matching Player.Id
wow this seems so silly! i thought surely there was a dictionary somewhere I could enter the clients ID and retreive their player properties but I suppose not
ill do my own then I guess
Nope. Sessions have no concept of the client Ids
oh that makes sense actually
well only kind of, because the players ID is still passed through when a player joins a session, im aware this isnt the same as the clients ID but it would still make sense to have a way to easily retreive player properties
I agree player and session properties are not handled very well
Like mentioned above, you can use LINQ and retrieve a player's properties by ID pretty easily. Should be no more than 2 lines of code
resorting to linq hardly seems like a great way but yeah, sessions will be small so it wont have any real impact
LINQs performance overhead is small. You could have massive sessions and not notice an impact.
Its more annoying than a real problem
I'm more curious about this honestly - Lobby Events pass you some sort of wrapper value for changes to Lobby data and Player data. Seems like an odd choice to not do that with the Sessions events
yeah the PlayerPropertiesChanged event has nothing
so you can recieve that event and not know whos properties changed or anything
seems weird
I do remember that's how Lobby started out before they introduced Lobby Events. But knowing that Sessions is using Lobby under the hood.. I wonder what the hold up is on replicating the same events with Sessions
yeah sessions has been very convienient except from that
while we're complaining, SessionInfo that you get from searching session also does not return Public Session Properties
hi guys im new to unity and unity networking with netcode
im trying to displat info about an annotation object (prefab) when is hovered
is working for host, but not for client ( is just an empty string)
void Start()
{
if (!IsOwner) return;
_camera = GameObject.FindGameObjectWithTag("PlayerCamera").GetComponent<Camera>();
}
void Update()
{
if (!IsOwner || _camera == null) return; /
Ray ray = _camera.ScreenPointToRay(Input.mousePosition);
Debug.DrawRay(ray.origin, ray.direction * 100, Color.red);
if (Physics.Raycast(ray, out RaycastHit hit, Mathf.Infinity, _layerMask))
{
AnnotationComponent annotationComponent = hit.collider.GetComponent<AnnotationComponent>();
if (annotationComponent != null)
{
RequestAnnotationInfoServerRpc(annotationComponent.NetworkObject);
}
else
{
HideAnnotationClientRpc();
}
}
else
{
HideAnnotationClientRpc();
}
}
[ServerRpc]
private void RequestAnnotationInfoServerRpc(NetworkObjectReference annotationObject)
{
if (annotationObject.TryGet(out NetworkObject annotationNetworkObject))
{
AnnotationComponent annotationComponent = annotationNetworkObject.GetComponent<AnnotationComponent>();
if (annotationComponent != null)
{
string info = annotationComponent.Data.Value.info;
Debug.Log($"Sending annotation info: {info}");
// Send the annotation data to the client
DisplayInfoClientRpc(info, true);
}
}
}
[ClientRpc]
private void DisplayInfoClientRpc(string info, bool showInfo)
{
if (showInfo && !string.IsNullOrEmpty(info))
{
Debug.Log($"Received annotation info: {info}");
_annotationInfo.text = info;
_annotationCanvasInfo.SetActive(true);
}
else
{
_annotationCanvasInfo.SetActive(false);
}
}
[ClientRpc]
private void HideAnnotationClientRpc()
{
_annotationCanvasInfo.SetActive(false);
}
i dont know whats wong
any advice is welcome
Change Start() to OnNetworkSpawn(). Make sure there is only one active camera in the scene.
hmm
for i have more players in the game, and each with its own camera.
and the player can add annotations
this HoverOnHandler is attach to a annoation game component (sphere) and it need the camera from player(prefab) to check which player is looking at the annotations added before
with pointannotation im adding the annotations as annotationSphere prefab
With multiple active cameras in the scene, the clients will only show the last one created
Also Getcomponent<Camera> is only gonna return the first camera in the scene.
This will also create multiple Annotation Managers. I'm not sure if you want that or not
ohh so i need to get the camera every time?
didnt find a way to get the camera from player prefab to annoationSprefer prefab for the HoverOnHandle script
dont mind that for the moment
You only need to cache is from OnNetworkSpawn I you do GetcomponentInChildren<>
But you'll need to make sure that the non local players have their cameras disabled
how would GetcomponentInChildren<> give the camera of the player prefab? as long as im working in a script that belong to another prefab
i dont really understand the thing about the non-local players camera to be disabled
i need to check if the player is non local to disable its camera with NetworkManager.Singleton.LocalClientId?
IsLocalPlayer would be the easier option for Player Objects
Hi, I'm making a matchmaking system for my 1 vs 1 online mobile game with Photon Fusion, but the problem is that once I press the “Play” button, the game doesn't wait for another player to join and sends me alone to the match/battle scene. https://paste.ofcode.org/38WVdauyrgHUmavGtC8JNm9
I am using a P2P mode as a test, but in the future I plan to change the logic to use a dedicated server
hmm i would read look it up
playerObject.IsOwner && playerObject.OwnerClientId == NetworkManager.Singleton.LocalClientId
for now i used this
i managed to fix it
big thanks
so im having an issue at the moment where if i were to start a game, then use another client to join said game all works fine. But if i were to leave and rejoin that same lobby i spawn and see an extra pair of arms with both my primary and secondary weapons, static, where i spawned, but this instance that did not happen and it spawned in a random location. im assuming its instantiating problems OR an issue with the clean up when i leave and rejoin, i just realized that when i rejoin the other clients dont the "player has joined the match" message.
Anyone? 😬
Hard to say with seeing your code. Could be a log in event that you are not unsubscribing from. Or the original player prefab is nor despawning
Would you like to take a look at the code that handles the leaving?
You'll need to make sure the prefab is despawning when the player. Still have no clue what networking you're using. It could also be spawning twice for some reason. You'll need to throw some debug logs in to see where things are going wrong
{
if (!photonView.IsMine) return;
Debug.Log("Quitting game...");
StartCoroutine(DisconnectAndReturnToLobby());
}
private IEnumerator DisconnectAndReturnToLobby()
{
if (PhotonNetwork.IsConnected)
{
PhotonNetwork.LeaveRoom();
while (PhotonNetwork.InRoom)
{
yield return null;
}
}
SceneManager.LoadScene("LobbyScene");
}
public override void OnLeftRoom()
{
if (!photonView.IsMine) return;
SceneManager.LoadScene("LobbyScene");
}```
the QuitGame function is called from the pause menu
ah, thats a good point, i am using Photon Pun 2
I don't use Photon but I don't see anything wrong with that code
hmm okay, ill go and start adding debugs
ive tried many things
most of which did not work
if anyone is able to help me out itd be greatly appreciated
hey, its my first time using netcode, and i am having an issue with OwnerClientId as it differs from server to client and i was depending on it for my player id. is this straight out bad practice or how do i get the correct client id from the server on the client?
for context i am making a landing page to connect players via relay NetworkList<PlayerInfo> player info has id, name and latency
i also have one local PlayerInfo per player, whenever i change data on the client object i update this object on the list via an ServerRpc method
NetworkManager.Singleton.OnClientConnectedCallback gets the client id for the list objects on the server side but this differs from the OwnerClientId
is there any relation between this IDs , or how is this usually handled
btw the player 2 in the server has id 2 (actual clientId = 1 but i am adding 1 to prevent id = 0) on the client side OwnerClientId for player 2 = 11 (actual OwnerClientId = 10)
OwnerID should be consistent across client and server. But it depends on when you are checking for OwnerId. It will not get set until after OnNetworkSpawn() is called
Personally i use Unity Authentication PlayerID as a network variable on the Player object instead.
hm so that is the issue i am rewriting the session manager because i found a few more issues, can you elaborate regarding your preference for Unity Authentication PlayerID
i notice i had the authentication initialized, i dont think i was using it anywhere at least explicitly but as anonymous sign in seems viable for my purpose
Player ID will be consistent across reconnects. the client ID will always increment if someone reconnects after dropping. You can map the Player ID to its current client id with a dictionary if you need it
i dont need particularly i just came across it first
i am testing now with the new script and the player id seems more reasonable
is playerId fixed lenght? i was counting on a non nullable type for networklist
documentation does not elaborate
i am using FixedString32Bytes for name, i wonder if its safe to use for playerId
Thats what I normally use
Docs say here that its random 28 characters
thanks for pointing that out
[Netcode] NetworkConfig mismatch. The configuration between the server and client does not match
Where do i start?
I fixed an error at the time was due to client authority and Id mismatch now its just this warning but there is no synchronization i just dont know what is causing the mismatch
I am trying to connect via relay, its a single scene i have 1 in scene network objectServerManagerand 1 network prefab that is assigned to default player prefab in NetworkManager
I made it work , dont ask how because i dont know what changed
usually just restarting Unity will fix this
Anyone know why this would be internal? seems weird to atleast not allow public getting
NetworkObject.PrefabIdHash is what you are looking for there
Nah was looking for global
are the fast buffer readers/writers like native collections where its a wrapper around a pointer
Does anyone know the general overhead for setting a network object's visibility, netcode wise. I have a rather large map, and I would like to only make objects visible to the users when they are near them. Would enabling / disabling the visibility of network objects have a large performance cost, as far as the transport is concerned? All the objects are already properly pooled, so im not concerned with the setup/deconstruction of the objects, just the pure network cost
For reference, right now im keeping all the data in a single network list. However, in infrequent, but still in scope, cases, this list can grow to a size larger than 64kb, which leads to issues syncing the network object (NetworkVariable data read too big. 65536 bytes.)
The server itself is throwing a [Warning] : A lot of pipeline updates have been queued, possibly too many being scheduled in pipeline logic, queue count: 66 in these cases, but im unsure of how to debug that
it is
Added a way to access the GlobalObjectIdHash via PrefabIdHash for use in the Connection Approval Callback. (#2437)
NetworkShow()/Hide() is just a De/Spawn call. You can spawn objects with no observers and they will be hidden by default
So if a new user joins the server, and all the objects are hidden, there should be no network overhead
But adding an observer has the same overhead as calling spawn
Can I use netcode for entities alongside netcode for gameobjects or is it one or the other? I’m rescripting my game for netcode so I need to know which works
Right, calling NetworkShow() will call Spawn() for those clients
You can not use both, no
I am having an issue with one networkbehaviour not beeing added to the internal networkbehaviour dictionary, the object is spawned, and when i try to call a serverRpc method on it i get an error saying that the object could not be found, but his is only on the networkbehaviour the object exists
KeyNotFoundException: The given key 'ServerManager' was not present in the dictionary.
(... message too long but is pointing to NetworkBehaviour script)
ServerManager.RegisterPlayerServerRpc (Unity.Collections.FixedString32Bytes playerId) (at Assets/Script/Managers/Network/ServerManager.cs:31)
NetworkPlayerManager.OnNetworkSpawn () (at Assets/Script/Managers/Network/NetworkPlayerManager.cs:19)
public class NetworkPlayerManager : NetworkBehaviour
{
public string id;
ServerManager serverManager;
public override void OnNetworkSpawn()
{
if (IsOwner)
{
serverManager = GameObject.FindGameObjectWithTag("GameManager").GetComponent<ServerManager>();
//serverManager is fetched successfully
id = AuthenticationService.Instance.PlayerId;
serverManager.RegisterPlayerServerRpc(id);
...
on the ServerManager (never reached)
[ServerRpc(RequireOwnership = false)]
public void RegisterPlayerServerRpc(FixedString32Bytes playerId)
{
NetworkPlayerInfo networkPlayerInfo = new(playerId, networkPlayersInfo.Count + 1);
networkPlayersInfo.Add(networkPlayerInfo);
Debug.Log($"{networkPlayerInfo} joined the session");
}
and also, ServerMethod ServerRpc method was working before, I changed the parameter to simplify the logic and probably changed something else elsewhere that affected this but IDK what.
ServerManager also needs to be a NetworkBehavior on a spawned network object
and it is
its spawned from start (already in scene) while networkplayer is spawned only when the player clicks on a button to join the network.
btw this is a relay server and i have option to host or join, this is happening right at the start with the host, although as i mentioned i had a simpler version of this working a few hours ago
i attached a screenshot, i changed very little, i replaced the players text with a more complex prefab and i refactored the networkplayer as i realised i didnt need the "player info" on the player as it simplifies a lot the logic. i always need to access the server so why not just store an id and avoid the extra synchronization but that was basically it, as far as i remember i didnt change anything else
Also make sure the server manager is not disabled or deleted on the client. RPCs need to exist on both to function
Thats correct, it exists, in this case the error happens on the host so its just 1 machine 1 player
And i am not disabling nor destroying it on any occasion
i found the issue, but i dont know the solution, so the order of the onnetworkspawn seems to have changed, if i ignore the call that throws exeption i can see the server manager is spawned after the player, i am using the default player spawn logic as it connects.
other than hardcode a delay , is there an approach where i can explicitly spawn an object on the network (that is already spawned on the scene) before the first player is spawned? i tried using OnNetworkPostSpawn() on the player to call the server method but this is still before the serverManager spawn
weird. OnNetworkPostSpawn() is explicitly after everything in scene has spawned. I would probably just spawn the player manually after you know the servermanager is setup. With an event
it seems that is only on the network object not the scene
i have to see this, but what an headache it caused, i know now what caused this i was confident server manager was spawned and this had nothing to do with the change but with the refactoring i removed an async method from the player initialisation that allowed time for the server manager to spawn lol
Not sure if I still need it (was experimenting with some stuff) but PrefabIdHash is a getter that just iterates through the networkprefablist via the NetworkManager so in the event you don’t have access to that yet it’s not viable. Realistically it’s probably not a problem just a tad odd that direct getting of globalid is locked
For anti-cheat in my game, it's required that part of my tick package represents events that happened on the client so that the server can verify stuff is legit. Is it a common practice to generate the mappings of integer to events per lobby, or would that be futile?
is cheating a problem in your game?
hey, i am making design choices (for network logic) but as a newbie i am not quite sure about the best approach.
my game in simple terms involves 2 players each has a territory, players only spawn units and the units start moving forward, if they locate a target to destroy ultimately that target is the enemy base
this is a cloudless relay service and i think i am trying something like distributed authority but its not really distributed authority, there is a central host, what i wanna distribute is the computation, particularly based on territory. i dont know if this makes sense but i am thinking the following:
- each unit is owned by the player that controls the territory the unit is in.
my thinking is that the player A spawns unitA and owns it until it reaches player B territory and player B takes ownership of unitA
benefit here being player B has the current state of unitA in real time, so in a fight with unitB for example it doesnt need to synchronize actions (2 way) it behaves as single player, while the state is still synchronized for player A (1 way)
does this make any sense?
this is only simplified my hopes is that one player takes control of all units in one battle , for example at the fronter it would be one player still computing the actions, if there are 2 fronts maybe it would be one player with each front and so on
I recently switched to the new Unity 6 Multiplayer Service and got everything up and running. However, my code was based on a lot of custom implementations for Relay and Lobby, which I am currently in the process of removing because they were overly complex and error-prone.
Now, I’m facing an issue when querying available sessions. In the old Lobby Service, the query result for a lobby included a data object containing the values set by the host. However, in the new ISessionInfo object, I currently don’t see any way to access the session property values set by the host (such as map, map type, etc.).
Is this feature missing entirely? If so, the service is practically useless, as users wouldn’t receive any match-related data to filter or make a selection. Or am I overlooking something?
wouldnt you need to make your own session object with the data you want? and access it via client/server rpcs or network variables?
At this point the user has not joined to anything (he wants to join). So I could not ask for any data, because there is nobody to get the values from. The data are completely handled by the service API.
ok, sorry i am newbie in network(netcode), so for me to understand your question, potentially learning something,
your lobbie is a connection to a server where you host your sessions, you wanna display existing sessions data so the player can choose a session, is that it?
Currently SessionInfo doesn't return session properties. You can stick to using the Lobby API in Multiplayer Services if you need it. And yea that is a problem
You would use matchmaking to filter out sessions
Thanks for the hint. I don’t understand why they removed this feature when it was already working, but well, I hope they add it back later.
Matchmaking is on the agenda, but for now, it’s completely out of scope. There are other things that need to be taken care of first.
Hello everyone, sorry to bother you, but I need your help. I'm working on an online car game in Unity, and I'm facing some issues that I really can't fix on my own. The problem is that I can't get the cars to spawn on the map chosen by the players in the game. Only the host is able to spawn their car on the map. Let me explain the car selection process.
We have a "Host" scene to create a game, then we move to a new scene, which is the lobby. The host creates a game that players can join. Once the players have joined, the host starts the game, which loads a "Game" scene where the menus are displayed, meaning the map selection, then the car category, and finally the car selection. After that, we click on "Play," which loads the map scene and removes all other scenes.
And it's from the map scene that everything bugs. In other words, the cars don’t spawn, even though I set them up with the required Mirror components.
I'll leave my GitHub here—if you could take a look, that would be really great.
https://github.com/scotty800/lobby
Hey everyone, your girl needs some help.
I've been working on an inventory system for a multiplayer game I'm working on, but I've run into a big problem. Picking up the items seems to work perfectly fine as does adding them to the inventory, but dropping the item runs into some issues. The player that drops the item does drop the correct item, but the player that picks up the item just gets the default item stored in the prefab.
I'm pretty sure the issue comes in with NGO's inability to pass ScriptableObjects as NetworkVariables, but with the way my inventory is set up, I pretty much need the item being passed to be a SO and not just the data from it. Is there any way I can make sure that the client's version of the dropped item gets updated to have the correct SO or am I cooked?
I'd really prefer not to have to re-write the entire inventory from the ground up, so any help would be majorly appreciated~! The code for the scripts can be provided if necessary.
Edit for some context: I don't entirely understand what's going on, but on the ground item, there's a few values that do seem to be getting set to those of the item that should be dropping, but the actual item itself is still incorrect. In this case, a rarity and item name value (both of which are network variables) are getting set to the correct data even though they're calling from the SO inside the GroundItem, which is not the correct item when being spawned on the client.
How to get the ip of a player in relay and in lobby?
I would have an ID for each SO then you can set that ID as a network variable
Or is it possible to get it
I don't think you can get the IP of the player over relay. That would be a security risk if you could
İ want to get relay player id from lobby player id and i want to do it by passing relay player id into the lobby player data but they can decompile it and send another id
How do i check if they are the same person
You can verify the access token using a jwt library if you really need to. You can get the public key from Get JWKS
That might work actually, like if there's ID's for each of them and then have it pick the SO from somewhere the client can access based on the ID of the item
Hey everyone!
So i'm getting into Relay little by little and i've been looking up on how to do it.
I'm getting real confused on RelayServerData for UnityTransport. Every tutorial i find on relay just tosses the Allocation and a string of "dtls" for connection type, but it seems that the package has changed and now there's not even a "connectionType" setting in the data.
Can't really find anything in docs either (i really may be just dumb or blind or both ngl), except for a "getting started" page that leads me to downloading a sample scene to use instead, which is, working, but not really ideal cause i want to understand
btw, yes, i am using Netcode for GameObjects and i've heard something along the lines of multiplayer center having all the lobby / relay things i'm trying to implement but haven't really found anything proper on that either
The easiest way is to the new Sessions API in the Multiplayer Services SDK
thanks, i'll look into it
Is there anyway in NGO to directly let a non owning client write to a networkvariable?
You can use AnticipatedNetworkVariable then use OnReanticipate() to sync with the server value
Oh first time I'm hearing of this one, ty
Client anticipation is only relevant for games using a client-server topology.
ah but theres no offical anticipatednetworklist implemention.. puts abit of a wrench in my plans hmm
You should be able to use AnticipatedNetworkVariable<List<T>>
should i be passing around readers/writers with ref or is by vlaue ok?
What’s the correct way to pass lobby player data through to a n4e session (I’m using relay)
Anyone know how to do parenting when using Photon SetParent() didnt sync
google has a lot of answers for that
i have a relay session working but when i tried to add connection approval, the callback ends with ```cs
response.Approved = true;
response.Pending = false;
Debug.Log("Connection Aproved");
but he logs show something like:
> - Connecton Aproved
> - pending client x connection aproved
it seems that the connection approval is called before the network is expecting a connection and the client never connects, this is happening on the host
what am i doing wrong?
```cs
...
NetworkManager.Singleton.GetComponent<UnityTransport>().SetRelayServerData(allocation.RelayServer.IpV4, (ushort)allocation.RelayServer.Port, allocation.AllocationIdBytes, allocation.Key, allocation.ConnectionData);
//this fllowing connection approved lines are the only change between connection working and not working
NetworkManager.Singleton.NetworkConfig.ConnectionApproval = true;
NetworkManager.Singleton.ConnectionApprovalCallback = ConnectionApproval;
NetworkManager.Singleton.NetworkConfig.ConnectionData = Encoding.UTF8.GetBytes(playerId);
if (!NetworkManager.Singleton.StartHost())
...
If you created a lobby first then connected to a session, I'm pretty sure I the session owner can update the session player properties. I might be wrong and only the local player update their own properties
The host is auto approved for Connection Approval. It sounds like the client might be failing or timing out the approval
You mean the client of the host? Because this happens on host initialization, i assumed its weird to approve the host but it does prevent the host player from initializing waiting for approval , i dont even have a second player client at this point
Yea, there is no way the host can disapprove itself. So it just automatically approves.
well but my issue remains, if i comment out the connection approval lines the players can connect if i try o use aproval system (for clients) the host player does not connect, by connect i mean the player prefab does not show on the screen as it should
and the callback for the connection approval is executed anyways even if it ignores the approval flag
are you setting it in the inspector or only in code?
enabling Connection Approval
Sorry is in code
Is it stupid to try to write your own networking solution?
I am aiming for a fast paced, competitive environment with medium to high number of connections. I am already familiar with the high level layout of networking system in competitve games, but I have little knowledge of low level networking other than some basic C code I did once.
Somewhat comfortable using NGO but haven’t messed with Custom Messages yet. Been trying to read the docs but struggling to comprehend their unique capabilities, I’d love to know some practical benefits of messing with them. One thing I’d love to be able to do is handle some of my own light networking outside of the context of a networkbehaviour, I have some custom network variable classes that need to communicate between server and client more than the variable itself allows and i’d love to contain this setup within the class for more modularity and re-usability
It's like building your own physics system. You would need to have a very specific problem you need solved that the built-in system can not. A lot of places do roll their own system. But those places have teams dedicated to it.
The thing about Custom Messages is that they do not have unique capabilities. They are basically RPCs that are not tied to any network object. They still use iNetworkSerialiable for its parameters. If you are using Custom Scene Management it will make sense to also use Custom Messages.
I haven't looked into it too much, but from what I understand NGO doesn't officially support / isn't built for large lobbies or competitve games. Photon, which is the only other solution I've heard of, seems to have a paywall
Depends on what you mean by "large" and "competitive". If you are writing an MMO, then yea custom netcode is unavoidable. Though Star's Reach is doing pretty well building on top of Netcode for Entities.
large as in 40-60 connections at a maximum running 60 tps
so just in terms of network bus ig
Oh, yea. Unity Tranport can handle that. The Lobby/Relay services have a hard cap of 100 players. You'll likely need a dedicated server though. Client hosts won't have the bandwidth to handle those.
Distributed Authority might help with that though
Yeah I was already planning on dedicated servers, although If i actually have a good product hopefully i can get a publisher to pay for them
or help
What actually changes between different networking solutions? Like I know some of them have different pre built features / set ups, but I don't know whats actually different at their cores
The built in features are the main difference. All the modern ones I've looked at all use RPCs, Network Variables, some kind of Network Object and Transforms
Has anyone used multiplayer play mode before? I'm having an issue where I can't get more than one screen in focus at once. For example I'll have the P2 window and the P3 window up, but I can't get them to connect because the one I'm not clicking on is always out of focus 😦
focus shouldn't be an issue with mppm. after you start the host, you should be able to start the client on each clone
Guys I have this code "https://paste.mod.gg/anttbeeivfwk/0" and already tried everything watching tutorials and codes of there more I just can't unlock my player client, the player host usually works but the player client does not leave the place, it even activates the animations but simply does not leave the place
A tool for sharing your source code with the world!
a few messages back, theres mentions to paywalls, only after i started learning netcode i realized even with relay (players hosting the game) has costs eventualy, anyone has an idea if its reasonable? for me its just numbers until i make a spreadsheet but i dont yet know what i will need. I was interested in Relay with Distributed authority, although free for now , distributed authority will have a cost I dont know if there is an estimate, i didnt find one.
for relay i saw that i can start with 50 players 24/7 per month for free but then i still have to account for data and i have no idea how much data each player/session will use so i dont know if those 50 players would exceed the free teer.
any advice. even pointing to a good blog would be great, my main concern is that i wanted to sell a game, not rely on subscriptions, so i dont know if using unity relay will be reliable on costs long term or if i should deploy my own relay, i wouldnt mind have a small fee for the multiplayer but you that would be a nono for many players even if its low value.
The short answer - the free tiers are generous enough that you would have to have a player base that is likely in the thousands to ever exceed it.
I dont know if you are talking literally or just an approximation but it seems than a few hundred would exceed the free tier at least on the Relay connections . not sure about data
I don't think it's very likely to end up with significant amount of players which you can't monetize.
not sure what you mean "end up with significant amount of players"
Of course it's an approximation, but I'd say it's a pretty accurate one. If you exceeded it with a few hundred those would be some insanely active players.
As for the bandwidth, that largely depends on your game, but the free tier is generous in that regard as well.
thanks
I highly doubt you'll end up in a situation where an active player base would consume enough server resources to outpace income from it.
ok, i have not made any calculations, but i will take your word for it, just to be clear your assumption is that without charging any subscription, just sell a copy for around 15£ / 20£
take your word for now of course, my only doubt is the actual cost , but that is not possible to predict yet, as i dont know the amount of data a session will tipically use
You could probably sell it for 0.99$ and be fine. CCU numbers are really not intuitive.
Are there any tricks for reducing the overhead on NetworkObject.Spawn()? Im keeping viewports for users where they dont observe objects until they're within a certain radius of them, via NetworkObject.NetworkShow and NetworkHide. However, I'm finding the overhead for the clients OnSpawn calls for these objects is substantial.
Sure the network traffic is low, but the CPU spike when a cluster of objects enters a players range is problematic
thats good to hear, thanks for the context
It's peer to peer
Weirdly enough it works if I use the P1 (main editor) as the host. Then I can join with P2. If I do that though, P1 operates really slowly while out of focus, and P2 stops completely while out of focus.
How many objects are you talking about here? How often are things spawned/despawned? In any case, using Object Pooling should help.
Do you have the project settings set to run in the background?
Oh, I don't think so? Haven't checked
I'll give that a try
Thanks, that worked!!
Im doing tests on around 200 objects or so. Pooling helps a LOT, but im still dealing with the raw overhead
I just realized Color is not compatible with BufferSerializer I assume its due to its Name property that is a string. is there a network version? i an do a struct with 3 floats just wondering
If you are using NGO then Color has built in serialization
Unity Primitive Color, Color32, Vector2, Vector3, Vector4, Quaternion, Ray, Ray2D types will be serialized by built-in serialization code.
You've got 200 objects being shown/hidden at the same time? But with pooling it should just be enabling/disabling them so there shouldn't be much CPU overhead
Are you using the FastBufferReader/Writer?
i am not sure.
i am using NetworkList and it requires my object to have INetworkSerializable, IEquatable<NetworkPlayerInfo> and this implies as far as i understand that all properties must be nun nullable
the issue with Color arises here public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
are you trying to serialize a System.Drawing.Color rather than a Unity color? unity colors don't have names
oh, good catch
this automatic usings sometimes ..
So how's netcode for gameobjects? Liking it so far but can't help but wonder whether there are some well hidden known issues that are just waiting to bite me
Anyone had extensive history with it (maybe even a finished product)? How was it?
I've been using it for a while now. Don't have any finished projects to show off unfortunately. The biggest missing feature is client prediction. But the anticipation system gets you 80% there.
From what I understand anticipation fits for about anything that isn't a competitive game
So it should be enough to provide comfortable co-op/pve experience
Honestly, it would probably work for a lot of competitive games too. It just doesn't do physics rollback
Networked physics is a nightmare anyway
Netcode for Entities handles it fairly well all things considered
I've used it since its prerelease. It works well for a variety of games I would say. If I had one critique it would be that the error trapping is slightly lacking and the error messages aren't very verbose or helpful to users in some cases. But that's usually only a pain point for beginners I would say.
That's just unity packages in general, I think they forgot how to properly log error half a decade ago with the whole entities thing
But anywa it's good to hear the thing is by all mean usable
I was already anticipating (🥁 ) having to sieve through 10 different third-party networking solutions to scrap together something quick like it was a while back
People won't stop talking about FishNet though. That one I never even checked out
People seem to have good results when using it. I think it boasts its own prediction system which tends to win some people over.
How can I serialize a list of struct data to be used in NetworkList?
NetworkList can not have a List inside of it. You might be able to use NetworkVariable<List<PlayerWeaponData>>
Hej all! I am having an issue with Cinemachine multiplayer cameras. I have checked pretty much everywhere including video's like NetCode For Game Objects Pt 5 - Cinemachine Cameras in Multiplayer. Unity manual and there ebook gives no info.
I am looking for a good resource to get cameras working for each client. Im using Netcode for Game Objects. Should I just get rid of Cinemachine and make a regular camera maybe or any suggestions pls. Thank you.
Can you give me an example code? That would be great. For now, I still don't know how to serialize it. I only saw from the documentation how to serialize other variables like int, float, and FixedString, but never a list
You don't serialize a list since its a reference type. You would have to use a Native Container
Netcode for GameObjects has built-in serialization code for arrays of C# value-type primitives, like int], and [Unity primitive types. Any arrays of types that aren't handled by the built-in serialization code, such as string], need to be handled using a container class or structure that implements the [INetworkSerializable interface.
Check out the Client Driven Sample it uses Cinemachine and the 3rd Person Controller
@sharp axle Thank you checking it now!
I have mine set up similar to that example
using UnityEngine;
using UnityEngine.InputSystem;
using StarterAssets;
using Unity.Cinemachine;
public class ClientPlayerMove : NetworkBehaviour
{
[SerializeField] private PlayerInput m_PlayerInput;
[SerializeField] private StarterAssetsInputs m_StarterAssetsInputs;
[SerializeField] private ThirdPersonController m_ThirdPersonController;
[SerializeField] private CinemachineCamera m_CinemachineCamera;
[SerializeField] private AudioListener m_AudioListener;
private void Awake()
{
m_CinemachineCamera.Priority = 0;
m_StarterAssetsInputs.enabled = false;
m_ThirdPersonController.enabled = false;
m_PlayerInput.enabled = false;
}
public override void OnNetworkSpawn()
{
if (IsOwner)
{
m_StarterAssetsInputs.enabled = true;
m_PlayerInput.enabled = true;
m_AudioListener.enabled = true;
m_CinemachineCamera.Priority = 5;
}else
{
m_CinemachineCamera.Priority = 0;
}
if (IsServer)
{
m_ThirdPersonController.enabled = true;
}
}
[Rpc(SendTo.Server)]
private void UpdateInputServerRpc(Vector2 move, Vector2 look, bool jump, bool sprint)
{
m_StarterAssetsInputs.MoveInput(move);
m_StarterAssetsInputs.LookInput(look);
m_StarterAssetsInputs.JumpInput(jump);
m_StarterAssetsInputs.SprintInput(sprint);
}
private void LateUpdate()
{
if (!IsOwner)
return;
UpdateInputServerRpc(m_StarterAssetsInputs.move, m_StarterAssetsInputs.look, m_StarterAssetsInputs.jump, m_StarterAssetsInputs.sprint);
}
}
The camera works fine on the host machine but clients dont, just a regular camera (Main) camera shows on theirs wich does not follow the player heh.
Make sure there is only one main camera in the scene and you are not spawning one with the player
Anyone familiar with Photon Fusion? Or anyone have link to their Discord? I'm trying to open the Discord link provided on their website but it Times Out
I have another basic question, if I want a game with single and multiplayer, is the best approach having the logic decoupled then having a mono behaviour and a network behaviour accessing it? or using the just network behaviour would be fine (if i dont initialize network behaviour would networkbehaviour behave as monobehaviour or something like that)
Decoupling almost always borderlines being impossible or a lot more trouble than it's worth. You can just run a host off localhost for singleplayer.
so there is no overhead for using network behaviour compared to monobehaviour?
for stuff like RPCs and NetworkVariables, I believe the updates would happen within the same frame - so there's really no difference.
hmm ok thanks
I haven't looked into the innerworkings of vivox but I need an alternative to dissonance and it seems like the perfect fix albeit there's ONE thing I need to know; is it possible to parent the voice of a player to a transform?
This is my huge issue with disonnance. There's a lot of weird client sided jank that goes on in my game and with dissonance you HAVE to give it a position to sync to other players
So obviously the voice is being synced at say 0, 1, 0 but on a client's side it could be meters away from that
I cant really look at any resources right now as I'm out but I want to know if it's a feasible workflow
You have to call VivoxService.Instance.Set3DPosition() in update or wherever.
Yeah I just got back and read the docs for that method and it's what I feared and is why I'm actively moving away from dissonance unfortunately. Stuff like position prediction simply wont work well with a method like that
For what it's worth I suppose I still have Photon Voice to fall back on. I just wanted to save on the costs tbh
Wait hold on I think I'm misunderstanding
I wouldn't think position rollback would be far enough to cause issues
Unfortunately my game is VR and very fast paced and based around co-op puzzles so there's a bit of a weird jitter between the voices updating their positions in dissonance
It's not horrible but once you hear it it's kind of one of those things you cant unhear
I disabled the option to stop them from being auto added but is there anyway to stop NGO from harassing me with prompts about my networkbehaviour missing a networkobject?
I need a restraining order or something
@sharp axle The objects I was testing with are completely empty. Just a networkobject on a prefab. Got a pretty sizeable slowdown when enabling that many. Looked to be a drop of around 10ms on my machine for the frame they spawned in on. Most of it seems to be related to the scene manegment system
Ill swap back to my test branch and get a screenshot of the profiler
Its some pretty interesting results. The overall overhead for spawning via NetworkObject.NetworkShow is 25 bytes if you don't have any of the other sync flags set (Sync transform, sync parent, ect). That seems reasonable. I think the issue seems to come from the fact that these 'show' messages dont get batched.
We can see here its executing 1000 individual create commands. This leads to the dictionary that tracks everything updating repeatedly, leading to the large GCAlloc in the profiler. So despite there being only around 8kb of messages, almost a megabyte of data is allocated. Overall, the overhead for calling NetworkObject.NetworkShow looks to be around .1 ms per object, which seems acceptable
All of these objects are pooled via the example NetworkObjectPool shown in the documentation
NOTE: THESE NUMBERS ARE IN DEEP PROFILING and should be seen as ratios rather than absolutes
In normal operation (AKA not logging the hell out of everything), the same test will execute in 15 ms, rather than 150 ms.
I'm still working on replacing my old lobby code with the new Multiplayer Service. Does anyone have a source on how to properly use the events on the ISession object? I can register the events, and I do receive notifications when an ISession.Change or ISession.PlayerJoined event is triggered. However, the ISession object itself doesn't seem to update—its read-only player list doesn't include the newly joined player. Unfortunately, I can't find any documentation on how to use these events to detect and process changes on both the server and client sides to update the UI accordingly.
I would open a GitHub issue on this. Seems like there could be some easy optimizations here. Also does the same thing happen in a build? I know the editor sometimes adds some overhead.
You still have to called ISession.RefreshAsync() after the event
Ah, yeah, im profiling on a debug build I made, rather than the editor. All these numbers are on an actual executable, rather than an editor
Correct me if I'm wrong. The ISession.Changed event was triggered, but the data hasn't been updated yet. This means that at the moment I receive and want to handle the event, the data is outdated. That sounds a bit strange to me— in the lobby, I got the NetworkPlayer on join and had the data immediately. BTW: Calling RefreshAsync when handling throws a SessionException: Rate limit has been exceeded exception.
I agree its weird. But most of the Session events don't actually include the data that changed. So calling Refresh is necessary
Have you got an example how to use it? If I add this Resync operation to the event handler I always run in an Rate limit exception. and nothing is updated: ``` private async void OnSessionChanged()
{
Debug.Log("[MatchManager]: Notified that the session has been changed!");
await activeSession.RefreshAsync();
var session = activeSession;
Debug.Log($"Session successfully updated {session.Id}");
Debug.Log($"Name: {session.Name}");
Debug.Log($"Player limit: {session.MaxPlayers}");
Debug.Log($"Player count: {session.PlayerCount}");
Debug.Log($"As host: {session.IsHost}");
Debug.Log($"Is private: {session.IsPrivate}");
foreach (var player in session.Players)
{
Debug.Log($"Player in Session:");
foreach (var entry in player.Properties)
{
Debug.Log($"{entry.Key} : {entry.Value.Value}");
}
}
Debug.Log($"Session Property-Settings:");
foreach (var prop in session.Properties)
{
Debug.Log($"{prop.Key} : {prop.Value.Value}");
}
} ```
hitting the rate limit would stop the refresh from happening. Are you polling the session anywhere else?
I don't think so. Only Queries to join maybe. I've to check this.
If you're using PUN or Fusion, it have Single Player Mode. Most of your code can be reused in that mode for single player too.
I have a techincal question:
I have an idea that requires three physical players and I'd like for them to play on only two virtual players: the master will be in a player of its own, while the two other players will play on another player in split screen. So three persons in total, two on a split screen.
Is there a simple way for me to setup on the host a simple camera and on the guest a split screen? So far I've had the issue that I cannot use two SpawnGameObjectAsPlayer because only one of the two will actually get a device input
Checked this. No API Service calls are running in the background. When I create a fresh Session finally ISession.Changed event is notified. If I call at this point directly await activeSession.RefreshAsync(); I directly run in SessionException: Rate limit has been exceeded thrown by the lobby handler.
Unity.Services.Multiplayer.LobbyHandler.RefreshLobbyAsync () (at ./Library/PackageCache/com.unity.services.multiplayer/Runtime/Multiplayer/Lobby/LobbyHandler.cs:394)
try using SessionPropertiesChanged instead of Changed. Joining a session will trigger Changed which if you are also calling RefreshAsync() will hit the rate limit. Unless you pause before calling Refresh
The local camera shouldn't be networked so you should be able to use split screen where needed
The camera is not networked, however I cannot have two players, each with its Player Input in the same player because one is "eating" the input actions of the other
If I just spawn two of them, which I did manage to do, only one will move and if I go to the other in the input debugger it doesn't have any device associated
The main player has User: 0, the second one has User: 1, the third one doesn't have a user
The remote player should have its player input disabled. Are you using the Player Input Manager Split-screen?
I do not know where you take your knowledge from, but using SessionPropertiesChanged fixed the issue with the Rate limit. Chapeau! But there are still no values available. In the PlayerJoinedHandler I first call await activeSession.RefreshAsync(); but the activeSession.Players read only list doesn't have any change. I only see the host player which has created the session. The joined user still not exist, but the session says, that 2 players are already in the session.
I'm a mod over on the Unity Netcode server linked in the pinned messages. Sounds like you might be running into a timing issue. It might take a frame for the Players list to be updated.
Ok, this explains where the skill comes from. Respect, good knowledge. Anyway, the new Multiplayer Service feels pretty incomplete and weird compared to the old Lobby Service. I get an event signaling that the values have changed, but I have to wait a frame before I can actually retrieve and use the data? What was the architect smoking?
However I will give it a try ... I'm starting to think I'd rather stick with the old service—it actually worked. Everything feels messy ...
If you had everything working there is no real need to move to sessions. the old code will still work even in the new package
You're absolutely right—I could stick with the old approach. However, the new service is much more lightweight (especially when it comes to session creation), less error phrone, and who knows what I’d be missing out on in the long run if I didn’t switch. It’s a shame that well-functioning features are being replaced with half-baked alternatives, especially for core functionalities. Too bad. I’ll see what I can do.
Thanks for your help so far!
Hello I am struggling really hard. In my game players can build their own custom map. The map is about 1~2 GB.
I just need a player to download the map only once but there doesn't seem like any library that supports this.
So far I used ENet and Photon
none of the two reallly do it since both of them has a speed limit bottleneck
can anyone recommand me any C# Networking library to achieve this?
just to alllow the player to download fast
You're gonna have to bring to file sizes down. But in any case, you'll need to use a file server that players can upload and download from. There is also a User Generated Content service you can use. https://docs.unity.com/ugs/en-us/manual/user-generated-content/manual/overview
I have high internet speed, and my players have high internet speed as well. Is it not possible to utilize the high internet speed?
we are physically located near each other with awesome internet provider
I guess if you set up your own ftp server
That's giving me ideas
I wonder why I couldn't have thought of that
That I think is actually the answer
isn't Minecraft somewhat like FTP anyway as well?
Not really, I know it exists but I also don't think it could work together seamlessly
I already enable the input OnNetworkSpawn()
private void OnClientConnected(ulong clientId)
{
if(NetworkManager.Singleton.IsServer)
{
SpawnClient(clientId, NetworkManager.Singleton.ConnectedClientsList.Count - 1);
// if the client is the second to connect, spawn two instead of one
if(clientId == 1)
{
SpawnClient(clientId, NetworkManager.Singleton.ConnectedClientsList.Count - 1);
}
}
}
private void SpawnClient(ulong clientId,int prefabId) {
GameObject newPlayer = null;
switch (clientId)
{
case 0:
newPlayer = (GameObject)Instantiate(_kingPrefab);
break;
case 1:
newPlayer = (GameObject)Instantiate(_attackPrefab);
break;
case 2:
newPlayer = (GameObject)Instantiate(_shieldPrefab);
break;
}
if (newPlayer == null) return;
newPlayer.SetActive(true);
newPlayer.GetComponent<NetworkObject>().SpawnAsPlayerObject(clientId, true);
}
Then in the player:
public override void OnNetworkSpawn()
{
base.OnNetworkSpawn();
if (IsOwner) _playerInput.enabled = true;
}
Are you doing local co-op with the players on split screen?
In one of the two clients, yes, but the split screen is made by editing the camera properties, not using the playerinputmanager
Because the players need to be spawned by a server
I need to have three physical users, one on a screen and two on another in split screen
So what I do is that I spawn three different prefabs
Ok, you will only have 2 clients in that case. With the CO op players sharing a client
Damn that's what I thought
but I need to restrict what device gets used in the split screen
I would make the host always be the one by themselves
I'm sorry I didn't get the meaning
Oh wait yeah
it's like that already
host is on one screen, the two others in split screen
You won't be able to use player objects since that is only one per client
But for the two on split screen I need to restrict what device gets used in which side of the split screen
I would still use the player input manager for that
Doesn't the player input manager expect to spawn the players themselves?
It can but you can ,make the join behavior be whatever you want. In this case it would be an RPC to the host to tell it to spawn a player
If I have this input manager, there will be a copy of this both in each client, right? or does this live only in a server?
Because what I was thinking was the opposite: when I click on connect I spawn the two players and then have them join through the PlayerInputManager using PlayerInputManager.Join()
Is this Incorrect?
In my mind that makes sense, but then this is what happens:
The first client gets three split screen while the second one (that is supposed to get the split screen) gets none
:loudspeaker: Collaborating and Job Posting
We do not accept job or collab posts on Discord.
Please, use Discussions to promote yourself as job-seeking, advertise commercial job offers, or look for non-commercial projects to participate in:
• Collaboration & Jobs
The docs say this: so in theory this should work... which technically it does, just in a different screen. Unsure why since in my script I set the ownership of the gameobject to the client... it looks like the PlayerInputManager isn't recognizing user?
It would be local on each client yea. Just disable split screen on the host
Mhh good idea, thanks
public override void OnNetworkSpawn()
{
base.OnNetworkSpawn();
if (IsOwner)
{
GameObject playerInputManagerGameObject = GameObject.FindGameObjectWithTag("PlayerInputManager");
PlayerInputManager playerInputManager = playerInputManagerGameObject.GetComponent<PlayerInputManager>();
if (NetworkManager.Singleton.LocalClientId == 0)
{
playerInputManager.splitScreen = false;
} else
{
playerInputManager.splitScreen = true;
}
_playerInput.enabled = true;
//GameObject.FindGameObjectWithTag("PlayerInputManager").GetComponent<PlayerInputManager>().JoinPlayer();
}
}
Mhhh it looks like this line:
PlayerInputManager playerInputManager = playerInputManagerGameObject.GetComponent<PlayerInputManager>();
returns null specifically in the P2 client
Edit: apparently it's because the second client cannot find the PlayerInputManager, because I had to assign it a network object.
Mhhh so yeah split screen only in client is now working... however it doesn't look like I can set the split screen only to some players? I can restrict the number to two, of course, but it will take first player (host) and second player, not second and third?
The host player on the clients should have its player input disabled
ahhh I see let me try
This is for a game jam btw so you helped me so much
Game jams are my specialty, lol
Can I ping you in #archived-code-general ? I don't want to bloat #archived-networking with PlayerInputManager stuff
actually more like #🖱️┃input-system
Sure
thanks
Or just make a thread
Wait I think I got this for now... damn thanks so much it's working soo smoothly now
It was a pain in the ass though I daresay
I don't understand why I have a NetworkManager that is perfectly working but NetworkManager.Singleton.SceneManager is null
Network SceneManager is only initialized after the network manager StartHost()/Client()
I'm looking to lerp the position and rotation of a major object in my game and I want it to be "synced" between all clients. Ideally i don't want to necessarily network the differences specifically in the event of inconsistency(?) but more-so tell each client to start the lerp at the same time and use [SOMEDATAIMLOOKINGFOR] to decide when this lerp will end. I know i can make everyone start at the same time with a clientrpc but is there a recomended time-esque reference I should use to make everyone do the lerp at a consistent rate? I assume that even though fixedupdate would be at consistent intervals between clients, the timing of those intervals might be offset between clients right?
I could be overthinking this
Lerp is already framerate independent so as long as they start at the same, it should be fine
anyone know where this is code-wise so i can comment it out?
@delicate parrot Theres an option to turn it off in the settings for netcode
the setting stops it from doing it for you but seemingly does not prevent the nagging
You disabled the Check for NetworkObject Component? Cause we have it off in our project and I dont get nagged about it o-O
oh odd, yeah i have
What version are you on? I thought they had fixed that
22.3.45f1
@sharp axle I got my code running. I realized that during all my testing, I had accidentally removed the JoinSessionOptions with the player data in the join call. As a result, it couldn’t match the data correctly, while not exist. Now, both the client and server receive exactly the data I wanted. BTW, it is not necessary to perform a resync in the event. If the JoinSessionOption had not been an optional parameter in the join call, I would never have made this mistake.
I’ve recently started working on the networking side of my game, and I’m running into some issues. Specifically, I’m having trouble with the player prefab being spawned correctly, or perhaps there’s an issue with how ownership is being assigned. I’ve discussed this with a few friends, and they suggested it might be related to spawning or ownership, but I’m still stuck.
- First Image: Shows the installed packages.
- Second Image: Displays the NetworkManager configuration.
- Third Image: Shows the GameManager script in the Inspector.
- Fourth and Fifth Images: Depict the player prefab setup.
A tool for sharing your source code with the world!
hey, could you show me an example usage of GetRichPresence for friends, I'm having hard time.
Good to know
I meant the version of NGO you are using
Player object issues
Hey guys, need some help!
I am currently trying to figure out how to do networking in Unity. For this I am using the Multiplay Center in Unity 6000.0.36f1
When testing the WidgetsQuickstart Sample scene and trying to create a session with names such as "test" or "abc", it keeps giving me this output :(
(SessionException: Invalid client world. Please make sure it has been created before attempting to setup network.)
Any clue why this would happen in a sample scene by Unity? I am using Netcode for Entities if that changes anything
NetworkVariable is written to, but doesn't know its NetworkBehaviour yet. Are you modifying a NetworkVariable before the NetworkObject is spawned?
I am indeed assigning a value to network variable, and it works as I intended, should i worrie with this warning?
on the host i need to set "max player" variable because i couldnt find this value on (whether on the rellay Allocator or network manager) but if i set this value after i start the host the host doesnt get this value on its spawn methods. so i moved the assignment to before the start host and it works but i get this warning
(I could subscribe to OnChange but again this is simple and works fine, i just dont like warnings lol)
I wouldn't worry about it, just keep note that you're setting it early and that that has certain implications.
I believe the earliest you can set it without warning is inside of OnSynchronize https://docs-multiplayer.unity3d.com/netcode/current/basics/networkbehavior-synchronize/#pre-spawn-synchronization-with-onsynchronize
thanks, still grasping the basics of netcode
Hello can someone help me with this. I have a child of network object. i have its transform on a place when a player gets the transform of child of the object. and put a cube he already has to exactly that transform it is not in exact place does any one know why this is. I am using photon fusion 2
Netcode for Entities requires a bit different setup
https://docs.unity.com/ugs/en-us/manual/mps-sdk/manual/build-with-netcode-for-entities
ohhh alright, thanks!
What are some of the better ways to structure player hierarchy for p2p sessions?
So far spawning a Player prefab for each player that contains the player character and holds all information about said player (as well as handling input and all that jazz)
Not sure if it's better to separate the player from the character and spawn them separately only granting the player ownership of the character on join
Really depends on your game. Can the player swap characters freely? Only in character select before a match? I generally will have a player class that has all the needed player data as a client owned network variable
No, 1 character per session. Seemed like the most logical solution for this type of game. Goes as follows:
Player
|- Character
|- Camera
I was speaking more of the fact that Player here has the network object that handles all the child prefabs, since this is the way hierarchies are handled in netcode afaik, with a single NetworkObject on parent
Shouldn't be a problem, right?
Camera and input components are also destroyed on spawn if the owner check fails. Not sure if it's the correct approach either. I've seen most people simply put return statements instead of nuking the entire component
Don't destroy component. in NGO that will mess with indexes that the network manager uses to keep things in sync
Any way to intercept and never spawn them to begin with?
I wouldn't place the camera on the player object at all. the player input can just be disabled
Yeah, the camera doesn't need to be networked at all now that I think about it. Just left it there for some reason
Ok so avoid structure differences between gameobjects on different clients, got it
Disabling should work fine, ty
hello, can I have another networkprefab list? Its getting messy and I want to sort them somehow. I made secondary networkprefablist but it doesnt work at all when I try to spawn objects, only default networkprefab list works
Hello, I just had a question about the industry standard for player state management in a networked scenario.
Pretty much, I am currently managing my player state machine by having the currentState as a SyncVar and sending ServerRpc requests to change the value depending on which action is being performed (such as running, attacking, dashing, etc). I started running into problems involving the player state during timing critical actions after implementing CSP.
I was just wondering what the standard is for managing player states. Would it be to incorporate player states into the CSP loop by applying local changes immediately with reconcilation?
You can. you just have to add it to the prefab lists list in the network manager
Yep that is all part of client prediction
ohh okay that was the issue thanksi
If you are using NGO, look into using AnticipatedNetworkVariables for the client state.
Client anticipation is only relevant for games using a client-server topology.
Gotcha! So would this mean that I would be dropping the use of currentState as a SyncVar, since I will be making immediate local changes to the player state anyways (using FishNet, not NGO).
And just handle the syncing through server and observer rpcs?
Dunno how Fishnet would handle it but yea.
Gotcha gotcha tyvm! ^^
you are using fishnet, that's a homemade library, industry talk wouldn't apply to that
hello Im making a 3d game like 4 player pong and I have a problem with balls in networked environment. Issue is if I enable interpolation they really miss collisions, changing positions early etc its weird. If I disable interpolation than this time it just looks so bad on clients. How can I make it better? Velocity of ball is like 30f. I increased tick rate to 64 from 30 , it helped but not good as I wanted.
Is there any way to get some decent logs on why a user may have disconnected? I have all the developer logs turned on, but sometimes a client will just disconnect with no message. The server only says that a client disconnected, while the client just says the same. I don't seem to see a way to tell if this was from timeout, desyncronization, being kicked, or some other internal process.
You'll need create your own interpolation. But networking physics is very hard. Check out the client anticipation section I linked above if you are using NGO.
If you are using NGO, I believe you can increase the log level of the network manager. But if it's happening randomly then it's like timing out for some reason.
Yeah, we're on the highest debug level for NGO, but nothing shows up
So I built a custom timeout detector, as I cant seem to find a difference between a client timeing out from a connection disruption vs a client just disconnecting because they pressed disconnect
Basicly just subbed to the transport's OnTransportEvent and set up a timer
Perhaps its WebSockets? We had to switch because of how our docker container needs to work, and the problem started showing up at roughly (give or take a week) the same time
You can try having the client call DisconnectClient() on itself and give a string reason. I don't know if that is a server only method though
📃 Large Code Blocks
Use links to services like:
https://paste.mod.gg/, https://hastebin.skyra.pw/, https://paste.ofcode.org/, https://paste.myst.rs/, https://scriptbin.xyz/
📃 Inline Code
Surround code with three backquotes. Not quotation marks.
To format as C#, add cs to the first line:
```cs
// Your code here
```
Add a comment with a line number if there is an error message.
Is it a good idea to extend NetworkManager and add a bunch of processing during player connect/disconnect or would it be better to create a separate manager and listen to NM events? 🤔
Really feel like I'm asking the most basic stuff imaginable but when it comes to networking I get a feeling that there's generally just a few ways to do something "right"
not the most experienced but extending the NetworkManager wouldnt invalidate the NetworkManager.Singleton?
and the prossessing you are talking about cant be done on NetworkManager.Singleton.OnConnectionEvent?
Yeah, exactly with those events
Singleton could be re-implemented rather easily
So it'd just be
CustomNetworkManager.Singleton
the way i am doing, first time learning netcode, is i have a session manager where i mostly comunicate woth and manage this events
probably is what you were talking about
Eh, I guess it works
Trying to not fall into manager hell where there's a manager for everything
😅 me
Yea. there is an example in one of the samples
Awesome, looks like it won't break anything. Ty
@lilac forge looks like the next update will include some options for transform interpolations
https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/pull/3337
I'm working on a multiplayer small arcade game and there's something I quite can't figure out. I manage to get all clients to connect but after a little bit one of those players gets destroyed (by the client nontheless) and therefore crashes everything. I know as a fact that my scripts are not destroying it because the only case in which I call Destroy myself is within Bullet.cs and there's nothing in the scene with that Component (and anyways it wouldn't try to destroy the player) so it must be something engine-related but I have no clue what. The only other Destroy I've seen is within the inpuaction script that was auto generated by the input system
I'm losing my hair over this tbh
Make sure the client isn't calling Despawn() either. Components shouldn't be destroyed if you are doing that anywhere
No Despawn either
It's like it's trying to destroy all game objects, it tries to destroy everything that is in the scene
Is the client trying to load a scene?
The scene loads, after like 5 seconds in the scene everything falls apart
it loads via the auto sync feature in the networkscenemanager
There's no coroutines running
Like out of nowhere, no warning before the big crash
public class PlaySceneLoader : MonoBehaviour
{
[...]
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
switch(NetworkManager.Singleton.LocalClientId)
{
case 0:
SpawnClientServerRpc(NetworkManager.Singleton.LocalClientId, (int)PlayerType.King);
break;
case 1:
SpawnClientServerRpc(NetworkManager.Singleton.LocalClientId, (int)PlayerType.Attack);
SpawnClientServerRpc(NetworkManager.Singleton.LocalClientId, (int)PlayerType.Shielder);
break;
}
}
[Rpc(SendTo.Server)]
private void SpawnClientServerRpc(ulong clientId, int prefabId)
{
GameObject newPlayer = null;
switch (prefabId)
{
case (int)PlayerType.King:
newPlayer = (GameObject)Instantiate(_kingPrefab, GetRandomPointAround(_sessionSpawnPoint, _spawnPointsScriptable.spawnRadius), Quaternion.identity);
break;
case (int)PlayerType.Attack:
newPlayer = (GameObject)Instantiate(_attackPrefab, GetRandomPointAround(_sessionSpawnPoint, _spawnPointsScriptable.spawnRadius), Quaternion.identity);
break;
case (int)PlayerType.Shielder:
newPlayer = (GameObject)Instantiate(_shieldPrefab, GetRandomPointAround(_sessionSpawnPoint, _spawnPointsScriptable.spawnRadius), Quaternion.identity);
break;
}
if (newPlayer == null) return;
newPlayer.SetActive(true);
newPlayer.GetComponent<NetworkObject>().SpawnAsPlayerObject(clientId, true);
}
}
Ok wait am I doing something wrong here? I keep getting "Only server can spawn"
But it's in a fucking ServerRpc
This needs to be a Networkbehavior not a monobehavior. Also change Start() to OnNetworkSpawn()
oh wow I hope it will! thank you
Ohh thank you so much as always
can I change ownership of an networked object but while also make it still owned by server?
Objects can only have one owner. If you remove all owners then it defaults to the server as owner
Is anyone experiencing the issue of registering webhooks for their Unity Cloud Build?
My code was working fine until yesterday. It is now returning "500: Internal Server Error". I have also tried this directly on Unity API: https://build-api.cloud.unity3d.com/docs/#/webhooks/addHookForProject
with a the sample payload:
{
"hookType": "web",
"events": [
"ProjectBuildSuccess",
"ProjectBuildFailure"
],
"config": {
"encoding": "json",
"sslVerify": true,
"url": "http://unity3d.com/example"
},
"active": true,
"id": 7
}
It still returns "500: Internal Server Error"
Not much you can do about an internal server error. I would open a ticket with support through the Dashboard.
What is this error? Can't find anything online about it
This seems to be the source of the issue. This script is attached to the default player prefab for the NetworkManager. When a new player appears on the server a character should be created. Is this not correct?
namespace Network
{
public class Player : NetworkBehaviour
{
[SerializeField] private NetworkObject characterPrefab;
[SerializeField] private GameObject cameraPrefab;
public NetworkObject character { get; private set; }
public override void OnNetworkSpawn()
{
if (IsServer)
{
NetworkLog.LogInfo($"Spawning player for {OwnerClientId}");
character = Instantiate(characterPrefab, transform.position, Quaternion.identity);
character.SpawnWithOwnership(OwnerClientId, true);
}
if (IsOwner)
{
Instantiate(cameraPrefab, transform.position, Quaternion.identity);
}
}
}
}
Probably also worth mentioning this happens during late join, when a player (and a character) are already present in the world
And before newly joined player gets a player spawned
So likely something to do with observers that replicate network objects already spawned to joining clients. No idea
I guess this works:
public class PlayerCharacterLoader : NetworkBehaviour
{
[SerializeField] private NetworkObject characterPrefab;
public override void OnNetworkSpawn()
{
if (!NetworkManager.Singleton.IsServer)
{
enabled = false;
return;
}
NetworkManager.Singleton.OnConnectionEvent += OnClientConnected;
}
public override void OnNetworkDespawn()
{
NetworkManager.Singleton.OnConnectionEvent -= OnClientConnected;
}
void OnClientConnected(NetworkManager m, ConnectionEventData d)
{
if (IsServer && d.EventType == ConnectionEvent.ClientConnected)
{
SpawnPlayer(d.ClientId);
}
}
void SpawnPlayer(ulong clientId)
{
var character = Instantiate(characterPrefab, transform.position, Quaternion.identity);
character.SpawnWithOwnership(clientId, true);
}
}
But still though I have no idea why can't I just use player prefab as an entry point for my clients
Since the script above is I'm pretty sure almost exactly what NetworkManager does when you specify a default player prefab to spawn
A player is added, server-side code runs during player spawn to create a character. What's wrong with this? Am I missing something?
Hey I have a problem with loading the scene for my clients. This is my code:
private void LoadGameScene()
{
this._loadingScreen.SetActive(true);
this._lobbyController._stop = true;
if (NetworkManager.Singleton.IsHost)
{
NetworkManager.Singleton.SceneManager.ActiveSceneSynchronizationEnabled = true;
NetworkManager.Singleton.SceneManager.SetClientSynchronizationMode(LoadSceneMode.Single);
NetworkManager.Singleton.SceneManager.LoadScene(this._gameSceneName, LoadSceneMode.Single);
}
}
Anything im doing wrong or why wont the scene load for my clients?
Hey, looking for a solution to the problem that UnityWebRequest request.downloadHandler.text contains "?" instead of diacritic characters.
We are downloading data from PHP endpoints in a serialized JSON format from a mySQL DB.
In the DB I have some text in a JSON blob that contains the data "Señor" note the diacritic mark.
When I test the PHP endpoint in the utility PostMan, it looks like Señor is represented properly in the returned data.
Yet when the data gets to request.downloadHandler.text, we see "Se?or"
My DB guy assures me the returned data header contains
header('Content-Type: application/json; charset=utf-8');
What gives? Thanks for any ideas!
Can you check the encoding on the string you recieve?
request.downloadHandler.text should be in UTF-8 which should support that character. You could try System.Text.Encoding.UTF8.GetString(request.downloadHandler.data) instead to make sure the issue doesn't lie within the .text property
How would I do that?
yeah, I am already debugging that System.Text.Encoding call on the downloadhandler.data and it shows the question mark also.
The curious thing is my PostMan utility (I think it is Mac only app?) shows the data and the diactitic is there. So I can't help but think it is at the Unity end...
I found a similar problem on stack overflow (here). And the problem was that c# uses Unicode for the strings. So I think you need to make shure to use a utf-8 string like @tame slate said.
thanks! I'll check it out.
Please help, Im struggling on that for literally hours. For some reason it boost and movement works for host perfectly but for clients, only boost works and movement not works at all. I tested player numbers they are fine. I think loading input system is also fine because second player can do boost but cant do movement I just cant understand.
does anyone know how to fix the error Messages were received for a trigger of type RpcMessage associated with id (0), but the NetworkObject was not received within the timeout period 10 second(s). on the server when i send an rpc message from the client? the client also give the error The given key 'WorldManager' was not present in the dictionary. before the timeout, the network object WorldManager with the WorldManager script exists on both the client and the server, so im not sure why it can't be found when im trying to send an rpc request to the server? even if i remove all code inside the rpc i still get the error on both the client and the server, so the rpc itself is failing to run, not the code inside of it
This is either sending an RPC during OnClientConnected() or the scene is taking too long to load
How can I make islocalplayer works for new spawned objects? Or How can I disable spawning object for player from networkmanager? My game has a custom character selection, I want to get rid of it
how do i fix both? where should the rpcs be sent from?
RPCs should only be sent in or after OnNetworkSpawn()
Remove the player prefab from the Network Manager and it will not spawn automatically. You can also use .SpawnAsPlayerObject
PlayerObjects are an optional feature in Netcode for GameObjects that you can use to assign a NetworkObject to a specific client. A client can only have one PlayerObject.
how do i send it when a scene loads after network spawn? i could make it run in update and set a bool to false on it's first run that causes the an if to not make it run any more but is that the only way? that'd be constantly checking values every frame that way
There is a OnNetworkPostSpawn() or you can check IsSpawned. There are also SceneEvents you can listen for
If you haven't already read the Using NetworkSceneManager section, it's highly recommended to do so before proceeding.
Is there any conventional way to send large files (images, videos, map data) over network to clients?
Or do I have to make my own implementation to break the data into multiple packets
But even then a 70mb file is around a thousand packets
Doesn’t seem very efficient
@rich meteor Does this file need to be synchornized over the netcode? Or do you just want it to download and you dont particularly care that the users recieve it in a synchonized way
because if its something that's state doesn't really matter that much, Id recommend just doing it over old school socket implementations.
However, if its something that should be synchronized, say custom drawing data from users, youll want to break it up with some kind of message system.
If this data is in a network variable however, theres a bug about very large network variables open right now. If the data is more than ushort (65565ish) bytes, it will disconnect any new users who join if you have network variable saftey enabled
Our team struggled with that one for a bit lol
I needed to synchronize game terrain data (height maps and a bunch of other technical maps) that adds up to 20+ mb, as well as a couple procedural textures
So ideally synchronized, but sounds like a pain to set up
Actually transferring the data wouldn't be too bad over netcode. But id worry about users having issues with connectivity when joining an existing session. We have to deal with GIS data (basicly geographic drawings) that can be several megabytes and it puts a large strain on new users who connect. Remember: if your sending these in a synchronized way, the user has to recieve all the data before they can 'join' the scene
If there are any tricks you can do (For example, sending a 'recipe' to generate the texture, rather than the texture itself), consider those first
Or, for height maps, consider splitting the data into height tiles, and only sending tiles to users when they're in range where it makes sense
A lot of the same problems your dealing with now are very similar to problems in the GIS (Geographic Information System ) field. Id give a look to how they deal with these problems, as they can save you months of flailing for a solution
I work in GIS, so if I can help, hit me up in a DM. Im happy to give advice on these matters
This is the big one. if your doing proc gen stuff ideally you would just sync the seed or whatever equivalent so each client just generates it identically
That's fine, I think it's expected to to have the user wait until all the necessary minimal data is loaded, even in synchronous way
Especially considering the fact that the world is finite and not particularly huge (<50mb), don't think there's much benefit of dynamically loading chunks of land as the player moves
Well, I forsee pain in your future with that level of synchronization, but I could be wrong. If you do manage it, I would be very interested to hear the results. Ill send you a sample of the encoder / decoder we wrote for dealing with our 2mb geodata files
I'll look around for some of the ways you can do that, doesn't seem to be any out of the box solutions in netcode as they likely never expected anyone to do this
Naturally
Though that tends to usually imply solving the problem would ideally be done through another route
Yeah, I would be cautious of doing it this way. We share a lot of map data between users, but 99% of it is done outside of netcode, as you dont really need the precision and accuracy that netcode offers. For textures, it might be viable to just load them in as they download, rather than forcing clients to download them as part of scene sync
Same with heightmaps and the vast majority of things related to GIS
Netcode works best for objects you expect users to interact with and change often, rather than static data you would query
I’m most certainly not gonna be doing it through netcode though the more I read into it
Which is a shame since I’ll have to open an additional connection to load large and need to write extra code to transfer them all myself but what can you do
There are other solutions that could work very well to reduce boiler plate. Depending on the type of data, you could use GRPC / Magic Onion to setup a micro webserver to serve the content. Our solution for these kinds of problem is that we actually run an entirely seperate webserver. What we sync over netcode is just the URLs that point to various peices of content
The fact that my current toplogy is client-host doesn't make it better
I'm tempted to go full dedicated but then again, that's just adding more complexity
Before I know it I'll be contemplating "oh, but why use netcode at all? I should use this other library for networking and increase the work needed tenfold"
Same pit I keep falling into time and time again
Well, NGO does some things really well. When it comes to synced data, its fantastic. Its got a very good system for network serialization and is blazing fast. For things that need to be high precision, I would definitly use it. Things like player position, states of enemies, locations of bullets, ect. I've had great success with our dedicated server architecture running inside of a docker container
Its just not a magic bullet that will solve every problem you have. Right tool for the right job is the key, especially in Unity
We keep the location of all players avatars and hands (we're a mixed reality AR map) synced with netcode and it works amazingly well
Trying to build a multiplayer system from scratch is a fools errand, unless your in a well funded and large team.
True. I'll just look for an alternative ways to send large stuff during the initial connection, should be relatively simple with everything network-related C# has
And if push comes to shove migrating client-host into to a dedicated shouldn't be terribly hard
Does the animator variable get automatically synchronized in netcode? It seems like when I do new AnimatorOverrideController() on a instance of myself in another build , it seems to undo any changes i've made on my side.
For context, I'm trying to swap out some abilities at run time. This works, now I'm just tryna sync the animations with the swaps. Everything works fine when everyone's already in the game but as soon as someone joins, they get reset like new AnimatorOverrideController() was called even though I've logged that it is indeed being called once only on my side.
It just seems like because I get created on the other build, it resets mine on my side.
I know this cause the moment I do if (!IsOwner) return in this method, i dont get reset. Unforunately this doesn't let me create overrides on the other side tho. Kinda stuck there
(Nothing is automatically synced in netcode)
Thats something I've known. I'm just questioning everything at this point
is this on the player?
yep
Not too sure sorry
thats alright
Not trying to stack overflow you here but are you sure the right solution to netcode not handling large data the way you want is to find another way to send large data rather than avoiding sending large data? Just curious what would require this
What's wrong with sending large data?
You join a game, you download procedurally created game files
It's not like it's a couple gigabytes
I seriously don't see why it should be streamed asynchronously
Most games doing proc gen like that don't send over the results of the generation, they send over the seed used to make it
Yeah if the game world is infinite
you don't need to send a 20mb heightmap if the client can just make an identical one locally
No my issue is that it can be modified
So I need to send to the client whatever the players did to the poor terrain
Yes I know I can ONLY send changes
But I don't see how that's beneficial considering the world isn't super big
I mean it's beneficial in that you'd be sending small chunks of data rather than big ones(?)
Hi, I changed the package relay to multiplayer service and now the RelayServerData don't accept the Allocation directly. What can i do?
I mean yeah sure I'd be able to use netcode for syncing if I stream the tiny chunks but like
It's 20mb
I think it's fine to just fetch it all when you join, that's not a terribly lot of data
Have you concidered sending only the deltas? Like, you send the data to generate the base heightmap, along with whatever changes users have made in this lobby. That could cut down on the traffice conciderably, to the point where it might be network syncable again
Yeah I did just say that
But then again I seriously don't think data that's over the limit for netcode messages but still so small in the grand scheme of things warrants doing all the prep for this kind of syncing
Lol it wasn't being reseted. The other client's settings were being written onto my side. also both players were sharing the same AnimatorOverrideController. which made things more confusing. Creating a new instance of the override controller did the trick and doing if (!IsOwner) return was indeed the right step
glad to hear you figured it out. it can be really hard to passively wrap your head around what network based context stuff like players are in when writing code in my experience
recently all my networkbehaviours derive from this little setup to help me kinda understand what is gonna be running where
sealed public override void OnNetworkSpawn()
{
base.OnNetworkSpawn();
ClientInitialize();
if (OwnerClientId == NetworkManager.LocalClientId)
LocalInitialize();
if (IsServer)
ServerInitialize();
}
protected abstract void ClientInitialize();
protected abstract void ServerInitialize();
protected abstract void LocalInitialize();
Wouldnt that potentually cause problems in Dedicated Server mode though? The dedicated server is not a client, and calling NetworkObject.IsClient would be false
Personally, id also go Server Init -> Client Init -> Local Init, as that should go from largest scope to smallest scope. The server might be setting up network variables, loading inital values, and doing complex setup. The client is generally reading those setup values and getting itself configured.
You could also argue the order might be Server Init -> Local Init -> Client Init. That way, the 'owners' also go first, and then the client init would be called
In terms of exclusively network related code i would agree but a lot of non network related setup are things i want to run post network spawn so i tend to handle those in client and such
Personally, Id adjust the names in that case, to something like PostNetworkSpawn. If its a small project, its all good and this is just being pedantic. But thats the kind of stuff that will make maintaining your code difficult if the project grows.
yes, it's also a solved problem
this terrain data is static?
No, as I said it’s going to change during the game, the players will modify the height
And I’m also aware of the approach of just sending the changes and generating the rest of the terrain procedurally on the client
how will they do that?
is that well defined?
if so, you can sync those events only, and edit locally
Just an rpc to modify the height (byte) either by 1 or -1
after inital sync
Right but I'd still need to get the initial map
why, what are you building
You ever played Valheim?
players change height data, byte by byte, in that game?
Yes
A byte ranges from 0 to 255, so a terrain can be 255 levels high
Initial generation is done, then you can shovel it or whatever to raise/lower it
Maybe they used ints for the height or floats instead of bytes, no idea, but I'm using bytes
their height map resolutions looks low res, and how big are their maps?
Probably way bigger than mine. No idea about the max height
look into streaming the changes over time, similar to how minecaraft syncs the voxels
u don't need to sync the whole thing immediately
and prioritize near by regions
so basicly you will divide up the map into chunks
Dude the whole thing is like 15mb, why is everyone so against just loading it during the initial connect? Is this really that much data?
I haven't completely caught up on this thread but large files should be sent through a file server. Either a CDN or AWS bucket or Unity's User Generated Content service
Maybe I'm missing something
you don't just send 15mb from a game server
this is a real time game
I would prefer not to use any 3rd party services. Why is this even necessary?
not a http server
During the initial connect, when you're loading into the server
That would literally be a 5 second wait
you can do that yes
Probably even less
but you don't want the server to lag due to sending so many packets together
Exactly, yes
That's gonna be a lot of packets if I go with the 60kb ones
So I'm looking for alternatives
Max packet size on the internet is like 1500 bytes
i already told you how to approach the problem
Surely there are protocols that make sending large amounts of data not as straining?
u don't need to sync the whole thing immediately
and prioritize near by regions
so basicly you will divide up the map into chunks
so when u first connect
u will only get the near chunk
Yes. File server protocols like ftp
which won't be that big cause it's just one chunck
etc
or all nearby chunks
you get the idea
while the other chunks
are being recevied slowly
in the background
that makes no sense
that will never happen
cause the issue is in the size
not in the protocol
Is sending 15mb of data to a client really that much that the server will noticeably chug if I try to do this? I will admit I don't know that much about best networking practices
if you are making a web app
then don't worry
cause the issue is games are real time
and they can't just send 15mb to some player
But that really doesn't seem like a lot of data. It would probably also be possible to do this work on a separate thread
even Steam limit download rate to 200 MB/s
let alone some game server
So let me get this straight
Computer A needs to send 15 megabytes of data to Computer B
You could use addressables as well
no
And it's such an enormous task that it can barely manage
you have many computers connected to one computer
and this is a real time game that can't stand any frame taking longer than 30ms
But that also requires storing addressables on some other file server
or whatever your tickrate budget is
Computer A is hosting the game
Computer B joins
Computer A sends data to computer B
Why would I send the data each frame
I don't want to send it in a few frames what
I just told you I'm fine with a couple of seconds of initial loading
Are we on the same page here? I'm not sending the ENTIRE map every time a player makes a change to it
I'm sending the change to all connected players
But during the initial connection, I need to let the new client know the state of the map to begin with
You can manually serialize it and fragment the message if you really want
But it's a bad idea
Doubt a giant array of bytes + width, height of the map is gonna be tough to serialize
Any of those fragments gets lost or dropped the entire file needs to get sent again
here
in the context of game networking yes this is a fairly uncommon and large task
I say give it a shot and report back
I probably will because it sounds insane
Like
Again I'm not experienced in game networking at all
But the idea of 15mb being an insurmountable amount of data for modern computers and networks is surreal
lol you don't get it
this is not a web app
that's why
if it was, yes, it's not a problem
How is a C# game server sending data differ from C# web server. You're still just sending bytes
response latency
20mb is not a lot in terms of local storage, whatsoever, because it's in the context of modern devices having 500gb - multiple tbs of max storage
20mb is a fuckton in terms of networking in the context of games because most networking related things get optimized down to the individual bits and bytes
games operate at 30 to 7ms
otherwise
your game is lagging
web server operate at 100-2000ms
Web servers are not the ones sending the data. They use CDNs and file servers
your 20mb texture is roughly the equivalent to over 20 million bools afaik
comparatively it is very big compared to how much games ideally send to eachother
doing the initial gen locally and saving the changes is comparatively far less data to send
and then hypothetically saving the inputs/actions that actually modified the terrain would be even less
(eg. in this case something maybe like saving and sending the targeted pixel index alongwith an int value indicating the number of times it's been raised or lowered compared to it's starting point)
At this point just chunking and sending a bunch of terrain fragments <44KB is simpler
It's still wild to be. Is there no way to just have 1 process constantly send bytes and a second remote process receive them and when done reinterpret it into something usable, like a byte array? I know I'm probably mising some crucial networking basics
To one player it seems fine. But scale it up to 20, or 2000? Your monthly bandwidth is not infinite and will start to add up
the processes your looking for aren't in place because they aren't the way anyone does them, not because they can't be done
If you prefer to go your route I'm the last person that's gonna dunk on you for doing your own thing but engine stuff, particularly networking stuff isn't really designed for what is the simpler way
Any of those packets get dropped and they have to be resent to get something useable on the other end. Even a 1% drop will end up snowballing on your server and will never catch back up
Eh, a session with a bunch of friends would probably be an equivalent of a youtube video or two. And that's if several of them rejoin a couple times and if I don't have any kind of caching in place
I will not have 2000 players
Wait so this kind of thing happens every time you download a file online?
Yes, files get corrupted all the time
Also media streaming is a very different thing. No one cares if a single frame of you video drops.
yeah streaming stuff is very incomplete because you can lose a lot without it being actually noticeable
Ok so the issue with that is that if I send, for example, a 64x64 chunk of land to the client, 4KB, and even a byte of it gets corrupted or missing otherwise it will resend it
And the problem is that it might end up sending 32KB instead of initial 4KB because the other 7 attempts failed
Unity uses Reliable UDP, which is pretty decent (Unless you manually ask it to use unreliable). The MTU for netcode is around 1.3k bytes. If you send a message thats larger, it will be split into smaller packets of up to 1.3k. Unity Transport is pretty good about reassembling these, so outside of very poor connections, you should be ok. But if your sending large amounts of data over a poor connection via Netcode For Game Objects, remember that a user cant 'enter' the game until its synced. The time this could take may lead to the user being kicked
Basically, yea. Depends on if your terrain system needs the full texture or can still load from the incomplete/corrupted one
So ideally you keep your stuff under 1.3KB?
I mean, ideally, but its not a requirement. If your 'message' is larger, its automatically fragmented into a bunch of smaller packets and sent.
Hense the bug I pointed out about if your message is over 64kb with network variable saftey on
The actual max size of a message is int.maxValue. Dont do that though
And in case of a corruption/loss?
Singe packet should be better right? Because with 2+ packets per some whole data you're essentially increasing the chances of the whole thing being dropped and resent proportionally the amount of packets you used?
Or is the transport smart and doesn't resend everything
The dropped packet should be the only one that gets resent, in theory. I dont know the exact workings of Unity Transport though. In general, its not something to worry about however
Alright, with all this being said and since sending the whole map is out of the question, I need a reality check. Is sending a bunch of 32x32 (roughly a KB) chunks as plain bytes with no (or basic) fancy compression to clients as they run around and load everything really a terrible idea or just not ideal?
Should be fine? Depends on the exact implementation and how many of these chunks are 'loaded' at once, but theoretically not a problem
Im syncing around 500 kb of data when players join and its fine
This approach would be syncing the data constantly though as the sessions progresses, since the whole map proved to be too big
Its more of a question of worst case. If you have like a gigabyte of data that was transfered to the players over the session, but it was all done in small increments, you wont have an issue. But if you had to send that same gigabyte all at once when a user joins youd be SOL
Yeah I was more concerned about that resending thing if it drops. I mean sure it's gonna be much much worse if it drops while you're trying to transfer the entire map
But still. How many people have such limited internet plans anyway?
Referring to this message
Its more of a question of what's suited to what purpose. NGO is designed for very high precision and transfer rates. Its for sending small deltas every frame, rather than a big chunk of data occasionally. It absolutely can still be used for both cases, but one approach is 'safer' than the other. As I said earlier, I work in GIS, where we deal with altitude data (literally 32x32 short arrays lawl) for displaying our map in 3D. Personally I would sync player relevant data over NGO and use a TCP socket or ASP.NET web server to serve the altitude data your server generated.
That being said, you can absolutely go with the approach you've described, and I think it could work. Its just not as 'correct'. Just like you can hammer in a nail with the butt of a screwdriver
At the end of the day, the nail is in the wood. Who cares?
use a TCP socket or ASP.NET web server to serve the altitude data your server generated
Eh, can't bother. You sound like you're in some serious business and I'm just making whatever in my spare time
Yup, so follow your dreams lmao. Set up an elevation tile networkstruct that just has a native array in it and your golden
Besides, it's a client-host topology. One guy hosts a game, another guy connects
No chance I'm hosting any sort of servers for them lol
But even if it was a dedicated server, little difference
keep a network list of what tiles are currently visible. Be sure to turn off 'NetworkVariable Length Safety' as theres a bug in it that could cause issues with your approach
Ty ty
Hi, i am new to networking and I am using same PlayerSpawner for Lobby which when I call StartClient it works perfectly fine but once all Players are ready and we load a new scene using NetworkManager.Singleton.SceneManager.LoadScene("Game", Single); Only the host PlayerObject is begin created but not for all other Clients. Why is that?
"OnSceneLoadComplete" never get called on any of Clients
Because you're subscribing to it in an if block that checks for IsServer
It still doesnt spawn Players even if i remove if check, and it worked when i load Lobby, same code
now OnSceneLoadCompleted gets called on Client with correct id but somehow InstantiatePlayerOnServerRpc never gets called now?
Looks like it is getting called but the PlayerPrefabtoSpawn is not set on the host
there exist only 1 PlayerSpawner object in the scene and it has reference to Prefab and is correctly instantiated the Host but not for the Clients😭
when I load new scene, the previous PlayerSpawner gets despawned and destroy and new PlayerSpawners get called OnNetworkSpawn in the new scene
Can we stop relay service temporarily through dashboard? Like in case if my game is getting high usage of relay and I don't want to go bankrupt. Is there anyway to immediately stop relay services and re-enable them when we like.
Yes. If you need it to persist, then it need to be set to Do Not Destroy On Load
No but you can use Relay without entering any payment info. It will then stop any connections beyond the free tier.
i need to spawn new one
My game already used 65% usage since it got a lot of players recently
I can't keep it on free plan any longer
1 way I thought of setting a Boolean remote config variable to stop players from creating or joining allocations
It's monthly pay as you go, there are no plans - just not entering payment info would pretty much achieve the exact same result as the solution you described above
No but I want to go to pay as you go plan, I don't want relay to not work after hitting free tier. I just wanted to know if I can in future just stop relay service to not go in debt
@tame slate
Now you are trapped into unity ecosystem
😂
Remote config is only option 🥲
This will help
At least people are playing your game! Thats a plus 😭
Yeah then some sort of backend service toggle would probably be needed. I wouldn't worry about it too much honestly. You'd have to keep growing at your current pace to go over the free tier, and even if/when you do go beyond the free tier, you'd have to blow beyond it at an insane rate to go "bankrupt" or "in debt". At which point you should definitely be monetizing the game.
The reason I mentioned "debt", is my game is free to play, it does have In Game Purchases. So there can be a chance of that.
this would be a great way to go about things, along with the adjustments mentioned in the later messages. I kinda just dived in, worrying about the elegance later and refactor as I go. Should I start prototyping another multiplayer game somewhere down the road, I'll definitely go ahead and set this up in my library.
a youtube video uses more bandwidth than a fortnite 100 player match, which costs Epic games millions of dollars monthly for all their servers
Ok but why would I care I’m not hosting anything for them
My players that is
If ever get any

i just wanted to give you an idea of how expensive bandwidth can be
Right but the scale is way off
And that was before I properly understood the limitations of data transfer
So it’s not that 20mb is terribly expensive to transfer, it’s just that there’s no good way of doing that in a context of a game server
also your problem is very easy to solve as i already told you many times
Divide the map into chunks, find which chunks are the closest to your player, send whatever changed data in them to that player.
And for all other chunks, go through them one by one slowly and also send their changed data to the client. But they are less prioritized so the client will take some time to fully get up to date data on them
problem solved
Yeah I ended up doing that
I just didn’t know there’s literally no good way to send a large file from server to client
A network list should do it
Just sync tiles with netcode
no, that misses the point, you want different data to be synced to each client
cause each client is at different position
Why if the map is so relatively tiny
It’s not infinite I’m not making Minecraft
Just sync it all it’s not a lot of data
what matters is you need your incoming data rate in the client to be less than 100 KB/s
if you manage to do that, good
there is a reason why fortnite or other games which send so much data and do so much
and still are below 100 KB/s
and as others said
if you don't want your game to suck
you need to send as little data as possible so resends don't kill the time responsiveness of the game
and to be honest
we are talking about height data
which changes very infrequently
so if you are smart about how you send things, you will not have to send much at all
I seriously don’t care if there’s a minor hiccup on the server when a player joins and gets all the tile data sync. If it gets too bad then I’ll start optimizing
lol that's not how gamedev works, your opinion does not matter
people will talk shit about your game
if it does that
I really don’t give a damn
I’m not gonna optimize a 20 mb map loading by making a fancy system that only records and sends changes or whatever the hell
I’m just making whatever
then you will fail
I’m not doing game dev for money that’s stupid if you’re talking about that
you might be lucky and find some github repo doing it already for you
look for minecraft clones in unity in ngo or mirror
cause the system they use is similar
I certainly would have
If I was making an infinite world
But since I’m not
I can’t bother
even if you only had to sync 512 KB/s, you still have to do this
let alone 20MB
and it's your choice
you can go ahead and ignore all this and go make a laggy game
Hi everyone,
I'm investigating a development opportunity and would love to get some feedback on what I'm planning can or can't be done.
There is an existing app for RC cars (which is not mine) which has been built using unity3d. Every player has their own instance of the app on their device to control their own car. A player can open a multiplayer session and let other players in the same network join it. As far as I can see, data is being exchanged through UDP and the server runs on port 7777.
I would like to create my own app which "joins" this multiplayer session to receive data from the race to display it as some kind of a central race monitor.
If I watch the data transfers through Wireshark, I can't make much sense of whats being transmitted. Sometimes the data will contain what seems to be JSON (but with some binary data before the JSON), sometimes its not readable at all.
From what I saw, I guess the client sends some sort of "hello" to the server when the player joins the session and then there is some ping pong going on between client and server afterwards.
I guess my questions are:
(1) How does unity3d compress/encode data which is exchanged through UDP? Is there any chance to convert it into something readable?
(2) Would I be able to create my own app to join the multiplayer session without deeper knowledge on how the server code looks like?
Thanks in advance!
this entirely depends on the networking middleware used. Unity has no network synchronization built-in that everyone "has to use". You could however expect, that if its done properly, its a delta compressed binary representation of the various datapoints. When you see json it might be something like messagepack, a secondary mechanism to sync large data packets or some intermediate string thats not really part of the network transport.
What you are asking here is how to hack into the network session with a 3rd party app.
^ and this is what that actually means
The original app could be run an open TCP server that anyone could connect to. Or it could have an API that could be used by a 3rd party app. Both of those are outside your control
Hm, I didn't think of it like that. I guess you're right. Although its for my personal enjoyment only 😄
not all hacking is nefarious. Its doable depending on its security but you'll not get much help with that here
Yeah, I totally understand that. I'll try again and see if I can get any information from the manufacturer of the original app. They're are not really responsive unfortunately. But thanks so far anyway!
Hi, is this the correct way to serialize this data? I want to serialize a list of data that contains another list
That should work.
What are the requirements for RPC to work?
I have two scenes, one scene will act as "server" and the other scene as "client"
I want an RPC to work so that the client is the callsite and it runs on the server
I tried making a singleton that exists on both client and server with the same script that inherits networkbehaviour and has a RPC, but it doesn't seem to get run on server when invoked by client
any suggestions?
The server would have to have both scenes loaded and a specific instance of a NetworkObject containing the NetworkBehaviour you're using has to be spawned
The scenes would need to exist on both.
If you don't want shared network objects between client and server then you would use Custom Messages
A brief explanation of Custom Messages use in Netcode for GameObjects (Netcode) covering Named and Unnamed messages.
Hello, sorry if this is a dumb question. I have recently migrated from NGO for unity 2022.3 to unity 6 with NGO (2.2.0). I am confused as to what this new ownership dropdown means / is used for in the network object component. I tried looking on the unity documentation page for Network object but they don't mention it and in fact the screenshots on the page don't show it. Any help or point in the right direction would be appreciated. thanks in advance.
https://unity.com/products/distributed-authority
This one if im not mistaken.
Hm, seems odd that it defaults to distributed. This dropdown didn't exist on previous versions so im unsure which to set it to if I want client server architecture with relay
Ownership status only applies when using DA. you can ignore it if not
By default, Netcode for GameObjects assumes a client-server topology, in which the server owns all NetworkObjects (with some exceptions) and has ultimate authority over spawning and despawning.
Ahhh I see. Thank you!
I cannot use directly NetworkConnection right, so if I have 2 players ID how should I find NetworkConnection for both players? To send them messages?
Or can I store player NetworkCOnnection dirrectly in runtime on the server?
Is it right approach if I store player NetworkConnection inside game class (runed on the server) and when player disconnect set it null until player reconnect and when it reconnected update it back?
What network library are you using?
Transport
Is there any particular reason you are using UTP directly instead of NGO?
I use it for board game, I do not need higher level api
Would you recommend me to use NGO, does it has some practical benefits?
You don't have to keep track of NetworkConnections, for one
Currently I do not use GameObjects on the server only on the client, can I use same way with NGO?
But for a boardgame you might not need realtime networking at all. check out the Cloud Code Chess sample
I checked it but I'm thinking about dedicated physical server
You can use Custom Messages if you don't want to use Network Objects
A brief explanation of Custom Messages use in Netcode for GameObjects (Netcode) covering Named and Unnamed messages.
It looks like a messages I'm currently using.
And it is doesn't look simpler then just Transport.
I have a NetworkVariable that contains a list, which itself contains another list. The OnValueChanged event is never called on either the host or the client. The NetworkVariable updates correctly when its value changes (I confirmed this with Debug.Log), but the event never triggers
screenshots are an aweful way to share code
can you send the lines where you modify the variable and where you subscribe to the on change event, if they are there i couldnt see
The last line is the one that modifies the variable
[Rpc(SendTo.Server)]
private void Network_OnCardSelected_Rpc(CardType selectedCard, RpcParams rpcParams = default)
{
int playerCardDataIndex = Getter_NetworkPlayerCardDataIndex(rpcParams.Receive.SenderClientId);
Network_PlayerCardData playerCardData = Getter_NetworkPlayerCardData(rpcParams.Receive.SenderClientId);
int cardDataIndex = -1;
Network_CardData cardData = default;
foreach (var data in playerCardData.CardData)
{
if (data.Type == selectedCard)
{
cardDataIndex = cardDataIndex == -1 ? 0 : cardDataIndex;
cardData = data;
break;
}
cardDataIndex++;
}
if (cardDataIndex == -1)
{
DebugManager.Log($"Card Manager - Selected Card data not found: {selectedCard}", DebugManager.LogType.Error);
return;
}
cardData.Level++;
playerCardData.CardData[cardDataIndex] = cardData;
NetworkVariable_PlayersCardData.Value[playerCardDataIndex] = playerCardData;
NetworkVariable_ReadyClientIds.Add(rpcParams.Receive.SenderClientId);
}
I subscribe to the OnValueChanged event in OnNetworkSpawn and unsubscribe in OnNetworkDespawn
public override void OnNetworkSpawn()
{
NetworkVariable_PlayersCardData.OnValueChanged += NetworkVariable_PlayerCardData_OnValueChanged;
}
public override void OnNetworkDespawn()
{
NetworkVariable_PlayersCardData.OnValueChanged -= NetworkVariable_PlayerCardData_OnValueChanged;
}```
if you like you can use "cs" after the initial ` to allow syntax colors
this should trigger the on change
assuming this are in the same class
Yes, they are in the same class that inherits from NetworkBehaviour and has a NetworkObject
if this NetworkVariable_PlayersCardData.Value[playerCardDataIndex] = playerCardData; is called in between spawn and despawn it should trigger the NetworkVariable_PlayerCardData_OnValueChanged
sorry i dont know better x)
Thanks for the info. So, all network variables won't trigger the OnValueChanged event when they're in OnNetworkSpawn and OnNetworkDespawn? I did modify it in NetworkManager.OnConnectionEvent, but also in between spawn and despawn
None of them triggered the event
as long as its in between += and -= it should trigger, there is the possibility of timing issues if you call very close to the spawn methods it could be too early or too late
if you can, and if this could be a timing issue try check if "is spawned" before using Network_OnCardSelected_Rpc
When you confirmed with Debug.Log, did you confirm on other clients or just the host after it made a change?
I mean, it worked normally when changing the value.
The only thing that didn't work was the OnValueChanged event
Only with the host. I used Debug.Log to check all the values of that network variable, and it correctly displayed the changed value on the host. Wait for me a bit to check it on the client
Okay. Because that does not mean much. My guess would be that it is not syncing to other clients.
NetworkVariable_PlayersCardData.Value[playerCardDataIndex] = playerCardData; I don't think this triggers a sync, and therefore wouldn't trigger OnValueChanged.
With NetworkVariables I believe you have to set .Value directly, and that's it. You can't set .Value.Property on a NetworkVariable that's a struct and I'd assume it's the same for .Value[index] on a NetworkVariable that's a List.
You're totally right. The Network Variable didn't sync with the clients
In your case you'd have to create a copy of the List, make the change you want and then set the copied list with the change to .Value
heyyyy
i think this is the culprit:
OnListChanged
as @tame slate said if you want the OnValueChanged you would need a whole new list, but if you want a change on this list its OnListChanged i completely missed this detail 😇
I believe OnListChanged is for NetworkList
this isnt it? or cant be?
instead of NetworkVariable<List<data>>this seems a good use for NetworkList<data>, it has the on list changed and will propagate this change
NetworkVariable_PlayersCardData.Value[playerCardDataIndex] = playerCardData;
It still remains the same. The variable only changed on the host, and it didn't sync with the client
NetworkList can't have a List inside of it IIRC.
Do you think it has something to do with this? This is totally a ChatGPT code to serialize the list
public struct Network_PlayerCardData : INetworkSerializable, IEquatable<Network_PlayerCardData>
{
public ulong ClientId;
public List<Network_CardData> CardData;
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
serializer.SerializeValue(ref ClientId);
if (serializer.IsWriter)
{
int count = CardData.Count;
serializer.SerializeValue(ref count);
for (int i = 0; i < count; i++)
{
var card = CardData[i];
serializer.SerializeValue(ref card);
}
}
else
{
int count = 0;
serializer.SerializeValue(ref count);
CardData = new List<Network_CardData>(count);
for (int i = 0; i < count; i++)
{
Network_CardData card = default;
serializer.SerializeValue(ref card);
CardData.Add(card);
}
}
}
public bool Equals(Network_PlayerCardData other)
{
return CardData.SequenceEqual(other.CardData) && ClientId.Equals(other.ClientId);
}
}
but can have array
It's possible. Unfortunately I'm not really familliar with implementing INetworkSerializable
i dont really follow the code as i would need to be aware of the context but in the "else"
int count = 0; //with count hardcoded to 0 nothing was happening on the loop
serializer.SerializeValue(ref count);
CardData = new();
oh so but if its reading you serialize an empty list , thats probably why its not receiving anything, although i dont reallyunderstand this yet
can you explain why you separate the write from else?
I'm sorry, but I'm completely clueless too. It was written by ChatGPT, and I just copied and pasted it
🥲
just for the sake of it,
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
serializer.SerializeValue(ref ClientId);
int count = CardData.Count;
serializer.SerializeValue(ref count);
for (int i = 0; i < count; i++)
{
var card = CardData[i];
serializer.SerializeValue(ref card);
}
}
||it was a big mistake 😅 || but this wont change the OnValueChanged to be triggered by the list[i] = value for that you need to use NetworkList<data>.OnListChanged, or use variable.value = yourModifiedList to trigger OnValueChanged
I got a NullReferenceException: Object reference not set to an instance of an object at
int count = CardData.Count;
so probably thats why the separation exists
i dont know why its needed to serialize count since its not a variable on the class
and maybe do a null check before count , if its null return since you dont have cardData to serialize anyway
Now, it gives me a bunch of errors on both the host and the client
ok, now its already making sense to me 😅
if (serializer.IsWriter)
{
int count = CardData.Count;
serializer.SerializeValue(ref count);
for (int i = 0; i < count; i++)
{
var card = CardData[i];
serializer.SerializeValue(ref card);
}
}
else
{
int count = 0;
//the serializer will modify the count variable so it will not necessarily be 0
serializer.SerializeValue(ref count);
CardData = new List<Network_CardData>(count);
for (int i = 0; i < count; i++)
{
Network_CardData card = default;
serializer.SerializeValue(ref card);
CardData.Add(card);
}
}
i would focus on this ⬆️
can you try making a NetworkList<Network_PlayerCardData> ?
and use OnListChanged event
Also keep in mind that the initial onListChange will not fire in OnNetworkSpawn
If you are using NetworkVariable<List> then you need to call .CheckDirtyState() on it after making any changes to the List
Just saw it a few minutes ago, and it seems to be working, with the OnValueChanged event being called. I just need to fix some errors since the network variable is working normally
//NetworkBehaviour
public void AddPrefab(PrefabId prefab)
{
NetworkObject no;
switch (prefab.id)
{
//...
}
InstantiateNetworkObjectServerRpc(no.PrefabIdHash, OwnerClientId);
}
i am stuck here for a while but now i realized that OwnerClientId is the same on both players, why would this be?
I execute this method by clicking a button on the client UI, the prefab instances fine just on the wrong player (in this case always returns 0 so the host works fine as it is client id 0)
i think i had a similar issue when i started but i am not sure its the OwnerClientId or other client id in some other context, but i need the client id to assign ownership.
//on InstantiateNetworkObjectServerRpc
NetworkManager.Singleton.SpawnManager.InstantiateAndSpawn(
networkPrefab: networkObject,
ownerClientId: ownerClientId);```
Is this function on the player or on the button?
i thinks i solved it with
//passing player id instead of client id
ulong ownerClientId = NetworkGameManager.Instance.networkPlayersDataArray.First(x => x.playerId == playerId).clientId;
its on a class to manage spawning objects, neither the player or the button, the button just references the function
If its a scene object the owner will always be the host/server
ok.. that explains it.
i have a spawn component to help spawn prefabs , it has a method to set data such as tag and color, usually i would use something like:
networkObjectInstance.GetComponent<SpawnHelper>().Initialize(playerData.playerMaterial, playerData.teamTag, playerData.enemyTags);
on network objects this is not working, as the Instantiation happens on the server this does not work for other clients, is there a simple way to achieve this on netcode?
SpawnHelper is not NetworkBehaviour , do i need to make it as such and have the Initialize be ClientRpc for example?
On the other hand I wanted this object instantiation to first happen locally and once i fixed the position it would properly instantiate on the network, i figure this is somewhat a common feature, but the only way i think this is possible is to have a copy of the prefab for local use and then the network prefab to properly instance with the final position and values, or is there a better way to achieve this?
I have a networkObject with a network transform thats movement is controlled by the server, Interpolate is on. From clients perspective i can only seem to get the InterpolatedPosition within LateUpdate() Is it possible to pass this position through into Update Instead of lateUpdate?
The position in Update() is not interpolated
You would need to make those Network Variables (or a single player data struct) so they can properly sync. However material can not be serialized so you would need to have like a list of material to choose from and send the index for the player material you want
i can use color, i am already on it, thanks
when i converted i got the error bellow, but i already tried one of the solutions and i am not quite sure what to do next.
the error shows when i am instantiating the object on the server before i attempt to modify the values
[GenerateSerializationForType(typeof(string))]
public class SpawnHelper : NetworkBehaviour
{
NetworkVariable<string> teamTag = new();
}
ArgumentException: Serialization has not been generated for type System.String. This can be addressed by adding a [GenerateSerializationForGenericParameterAttribute] to your generic class that serializes this value (if you are using one), adding [GenerateSerializationForTypeAttribute(typeof(System.String)] to the class or method that is attempting to serialize it, or creating a field on a NetworkBehaviour of type NetworkVariable. If this error continues to appear after doing one of those things and this is a type you can change, then either implement INetworkSerializable or mark it as serializable by memcpy by adding INetworkSerializeByMemcpy to its interface list to enable automatic serialization generation
Debug.Log("Hit");
NetworkManager.Singleton.SpawnManager.InstantiateAndSpawn(networkObject, ownerClientId);
Debug.Log("Not Hit");
should be using one of the FixedStrings instead of strings
ill try that, thanks
in the screen shot i have 2 players, the pink and the blue(host) the blue data seems to be all in sync, particularly color and transform, but the pink is not.
the settings should be equal for both mainly authority for the owner, the transform is handled by the NetworkTransform component, i just set the transform.position and for the blue(host) is propagated but for the client its not, for the color at the moment i have this:
//this is where I set the color
protected void InitializeAsset()
{
//The value of `color` is correct for all players
ChangeColorServerRpc(color.Value);
}
[ServerRpc(RequireOwnership = false)]
public void ChangeColorServerRpc(Color newColor)
{
ChangeColorClientRpc(newColor);
}
[ClientRpc(RequireOwnership = false)]
public void ChangeColorClientRpc(Color newColor)
{
//Only changes from the host object are propagated
foreach (var r in renderers)
{
r.material.color = newColor;
}
}
basically the host gets the color from itself and the client, and the client only gets form the host, the client gets the transform from the host but the host doesnt get from the client
I would use network variables so late joiners can be in sync. Otherwise you need to sent the rpcs every time someone joins
Does anyone have an example of using a NetworkList<data> where that data contains another List<anotherData>? Since netcode doesn't allow a List inside a NetworkList, I use NetworkVariable<List<data>>. It works fine, but whenever something changes, the entire collection is synced again. I want to use NetworkList because it only sends the changed data over the OnListChanged event. I also tried using NetworkList<data> with NativeList<anotherData>, but it just gives me a bunch of additional errors
OnValueChanged gives you the previous version of the list as well as the current version of the list. You should be able to extract what was updated in the sync by comparing the two.
Should be fairly simple to accomplish using LINQ and the Equals function you had to implement with INetworkSerializable
I mean, if the collection is large, isn't it going to hurt the bandwidth or something like that?
No. NetworkVariable<List<T>> has delta compression since 1.9.1
Thanks. First time hearing about this delta compression thing
In this case the color is unique to the player, and the color is already a network variable, but it starts as gray and only gets the player color when the player positions the object.
If its not obvious i am still a bit confused with network logic, i started this bit without rpc but trying to fix issues ended up with this. I guess i can try again without rpc but at this point of the game there are no late joiners unless its a temporary disconnection.
The network variable would need owner write permissions if they are in the player. Then the player can control its own color
networkvariables can't be set to owner write, no? i thought you needed clientantricipated ones or whatever
will unity 2 get unitynetcode update or not? Right now latest release only available for unity 6.
I have writePerm to owner, but i will try this again when i have time thanks for you help
On initialization you can use new(writePerm: NetworkVariableWritePermission.Owner)
https://docs-multiplayer.unity3d.com/netcode/current/basics/networkvariable/#permissions
NetworkVariables are a way of synchronizing properties between servers and clients in a persistent manner, unlike RPCs and custom messages, which are one-off, point-in-time communications that aren't shared with any clients not connected at the time of sending. NetworkVariables are session-mode agnostic and can be used with either a client-serve...
we are talking about writing
Hello, I am going through the netcode tutorial here: https://docs-multiplayer.unity3d.com/netcode/current/tutorials/get-started-ngo/ but due to the use of static methods the scripts won't compile. Did I overlook something or is there an error in that tutorial?
Use this guide to learn how to create your first client-server Netcode for GameObjects project. It walks you through creating a simple Hello World project that implements the basic features of Netcode for GameObjects.
yeah that looks like a mistake in the tutorial, weird
Any way to disable this? Or am I doing something wrong?
Hello, unity noob over here, I experimented a bit with RPC calls and was wondering if photon fusion + photon voice would be a good solution for a solo project by a beginner ( I have C# xp, just 0 experience game developing ) [I Allowed myself to repost here since I didn't get an answer in #💻┃unity-talk ]
NGO2.x is Unity 6 only. But NGO 1.x is still getting updates for now
I imagine some issues eventually crop up when 2 Unity editors try to work on the same files at the same time.
Should I update my game to unity 6? Current NGO version is not really enough for me. It's a party game and sync is not well enough at all.
The network variable would need owner
anyone come across this error when setting up a dedicated server? I'm under the assumption that all I need to do to use Multiplay is to just initialize UnityServices. I'm not really sure why it's demanding an IP and I'm not sure where I would put said IP
the mildly fustrating part is not knowing what's causing the error. all it's telling me is that IServerEvents serverEvents = await MultiplayService.Instance.SubscribeToServerEventsAsync(multiplayEventCallbacks); is the error. Commenting it out and the error moves to StartServerQueryHandlerAsync()
Is there some multiplay config that I'm missing? I can't proceed forward at all lmao
Okay it appears that creating a "server.json" in the same place as this script seemed to do the trick. Still getting some errors about the ServerConfig being null but at least its progress
Hello everyone,
i am trying to update the session and set it to private so the players that try to join afterwards can't join and they create a new session of there own.
But for some reason it sets the session to be not private soon after it is private or a new player is trying to connect.
public async Task CreateSession()
{
if(activeSession != null)
{
activeSession = null;
}
var sessionOptions = new SessionOptions()
{
Name = sessionName,
MaxPlayers = maxPlayers,
}.WithDistributedAuthorityNetwork();
activeSession = await MultiplayerService.Instance.CreateOrJoinSessionAsync(sessionName, sessionOptions);
hostSession = activeSession as IHostSession;
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
HideSession();
}
}
public void HideSession()
{
if (hostSession == null) return;
hostSession.IsLocked = true;
hostSession.IsPrivate = true;
print("Lobby Privated & Locked!");
}```
Try using hostSession = activeSession.AsHost()
I need to setup multiplayer with dedicated servers and Matchmaking what the best way to go about it
what version is this? Things like IMultiplaySessionManager and UnityServices.Instance doesn't seem to be valid
I don't get what is supposed to be happening in their code. Isn't ServerConfig only assigned to when they actually get an allocation back with said allocation's details?
Keeps throwing me a nullreference at this line whenever I call their StartServerQueryHandlerAsync
nevermind I'm just stupid. It seems this is all I need to do before sending it to the actual server build in multiplay
I remember seeing a different error thrown for when the sdk detects if it's not on the actual servers so I was expecting that error this whole time before building it and sending it over.
The lesson learned here is to test it before complaining
i'm getting a nullref here... not sure why? i haveNetworkList of floats and it IS initialised, i can get values from the list just fine, but its adding that it hates. I have a static function that calls instance.AddTo_ServerRPC which is where this code here is. Nothing to dio with it is null and the lists length is correct, and also i have other networklists working perfectly fine. error attached
using Netcode for Gameobjects 2.20
is it null at a particular index?
no i debug.log'd the value at index its 0 like i set it to when i initialise it (i initalise with howveer many values of 0 when the round begins)
Hello, I'm trying to work on a multiplayer game, and I'm having a little trouble with RPCs. I'm trying to separate client side and server side into separate scripts, and theoretically separate scenes, how can I have the client send a request to the server, and vise versa. Do I have to have both scripts in the same scene for rpcs to work? I've been trying to do research, but haven't had too much luck finding examples that specifically include separating the client/server, in scripts as well as scenes.
nothing about how networking works is tied to things being in the same scene as eachother
anybody know why the server doesn't carry out RPC calls unless the server's viewport is on the objects?
1 player hits another but the server will only relay that information when the server's camera is looking at both of them. NetworkTransforms and everything else work fine
Then how do I access a RPC method that is only declared on the server side script, when the client can't see that script?
You might find some help by looking through this example project that does a lot of server / client script splitting afaik
https://docs-multiplayer.unity3d.com/netcode/current/learn/bossroom/bossroom/
Learn more about installing and running the Boss Room game sample.
If your new to networking at least in my experience you might not want to do the whole splitting though
I am new to it, and looking at the project, I think I was misunderstanding how RPCs worked a bit.. I thought basically the client would send a "event" to the server asking for RPC XYZ, through the existing connection established, and the server would just have a listener for "event" XYZ, through the RPC system, and react to the "event". Now I'm realizing the client needs to actually know what the RPC does, it can't just say "do X method, here's the data for it".
I'm also running off like.. 3 hours of sleep, that probably doesn't help
Here's a video about it
As long as the scenes are loaded additively, that should be fine. But I've found trying to separate clients and server to separate scripts is more trouble than it's worth.
You might want to look into Custom Messages if you don't want to fool with network objects.
https://docs-multiplayer.unity3d.com/netcode/current/advanced-topics/message-system/custom-messages/
A brief explanation of Custom Messages use in Netcode for GameObjects (Netcode) covering Named and Unnamed messages.
No clue why that's happening. A server build wouldn't even have a camera in it.
Do you have some kind of view culling happening on the server for some reason?
No I dont believe so
You can use RPCs as events if you want. But they have to be declared on both client and server
Is the server there a host? What happen if you disable the camera on the server?
nah not a host. It's a dedicated server on multiplay. The camera is also already disabled. Unless a disabled camera still culls stuff? I could try just deleting it
Oh that was the scene viewport. That shouldn't matter at all. How does it act when deployed to Multiplay?
as expected, network transforms get relayed. RPCs also get relayed. However, the melee you see in the video is triggered by a OnTriggerEnter on the server side and then gets relayed to the clients. That's the only thing to stop working so I also believe it's some kind of culling issue
But with nographics there is nothing to possibly cull. Unless you have some other asset that's doing it
Very little packages here. Haven't dabbled with culling in code either. I'm just as puzzled as you are
unless I was very unlucky and built the game on a faulty version. this is unity 2023.2.0b17
I can't think of anything else to do, nor can I find anybody else with this issue online
i shall raise the white flag for today.
is such line is okay connections = new NativeList<NetworkConnection>(1000000, Allocator.Persistent); for a 1 v1 board game if I want to create matchmaking based on players connected to the server, or there is way for dynamic initialization of connections count?