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.
Related
im making a multiplayer FPS game, and I have pretty much all the networking done and working. The issue is, that photon is syncing to players local movement, but if u have a bad connection, you could not tell it is happening cause player send late updates to the server and you can see other players lagging but you can move free and smoothly.
Im aware a lot of games work this way but i also know there are games like medal of honor that your player get stock in the last place every one else saw you. I need to know how to implement this on my game, because gameplay depends on it.
What you describe is "local prediction" of actions / movement.
If I understand this right, you want clients to not act or move if there wasn't a confirmation? If so, you'd need an authoritative host or server. You'd always wait for a confirmation from the host to move the player in any way.
But .. this is not going to work well. Players will feel the lag very much and this is annoying.
You probably want to predict the movement, then correct the local situation if the server disagrees.
I would recommend using Fusion instead of PUN for shooters. It can be run with host and has a nice API to reconcile the actual state from prediction to what the host simulated.
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.
I am trying to build a tower defense game using Unity and Photon. I generally find answers on the web but found nothing for this situation:
I have a spawn manager script that spawns enemies and increases a spawnIndex (only the master client does this). Since the master client is handling the spawnIndex, as soon as the master client leaves the game, another player takes over and starts spawnIndex back at 0.
I tried singleton implementation with no luck. I need a way for the master client to maintain a variable and, if they leave the game, have that variable taken over by a new master client, continuing where it was left off.
Thank you for choosing Photon!
The spawnIndex should be a custom room property and not a private field.
You can read about "Host Migration and Master Client" in general here.
It's also preferable to set the spawnIndex using "Compare-And-Set" (or "Check-And-Swap") only by passing the old value as expectedProperties parameter in PhotonNetwork.CurrentRoom.SetCustomPropreties.
I'm trying to develop a TCG(trading card game) in Unity(I'm Unity newbie) and currently stuck on the architecture of the project and the card effects in particular. Coming from web development background for me all the logic and card effects should be on the server but going through some tutorials for Unity I think the logic should be on the client and I should use a simple room-based server to notify for player actions. Is that correct?
To summarize - where the game logic should be(e.g. card effects, rounds etc)? On the client or on the server?
I actually worked on one of the major TCG's out now for iOS/droid, so this is coming from experience. You definitely want all game logic and rules to be on the server. Do not trust your client to be the source of truth for any game outcomes etc. People will be able to hack that by tampering with the data sent back to the server. They don't have to decompile the game to do that, it can be done merely by sniffing the net traffic.
That said, you may end up with some duplicated logic on both client and server, only so that you can enforce game rules and display the outcomes without always hitting the server. However, your server is always the source of truth and the client is just there to accept input and display outcomes.
The general flow was the client would send a message requesting a new game to the server. The server would respond with the cards for each side and the opening move for the first player. Then the client would simply parse each move and display the outcome. On the cards objects we had methods for many of the actions, such as DrainHealth() and BuffAttack(). When called, these methods would trigger things like particle effects and sound fx attached to the card script.
Yeah the effects should be on the client, I assume your game will be turn based right? You might want to take a look at photon then:
https://doc.photonengine.com/en-us/realtime/current/getting-started/realtime-intro
They have a loot of good tutorials about their API and it's well documented :)
Hope that helps you,
good luck
I coded a bomberman application that uses a gamekit peer to peer connection. The problem is that after a while the game isn't in sync anymore.
I looked at the sample code for GKTanks and used their model. There is no client/server relation between peers so I didn't use one in my game. Both peers maintain a gamestate which they update based on received data.
I have a NSTimer that's used for running the gameloop at each frame. The NSTimers aren't in sync so sometimes the gamestates become different ex: players pick up a powerup at approximately the same time and they both get the powerup because it takes a while to send data.
I would appreciate any idea on making the app work. I'm thinking of rewriting the code to use client-server but I'm not sure if it's a good idea... yet
Thank you!
EDIT: I changed the code such that a random player is picked to be the host.
Every time a player places a bomb he asks the server where to place it. The server returns the players position(as seen on the server) and then tells the player where to place the bomb.
For powerups the server checks if a player picked up a powerup and if he did it sends a packet informing him.
Another problem has appeared now. The latency between devices is high(I'm using a bluetooth connection). It takes around 0.2 seconds to place a bomb after the client tapped the button to place it.
I'm sending all data reliably. Am I doing this right?
Well preferbly you want a host-client relationship where only the host can manipulate the game state, so in your case it would be:
Both players rush to the powerup.
Host picks it up first.
It gets registered and the host recieves the power-up.
Meanwhile player#2 also picks up the power-up, sends the action to the host.
The host informs player#2 that the power-up is already disappeared.
The thing with your situation you are bound to get desynchs from packet loss.
With host-client relationship that cannot happen, the only problem is the host always has an advantage that becomes greater when the latency increases between devices especially on smartphones.
In a game like bomberman it's perfectly plausible to send the entire gamestate each time something changes instead of the action that was performed, this is to ensure both devices are in sync.
To sum it up: both users have their gamestate but only the host can manipulate both.
what you should do:
one of the devices is host, another one is client
host process all the game states and makes decisions, then it sends whole gamestate to the client
client gets the gamestate and just draws everything based on it - it doesnt make any decisions (who picked bomb, did bomb exploded etc)
client just sends input to the host (pressed left,right, pause etc)
that's it. if you try to make decisions on both machines, you will run into big troubles trying to keep them in sync.