Multiple or single NetworkManager in Unity - unity3d

ok so I'm trying to get multiple matches going in an online multiplayer unity game and I need to know:
Is it better performance to manage all connections from a single NetworkManager or break up user connections into multiple ones? I ask with respect to performance. So will this be more costly for my server or the reverse?
danke sehr

ok so i thought about it a little more and since you can only have one active NetworkManager per scene (according to documentation ) I suppose I can't have multiple ones to break up connections as I was thinking.
My idea now is to use matchIds using Mirror but I'm stilling running into an issue. Collisions can still occur between GameObjects even though they have different matchIds.

Related

How to make a networked enemy in unity and mirror

I'm making a multiplayer game and for kind of all of it I need to have enemies and AI characters.
-for example 5-10 players in a match fighting a monster together. and the monster needs to be synced for all clients.
-or when there are not enough players online the server would add AI bots to the match so the player wouldn't get board.
I tried to make the AI and spawn it and give its authority to one of the players so the AI calculation doesn't cost the server.
Even though I couldn't have the server-side AI because Match Interest Management and that wasn't possible by that.
The problem starts when for example 2 players join a 4-player match and server adds 2 more bots everything works fine until when the match starts the first player which controls the AIs is fine but the other player gets freeze. I look for any infinite loops in my codes but I didn't find anything. I tried delaying spawns but still nothing.
The freezing happens when I use the dedicated server. in the editor and local network there is a very low chance it would happen.
if anyone knows Mirror Please help me if you think you can.
Thank You. Sorry if I didn't explained well.

Trying to understand Unreal Engine 4 replication

I'm trying to understand how to call events between client and server. My goal for now is simple. I want to create anything that is interactable for 2 players.
Easiest thing I could think of was cube that is switching color when clicked. So I did create actor based blueprint, checked "Replicates" and AlwaysRelevant to be sure. PlayerController is also replicated and there is no pawn needed.
Color change blueprint:
SM is just static mesh if that is important. As far as I know client have no authority to call multicast events so I wanted to push it through server but it stops there. Called from server works as expected and color itself IS replicated to client, however client cannot change color himself.
What am I missing in this concept? I've watched like 5 videos about replication and I started to think there is something missing which is either obvious for everyone but me or their examples do not need things I do here.
As you've found out, a player's client can not directly call server RPCs on actors which the player does not own. Calls must be routed through that player's PlayerController. The server copy of the player's PlayerController can then call server methods on server-owned actors.
Another issue is that you seem to be using both RPCs and replicated properties for the same purpose. Unclear to me why changed is replicated since you're modifying it in a multicast event which normally runs on all the machines. This is a recipe for hard to find race condition bugs.
Replication in Unreal is definitely one of the harder concepts to get the hang of. The resource that helped me the most is this guide which while quite dated, is both comprehensive and to the point.
You can't have it in PlayerController, it's got to be in a Pawn, or if not, in PlayerState, or it won't get shared to other clients.

PUN2: is this recommended for a rigidbody sync state and collision?

I have managed to sync my ridigbodies real good but I just noticed that when a client (that's not the master) collides with one it doesn't move, it's locked, while reading on the net I had an idea when the object collides with a rigidbody I just transfer the ownership of that object to that client for the moment for this client to process the collision (I have tested this and it works really good, both clients sync perfectly)
is this recommended? performance-wise and security/cheating wise?
Thanks!
Short answer:
Transferring ownership of a GameObject to a client, when that client needs to control and update the object data, is fine. In cases of detecting cheating possibilities, always have one client (typically the master client or a dedicated server) validate, correct and sync the data to all clients.
I will not make any assumptions. Based on your explanation of the issue, it seems your GameObject Rigidbody IsKinematic was not being synced, causing the collisions having different effects at each client end. But in case that might not be the issue, I have a longer answer hoping it might help for this or other scenarios.
Longer version:
Sync Rigidibody data over the network where it is fundamentally required to be present on the client GameObject. The rest of the Rigidbody data can be created / calculated / simulated on each client individually:
This way, you will make sure all parameters of that Rigidbody are correct (e.g. isKinematic is correctly enabled/disabled on all clients)
Your games will always have the minimum required data to create/simulate the rest of the events and effects properly, reducing network lags and improving performance.
Where data validation is required, the master client will always validate the non-master client data, makes the crucial adjustments and decisions and updates the room data for all clients where necessary. This reduces the chances of players cheating.
Developers will find bugs easier when the events that are supposed to take place on each client, do not align with what is expected. This shows itself more often in scenarios where several events should take place at the same time and on each client.
Much longer version:
When I use PUN2 on GameObjects in my games, I only sync Rigidbody where those GameObjects require Rigidbody values to be present on the clients during collisions to perform specific tasks (e.g. using the velocity or direction for dynamic sound/visual effects), or when the master is validating and correcting the data needed for the non-master clients (as a result of network delay or cheat/hack tampering the data on client side).
When using PUN2 (up to this date), I update its class internal code to my needs. For example, PhotonRigidbodyView does not sync the kinematic state of a Rigidbody yet. When I need this in my games, I could override the class with my CustomPhotonRigidbodyView class (and/or updating the PhotonRigidbodyView a bit).
Does it effect the performance when using PhotonRigidbodyView? Yes, when not used with care, it does decrease it when there are too many objects syncing over the network at the same time. The clients will see jagged movements.
Does it allow cheaters to take advantage of this data, manipulate it and send it over to the clients? Yes, if the game is vulnerable to basic cheats. Then again, the topic of security/cheat detection is quite vast, so for each game definition of "basic" cheats are different.
Is it a good idea to transfer ownership momentarily to be processed on client side? Yes in some cases, other cases no:
If doing this momentary transfer is the only place you do this and it solves all your problems (except cheating), then use it so you won't spend too much time fixing this one part in a different way.
If the Rigidbody or Transform data is being validated and/or synced, either constantly or in periodic intervals by one client (to prevent cheating or to sync client data properly at crucial times), then it is fine to transfer momentarily too.
I typically transfer ownership, when the object data must be changed by the client (e.g. grabbing / dragging around / shooting / throwing) and once the action is performed, ownership will be back to the master to be validated and synced for all clients (including the one that just transferred the ownership). This results in more time spent on testing, catching unwanted (possibly unseen) bugs, and reduced cheating possibilities.
In case a developer working on your game has not properly optimized the Collider and/or Rigidbody components for each GameObject yet, please make sure you have done so before syncing their data over the network. This page in Unity doc may be a good reference to check whether your GameObjects need to be static colliders or dynamic colliders:
https://docs.unity3d.com/Manual/class-Rigidbody.html
https://docs.unity3d.com/Manual/CollidersOverview.html
Once the GameObjects that need a Rigidbody component are identified, then you can decide which ones need to be fully synced over the network or partially synced and/or their ownership transferred when required.
I hope my answer does not confuse any of the readers. If there is anything not clear, please mention in the comment and I will improve my answer for you.
Update: 2019-05-10 (reply to the 2nd comment):
For a pool game involving so many GameObjects, I would not transfer the ownership of all objects to a client. I would:
Create a struct holding the necessary information such as:
ball_id: indicating which ball is being hit by the pool stick
hit_info: a Vector3 representing the position (on the ball surface) and direction of the hit applied to the ball, by the hit stick.
hit_force: the required force to apply to the Rigidbody of the ball that is being hit by the hit stick.
and any other information that I might need, when the player hits the ball with stick.
I can then combine this information and pass them to the AddForceAtPosition method of the Rigidbody of the ball.
Dispatch this struct in the room, for all the clients to receive.
Once each client receives this message, including the sender, (in OnEvent as EventData containing the Phton Event Data), it will apply this info to the correct ball and will create its own version of physics (small differences will be noticed between each client).
This way:
I have the minimum amount of information passed over the network to make the simulations happen on all clients
Improved performance of the game by avoiding parsing and applying unnecessary Rigidbody data
Reduced the cheating possibilities of a client moving any of the other balls that they are not supposed to, around the table or into the pots.
To increase security as well as making sure the balls on all clients are exactly where they are supposed to be, another struct will be dispatched for example by the master client, indicating the exact position (and rotation) of each ball on the pool table (or in the pot).
I would sync the ball positions periodically (either at pre-defined intervals or at specific moments of my choosing depending on the game state) to all clients to overcome any incorrect positions at any moment in the game. This periodic sync can be done by the master client or a dedicated server.

Giving enemies Health/Multiple hits

I am trying to make a game with multiple types of zombies that take multiple hits to kill. For example, I have a runner zombie sprite node that has 2 health. When it is hit once it speeds up and when it is hit again it dies. I have been trying to get my enemies to be multiple hits and I never figured it out. Do I make a class with various properties such as a health variable or do I make a function? Identify all of the enemies and their health? Help Please!
Obviously, there are many ways of doing this, but if you are using GameplayKit's Entities and Components, then it would be logical to store this kind of data in a health component.
In general, if your game is getting complex, have a look at GameplayKit's guidelines and likely you will find all the answers.

Unity UNET How to change online scene in sync with clients

I'm using the old Unity 2017.3 UNET implementation in my game. Players connect to a server and are placed in a Lobby scene until the party leader selects another level to go to. The implementation is just a slightly modified version of the default NetworkLobbyManager.
The trouble started now that I've begun heavily testing the networking code by running a compiled build for a client and then using the editor as the server. Very frequently, the server running in the editor will run a great deal slower than the compiled client build. So when I use NetworkManager.ServerChangeScene the client will load the scene before the server, which will cause all NetworkIdentities on the client scene to be disabled (because they haven't been created on the server yet.)
It's a lot less likely to happen if the server is running a compiled build, because the server will almost always load the scene before any clients. But it does surface a bigger issue with Unity itself. That there's no guarantee that the server will be available when changing scenes.
Is there some other way of changing scenes in a networked game? Is there a way to guarantee that the server enters the scene before any clients? Or am I stuck just kind of hoping that the network remains stable between scene changes?
Well I thought about it more overnight and decided to look in other directions, because more investigation revealed that sometimes the Network Identities are still disabled when the server loads the scene first as well.
I was looking through the UNET source code and realized that the server should be accounting for situations where it loads the scene after the clients, although that code looks a little jank to me. This theory was backed up by the documentation I found that also says NetworkIdentities in the Scene on startup are treated as if they are spawned dynamically when the server starts.
Knowing those things now, I'm starting to think that I'm just dumb and messed some stuff up on my end. The object that was being disabled is a manager that enables and disables other NetworkIdentity objects. I'm pretty sure the main problem is that it's disabling a network identity on the client, that is still enabled on the server, which is causing the whole thing to go haywire.
In the future, I'm just going to try and stay away from enabling and disabling game objects on a networked basis and stick to putting relevant functionality behind a flag of my own so that I can "soft disable" an object without bugging out any incoming RPCs or SyncVar data.