Like that: 1EJXTh4HMAE It's a classic clip that was actually shared in LAN parties quite often. I think I still have it somewhere on a HDD. Yes, the time before RUclips was a thing
@@tomweiland i was following a tutorial and it had 35 errors here is the tutorial i followed: ruclips.net/video/oyvt7RacVoo/видео.html here is the code: using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerMovement : MonoBehaviour { public bool CanMove = true; public CharacterController PlayerController; [Header("Camera")] [SerializeField] private Camera playerCamera; public float MouseSensivity = 5f; public float XRotation = 0f; [Header("Walking Params")] public float WalkSpeed = 4f;
Yeah for sure. So much work goes into the (mostly) seamless multiplayer experiences we all play nowadays, and I think most people take it for granted how ingenious the systems that make it possible really are. Working with multiplayer stuff for the last ~4 years has really changed how I view games :P
Haha I'm glad you like it! Despite what this video seems to suggest, I do think that anyone that's interested enough can certainly learn at least the basics of networking :)
This is very relatable. Great video. Whenever I tell people about how annoying it is, I don't feel like they comprehend the full extent of it. Even this video didnt fully give it justice. It's feels like you are slowly driven mad by some eldritch god. Stuff stops making sense but it kinda does, sometimes... You start to understand why online games seem so limited sometimes. Make sure to take care of your mental health. Take breaks and do other stuff that gives you joy and purpose in life.
For sure. This stuff can really bend your brain around... And yeah, mental health is something to be aware of when dealing with this madness. Although honestly 90% of the last 3 months that I "spent working" on this were actually spent either enjoying the summer or procrastinating tackling this problem 😅
3 года назад+4
It's like quantum physics. But with better excuses.
Latency is worse than you think. Your processor has the speed of a 486 if you disable its caches. It is essentially playing a multiplayer game with itself since RAM is so hideously slow and instructions are pipelined over multiple clocks. Memory has kept up on bandwidth by taking many memory cells that operate slowly and multiplexing their output into something with a high clock frequency; but latency is scarcely better than 1998 because the individual cells are still slow. Even if latency of RAM was 1 clock instead of hundreds of clocks your CPU is pipelined; this means every instruction is chopped up into many stages and microops which can execute in parallel or out of order. Multiple instructions that use the same resources can be in flight at once as long as they are in different stages or in a different execution unit. To get around the latency problem the CPU is executing instructions out of order; as long as they don't depend on a prior result; and for every branch (think while-loop, if statement or for-loop) it is predicting if that branch will be taken or not and executing instructions on that basis. If ever it is wrong it needs to undo hundreds of instructions and their effects on several levels of cache as well as RAM which all have different latencies. And it gets worse; for legacy reasons the CPU has few registers and it is getting around this by renaming registers on the fly and having more physical registers than it has software addressable registers. So if you put the result of a calculation in EAX and store its value to RAM, then write something else to EAX and use that to do another computation; your CPU is aliasing EAX to different physical registers and trying to execute those things in parallel. Now there are also multiple cores which are using the same cache (L3 and RAM) in parallel and there are multiple levels of cache that have to be kept synchronized and the bigger they are, the slower they are. And this is hardware; so this either works perfectly on the first try when you release it to the consumer or you are down billions of dollars if you release a defective product that has to be recalled. High performance processors are pure nightmare fuel.
Oh Jesus, my notifications reminded me of this cringe comment I made 2 years ago. I learned a ton since then. It can definitely help if keep things simple and rely on existing systems and tools to sync stuff. But even with a lot more experience, my comment still holds truth. Always remember to code defensively! Also log errors and important events.
Switching from a physics based system to a simple parenting system when stepping onto the ship is actually genius. I had a stupid grin on my phase when i saw that part in the video cause i was also like "wait, how does one fix this actually?". And then my brain was like: "ah of course, why did i not think of that!" :D
It's an okay solution, but it has its issues. The jitter when getting on and off the boat being one, but I also foresee it complicating things when I get around to dealing with lag compensation. I'm strongly considering just predicting the ship's movement as well-that'd avoid the problem in it's entirety and is probably a simpler, easier to maintain solution 🤔
@@tomweiland Why not incorporate some allowed error margin for the client calculation on the server and be like "ah yes this sounds within the realm of possibilities, hereby I declare you not a cheater and I accept this update"
@@lock6562 Most likely, but as long as you give them a sort of "Vector3D positional_errors_accrued" variable that slowly returned to (0,0,0), you could see if someone gets too many errors in quick succession is probably cheating. With that, people would only be able to hack in a very small advantage at best since the rate of their advantage is limited to not accede the resetting speed of the positional_errors_accrued or it's max value.
I tried making a multiplayer fps and gave up because of these things. It's really hard to conceptualize what this sort of entails until after it starts bending you over.
> Spend forever making functioning multiplayer game/modes. > Half the playerbase only plays singleplayer. Social anxiety, the hardest challenge of all.
0:16 Yeah its such a good feeling when you rewrite all of that code but in a different way beause you thought your other way is stupid and didn't work BUT! then you see that you didn't type () or added an extra space Great video btw Hope we can see more videos soon. Love the progress so far Good luck!
Yeah it's always nice when issues are quick one word fix...except when you spent 3 days trying to _find_ the issue in the first place :P Glad you enjoyed the video-I'd definitely prefer not to go another 3 months before the next one, so hopefully soon!
@@tomweiland The boats sound like they make it significantly harder. I believe sea of thieves switches players to local coordinates for the ship. Do you think that is similar to your duplicate ship approach?
Hey, I ran into similar issues while developing pantropy. We had the player move on ground and flying/moving bases here are my tips: 1. DO NOT use a rigidbody to move your player. Physics movements are never equal on server and client. Use a CharacterController instead. The characterController.move function is always accurate and the player will move an equal distance on server and client. 2. Don't use the characterController for ground collisions. Use a raycast and keep the player a given distance away from the ground. Move the player downwards if the ray doesn't hit anything. 3. Set the player's transform as a child of a moving object (like your boats) on server and client when he enters it. You will not have any weird physics glitches thanks to the "groundray". Hope these helped, this wroked for me flawlessly.
1. The problems I've been dealing with aren't related to a lack of physics determinism. You can actually make Unity's physics deterministic on the same machine by enabling the "enhanced determinism" option in the physics setting, and I've really only been developing & testing with both client and server on my computer. I also want to be able to easily apply forces to players, and I don't like how the CharacterController is basically a black box-no idea of/control over what goes on under the hood. 2. Again, not really a fan of CharacterController in general. 3. Making the player a child of the boat would give largely the same result that I ended up with at the end of this video. When getting on and off boats it would still jitter, and I kind of prefer my solution because I really didn't want the player to be a child of the boat. Thanks for taking the time to make suggestions though :)
I did actually come back for this advice, and I did use it. In standard cases, this would be a perfectly fine solution. Unfortunately, my case turned out not to be standard.. of course.
As a RUclips commenter with absolutely zero game coding experience, this seems fairly good 👍, thank me later and yes I know my opinion is highly sought after
Try using a downward SphereCast and/or CapsuleCast over a single Raycast. While that solution seems to work for you, there are many scenarios where it can break. A great example are slopes. Granted, if you use the CharacterController component, slopes are automatic. But if you make your own kinematic character controller, you need to detect slopes on your own. Using something like CapsuleCast provides fantastic results. But I'm not gonna lie, creating a kinematic controller is probably the hardest thing I've ever done is game dev. It still doesn't even work tbh. There is SO much math involved. At least I learned a ton lol.
*Check out the next devlog:* ruclips.net/video/cYLnVp1ngwA/видео.html So yeah...this is where I've been for the last 3 months (although I did also enjoy the summer a bit). Thanks for watching :D If you're interested in learning more about client prediction/reconciliation, check this out: www.gabrielgambetta.com/client-side-prediction-server-reconciliation.html
Wow bro. Just wow. You've ran into your first major learning curve I'd say. Prior to this you've done splendidly and really.broufht something great to the table. Now though. Your gonna have to learn how the big guns do it i suppose. Why not contact aome AAA companies and ask about it through their human resources. The Internet is obviously failing to provide decent documentation for you. So ask how the big guys do it. Might be a few neat tricks they use thar you can implement. Just a thought bro. I'm not even gonna attempt networking until next years project. Was thinking about starting with your tutorials
@@BadBanana definitely not the first learning curve 😅 There's also plenty of resources out there on how prediction/reconciliation should work, but virtually nothing about how to ensure it works while standing on moving objects like ships. The only other game that comes to mind which would have had to deal with this is Sea of Thieves, but I'm about 95% sure they solved it the same way I did (with a "proxy" for the boat).
I personally use Unity and like it a lot, but I haven't used Unreal Engine so I'm probably at least a little bit biased. I think the most important difference is the programming languages they use-Unity uses C# which I _love,_ while Unreal uses C++ which is apparently one of the hardest programming languages to learn. You can use blueprints in Unreal instead of C++ which is like visual scripting, but I've never really been a fan of that. Both engines can be used to do a lot of the same things, but I'll probably always recommend Unity because it uses C#.
@@juju8470 I've worked in Unity and Unreal and as Tom says coding in C# is really nice and C++ usually is a slower and more tedious process and yes its difficult to get into. Unreal has a lot of build in systems similar to unitys monobehaviour but its so massive and that can be really hard to get into, so lots of trail and error early on. Blueprints is actually also pretty enjoyable to work with until you have to make massive system for your game, it can get rough to keep track of the code. Unreal also offers a lot of shortcuts and more dedicated support for artists, and level designers to get going. Unreal also has a more integrated multiplayer systems, haven't touched it myself but compared to unity its very much an engine feature. Imo I've had less issues working in unreal on a engine error level, and the experience has been smoother working in unreal but Im still much more comfortable with unity.
@@tomweiland Be aware of using Unity networking library to develop multiplayer games, they change the API every several years mainly because not many people use it. I think it's totally not necessary, they just have to improve the API not abandon it! Unreal use the stratege and it works just fine.
Fancy to see you here, I asked you about how you networked redmatch 2 in steam comments a while ago. Been a rough learning for me but fun nonetheless. Seeing this video just adds a layer of terror to the ordeal but it will be done...
Godspeed my friend, that's why I'm sticking to single player for the foreseeable future! Also the music that kicks in at 0:30 made me think That Chapter and I was worried someone was going to end up dead by the end of the video
These problems are why I probably wouldn't recommend a multiplayer game for a first project (unless it's local multiplayer). It's a real headache to figure out the proper way for networking in games, and when you're also doing everything else for the first time, it becomes a whole lot to handle.
This is a great video. Very good and clean explanation of an otherwise very complex topic. A few things from my several years experience: - there's no need to "compare" for misprediction... just overwrite with server data and resimulate forward (maybe this is what you do already) with the local input buffer... - for moving boats, and all moving platforms in that sense, it gets trickier because you could place the boat in predicted timing as well (if you also predict/rollback physics, which you can do), but this would create a problem for proxies (view of other players) as they are generally on interpolated time. One thing that may work for proxies is to predict just their gravity and move-with-platform part... But in either case or solution you will loose one thing, which is the capability of doing accurate lag compensation... but that is another story...:)
Thanks for watching :) You're right about not needing to compare positions-I don't actually do that in my code, but since I didn't want to get into the whole rewinding-and-resimulating part I figured that'd be the easiest way to explain what happens from there in a single sentence. I definitely thought about predicting the boat movement as well, but that would've then meant also predicting the waves, and it sets the precedent of having to predict anything that moves which the player might end up standing on. Then again I suppose I've set a similar precedent in the sense that if I want to avoid jittering on other moving objects, they're going to need "proxies" as well...
"You realize that you didn't read the documentation properly". Oh, if only! I can't even begin to count the hours I've wasted on following incorrect documentation.
Glad you enjoyed it! I can at least see the light at the end of the tunnel now, so maybe take it as inspirational with strong warnings about what you're getting yourself into? :P
You are doing great work man. The fact that you have gotten this far this quickly already puts you light years a head of others in the industry. To top it all off you are teaching yourself all this. That puts you even farther. I can't wait to see any tutorials that you (hopefully) put out for the new netcode.
It's interesting to hear your experiences with implementing multiplayer. I'm writing a multiplayer game myself in Unity but it's simultaneous turns on a grid-based map so I'm not feeling the pain of realtime play, I'm sure I'll discover my own pains as I progress though. Anyway, I always liked this quote from Michael Abrash's Black Book on reducing player latency in Quake - Reduced latency also often makes for more frustrating play. It’s actually not hard to reduce the latency perceived by the player, but many of the approaches that reduce latency introduce the potential for paradoxes that can be quite distracting and annoying. For example, a player may see a rocket go by, and think they’ve dodged it, only to find themselves exploding a second later as the difference of opinion between his simulation and the other simulation is resolved to his detriment.
Yeah, hiding latency introduces a whole other set of problems to deal with...can't wait! It's very wise of you to work on a game that doesn't require realtime play 😂
@@tomweiland Yeah, well actually no, I should have edited that. It is realtime but not realtime realtime. As in the players move in realtime simultaneously during their turn but they're restricted to a grid so I don't have to worry about little annoyances like physics and collisions. I've probably got it easy compared to you but there's still plenty to think about. It is at the same time both a 'fun' challenge and an interesting learning experience.
I am soo happy I kept it ad 2d without physics and to something where single milliseconds don't matter that much. I really am feeling with you though, network-code is the worst to debug. Especially if you went insane like me and introduced multi-threading in the process, please just end my eternal suffering.
Yo, you finally got into the same problems I have been working on for the past 3 months. I was almost getting angry seeing you not having to deal with any of those. 😂
@@tomweiland Jittering is not a bug, it's a feature. It defines the status of chaos of the world making the player feel the uncertainty and instability of life. Latency also is important, it teaches the player to wait and have patience or to take initiative and get a better connection.
Sorry for enjoying watching your struggles on RUclips :D Keep trying, it will eventually succeed (if it doesn't drive you mad). Remembers me when my friend and I had had to use an obscure front framework and the correct data wasn't showing, it took us 3 weeks of heavy sweating and nightmares to discover it was expecting some weird null instentiatiation with no data to work...
This was a really good video Tom. Great video editing as well. You can see the effort you put in. Good luck with the continued efforts and we all look forward to more updates in the future!
Hey Tom! Has been a while since I dropped in to watch a video by yours. It changed, in a good way. You made me chuckle and it was informative. Keep up the work, mate!
I think if/when I eventually finish this game, I will build a singleplayer game next. Or at least a multiplayer game that doesn't require hiding latency to ensure a good gameplay experience. Maybe a top down RTS or something 😂
As a person who's just jumped into the ship of game development, I've decided that I want to make a multiplayer game at some point. So, I will absorb all of the videos that you have with issues and explanations/solutions to these issues. I've subscribed waiting for for the next video lol
I mean that's nice I guess...but totally useless in my case. A generic prediction solution would have the exact same issues on boats that I'm having, so I would end up needing to heavily modify it (at which point it'd probably just be easier to write my own). I'm also using Unity and don't plan on switching-I like C# and don't feel like learning C++ right now, and blueprints are quite unappealing to me. It's also worth noting that Unreal's netcode out of the box is really only good for small arena shooters with less than like 20 players (my game is not one of those). Epic themselves had to make modifications to get Fortnite to be able to handle 100 players on the same map.
@@tomweiland Yeah that's true, the MMORPG Ashes of Creation is being made on UE4 and they had to make their own proprietary networking to make UE4 capable of supporting a massive concentration of people (the Massive on MMO :P)
@@Hunsenbargen I would think this is mostly about reducing fidelity. Players that are far away don't need 60 updates per second or even 30. Even 1 update per second will go very far as long as they are running in a somewhat straight line or turning smoothly. You therefor only need to send frequent updates if they are doing something unexpected. As the number of players increases the naive solution is an O(N^2) problem.
I was going to say. A lot of these issues (not all) are solved in UE out of the box. I actually found it very easy to set up a multiplayer replicated movement model.
3:34 - You must have never been playing GTA5, and been riding in a car with someone as they smash into a wall, only to find that it was your client mis-calculating, then have the car magically appear back on the road, once the server updates the real position.
"Take 2 days to fix the error" Me trying to upload my game to google play from past 2 days 1. Keystore 2.some random arc64 3.150mb limit 4. api time taken 1- week
This is actually a great explanation why standing on a vehicle in any multiplayer game like Battlefield series was always normally fine, but when it was moving, things would go spasmatic and probably end in phasing through the vehicle or dying for no reason.
Makes sense-as long as it's not moving, you don't experience the effects of objects from different "time streams" interacting. Once it moves though, 💩 hits the fan :P
I did laugh with you at a couple of points. Streaming gaming services can't come fast enough. Your description is excellent, I think it was wise too stop before you got into estimating latency and forward calculating at the server. "Time streams" was a great phrase. Still enjoying your vids, sorry it's being such a pain.
Glad my humor hasn't been stripped of me along with my sanity 😂 I'll figure it out eventually, I have the bulk of the pain out of the way now, so I at least see the light at the end of the tunnel :) I'm hoping I explained things well enough with enough visual aids to keep people interested even if they're not familiar with programming and multiplayer.
5:09 Little tip for recording long texts where you run out of breath: take little stops inbetween to breathe and cut it out in editing so you have a more chill recording experience :)
Sounds like fun :D Sorry you went through these issues but this was very informative! It starting to sound like the Marvel Multiverse with all the client and server prediction stuff haha. Glad you got a lot of the latency/jitters fixed, at least with a single player in!
You probably want to keep your control over the server, but if you ever decided to switch to Photon, it has an option for extrapolation to enable Photon's server to predict where a player's transform may be in its Photon Transform View Classic documentation. I'm unsure of how well this will work for your game, but in case you weren't aware of this option, thy has presented it.
I had the same problem when I created my first multiplayer game too, but I found out that letting the player move only after getting the move message from the server worked better than trying to predict the player’s future position on both the server and the client at the same time. The process was: player presses W -> sends it to server -> server check if the move is valid and instantly sends back command to tell client to move the character. The latency can be forgiven because most of the time it happens in less than one frame. That way, I can focus on reducing the message size instead of trying to correct the player position, which is a dead end.
Waiting for a response from the server before moving quickly leads to an experience that is sufficiently unresponsive for it to feel awful. A 50ms round-trip time is plenty for the delay to be noticeable, and I'd argue that it's unreasonable to expect most players to have less than that, especially when you factor in the added delay from your tick rate (lower tick rates mean bigger gaps between ticks, which effectively increases the time it takes for the server to respond) and from slightly buffering positions so you can interpolate them and have the movement look smooth. Players with powerful rigs and high refresh rate monitors will also be more likely to notice delays than players whose monitors max out at 60hz. _"The latency can be forgiven because most of the time it happens in less than one frame."_ This is just not true in my experience, unless you're testing with the server and client on the same network. At 60hz you have a frame time of ~16ms, and the vast majority of your players will almost certainly not have a round trip time that's less than that. Someone with a 144hz monitor will have a frame time of just ~7ms, so even if they somehow had a mere 25ms round trip time on their connection, at least 4 frames would pass before they see the result of a key press.
I think player movement can be handled locally, but if the player moves beyond the sphere of allowable mismatch and for too often, it can be verified more and more by the server. I used something like a "suspicion" tracking variable, where someone speed hacking or teleporting quickly finds their movement entirely server-authenticated. So it trusts the client initially, but the trust can be lost for a time. Multiplayer coding is absolute hell, just getting a game to finally accept connections was a whole endeavor...
The problem is that checking speed or distance traveled doesn't account for things like collisions, and those metrics really say very little about whether the movement is "acceptable". A system like that wouldn't catch someone who's walking through a wall, or someone who slows their gravity down so they fall slowly, and making the system capable of detecting those things essentially requires simulating all of the movement logic on the server. At that point, it's arguably easier and less work to just give the server full authority, and by doing so you'll also avoid dooming yourself to playing the cat & mouse game of hackers finding ways to exploit/evade your detection systems and you having to react. At the end of the day it just comes down to what tradeoffs you want to make-I prefer giving cheaters as little chance as possible to gain an advantage :P
Before you got to the part where you wanted to get back to the practical side of things 4:13, I immediately thought "why not use a decimal data type and clamp the position to the nearest median? The difference is negligible." Also, to fix your new problem, it starts off with how you tackle the problem. First off, depending on your set up, the water becomes the parent and the objects such as ships and the terrain to walk on become the children of the sea. When the boat sails out to the sea and hits a certain local distance in the water, the land itself moves away from the boat and the water instead; This has the server calculate the position of the static land (and local position of the player), not the boat.
_"I immediately thought 'why not use a decimal data type and clamp the position to the nearest median? The difference is negligible.'"_ What exactly would this accomplish/solve? _"When the boat sails out to the sea and hits a certain local distance in the water, the land itself moves away from the boat and the water instead; This has the server calculate the position of the static land (and local position of the player), not the boat."_ Are you suggesting that I make the boat stationary and move the land and water around it in order to make it _look_ like the boat is the one moving? That sounds _at least_ as complicated as the solution I ended up with, and it has many more problems. What should happen if one player is standing on a boat and another is on land? What should happen if there are 2 boats? Which one should everything move in relation to?
Best choice I made when creating my multiplayer game was switching over to Unreal. I've used Unity for years, learning all the ins and outs, but it lacks the tools for multiplayer development. Unreal has a ton of great features for multiplayer like profiling, viewing net corrections (aka where you f'ed up), controlling multiple players and simulating latency and packet loss. The cons are that it can be tough to find documentation on stuff and there are some videos out there that give bad advice (such as using blueprints for multiplayer; DON'T use blueprints for player movement, C++ is the correct way). Luckily, there are great videos out there that give awesome advice on how to do it properly.
Unfortunately I love C# and don't really want to spend a ton of time learning C++ just so I can use Unreal's multiplayer. Also, while I haven't used Unreal's netcode myself, I've talked to others who've said it's really not as great as most people make it out to be. Either way though, I'm not sure their out-of-the-box solution would take care of the problem I had here, so it's very possible I'd just end up having to solve the same issue, just this time using a language and engine that I'm not at all familiar with.
Hahaha I haven't even tried multiplayer yet, but I feel your pain. It's always some small error that you spend most of your time trying to fix.. Nice video!
@@tomweiland sorry was a late night message ☕️ I meant we’ve started to look into client predictions as we are building a multiplayer element to our game - turns out to be a bigger can of worms than we expected 😖😂
I mean client prediction itself is still _relatively_ okay. The problems really come in when you need it to work on another moving object like a boat...
If I understand game networking correctly, there are 2 general approaches of syncing client's state with server's state. 1) Delayed input - you submit input and wait until your world state is set by server. It allows world behave smoothly on all clients, but your inputs are now less responsive. 2) Client prediction - you submit input and instantly simulate what should happen. Server then modifies your past world state and you reapply your input history, effectively correcting the present. It makes your inputs responsive, but since each new modification skips some of it's personal time, sudden events now look abrupt unless you somehow awkwardly interpolate them. Or instead of reapplying history you could accumulate error between client's and server's predictions, and then slowly/instantly use it to displace values. You can use both of them, each for it's own system. Delayed input may be used for walking around, and client prediction - , with "server feedback" part possibly omitted, - for moving your head around. And only in cases when ping is above 30-40 ms differences between those two methods become clear to a user. With first approach you'll have slower inputs, and second one will make everyone around you walk a bit weirdly. First approach is simple to implement, and second one requires you to remember an input chronology, timeline of entities that can move and are near you; but it also allows for competitiveness in platformers or shooter games (although it takes some extra cpu). ================= Also, some notes: - You have to account for high-ping cases. Ping changes over time - it may suddenly skyrocket and then fall down, and it isn't always low between two computers of the very same country. Be cool and expect the unexpected. - Not everything at all times should be broadcasted to everyone. You should only frequently update objects/features, that are close to respective clients and are hardly predictable. And you also shouldn't forget to have even minor details updated from time to time (positions, lists of existing entities), or else you may end up with severe desync. Especially if you often use UDP. - Server world state may intentionally lag behind players (or players may simulate ahead of time) just to accumulate player inputs and resolve conflicts when two players press key practically at the same time. - When some continuous non-physical state (eyeAngle, walkDirInput) is received by client, it should be interpolated or extrapolated. - Server may calculate some events (headshotting someone) from perspective of what player had seen during input submission. This is called lag-compensation, and should not be used when player's ping is far too high. And it may be useless if server-state stays behind on timeline, and so it knows what both players were doing during the headshot tick (or so I think). =================
Yeah latency itself is annoying, but on top of that you have to account for a lot of unpredictability-ping fluctuations, lost packets, duplicate packets, etc.
First one minute is all i need - blaming own lack of experience for problems Now dont get me wrong, software development is extremely vast and complex domain. Networking especially, its one of the most complex stuff out there. But cant blame own lack of skills/experience for stuff not working
@@tomweiland hahaha, you're the man tho, i really appreciate your work, i can watch your tutorials to understand a bit more about how things are done. Keep it up! :)
interesting idea with syncing the player position relative to the boat, but you could skip the floating boat, just synch a parent id + relative position over the network!
The problem with that is that it doesn't account for the discrepancies/delay in the boat's rotation, which would still lead to jittering/mispredictions an various situations. That's part of the reason why I went to the trouble of adding a "proxy" boat-it doesn't need to rotate so it just avoids that issue entirely.
That's something I may try in the future, but I didn't want to deal with another predicted element on the client, especially because then I'd have to deal with problems that arise from seeing other players in the past (impossible to predict because of the nature of FPS movement) while having them collide with boats that are comparatively in the future.
@@tomweiland afaik multiplayer games (including fps) should predict as much as possible on the cilent side, you should really dig into valve docs on networking, good luck btw, networking is one of the hardest things to do in games, theres a reason why those tutorials were made by a team of industry veterans at valve
The client needs to emulate the server. Inputs made after the last received server frame needs to be re-processed (and the physics system needs reprocessing). You then need another system that interpolates all moving entities "current" position to the new one calculated after physics is re-processed. (Each entity has multiple positions and velocities: last server frame, predicted position/velocity, and visual position/velocity) What the player sees is effectively always in a parallel universe that is very very close to the server's ground truth (separated by about 1/5th of a second of predicted state).
@@tomweiland It didn't sound like you were doing that at all from the video. If you were emulating the physics and interpolating the predicted truth with the visual truth, why would there ever be choppiness?
@@tomweiland Maybe I didn't explain it well, but you would never have collision problems from the boat if you were properly replaying input and recalculating physics.
"Choppiness" wasn't the problem, at least not due to a lack of interpolation. _"you would never have collision problems from the boat if you were properly replaying input and recalculating physics."_ Yes you would, because the problem is that clients see the boat in the past compared to the server, resulting in what is effectively a misprediction. The only thing that _really_ solves that is predicting the boat's movement as well (which is what I'll be doing in the future) so that it exists in the same "time stream" as the player on the client's end.
@@tomweiland Why would a misprediction cause any choppy problems? If the server says "10 frames ago, this is the state difference of all objects" and then the client says "okay, i'll replay the user inputs for 10 frames" you then have a new true player xyz position. You then interpolate the visual xyz position to the true player xyz position over the next 10-20 frames. Where does the choppy part come from? At no point displayed to the screen does the player ever get thrown to a new xyz position because the visual xyz position is decoupled from the true xyz position.
made a Multiplayer game for my college thesis, i made many Multiplayer projects and i have the programming part figured out, the problem is... design, you need a solid design document before the first line of code written, because retrofitting features in multiplayer code is nightmare.
_"because retrofitting features in multiplayer code is nightmare"_ In my experience, adding features down the line to a multiplayer game is actually not much of an issue-at least not significantly more than adding a feature to a singleplayer game. What _is_ a nightmare is taking a singleplayer game and then trying to make it multiplayer. But yes, having a solid idea of what features you want to include from the beginning is usually helpful as it allows you to build things with the future in mind. That goes for both singleplayer and multiplayer games.
Oh god the "Hey it seems to work really well on the host lets try it out on a separate client, too! ... oh this will take hours to fix won't it" is just the pure joy of creating multiplayer games.
I had a very similar experience working on a multiplayer FPS i never ended up finishing. I avoided the issue with player-movement by using a character controller, however, I was having lots of issues with rigid-body projectiles. It was such a pain in the head I ended up scrapping most of them.
Hmm, you must have had a different problem then, because using the CharacterController instead of a rigidbody controller wouldn't change anything. I'd still have the exact same issues...
Basic dead-reckoning problem, easy solution actually. You always use the client to determine their own position, the server's job takes the incoming movement data to determine velocity maps while testing to ensure players are within margin of where they should be given timestamps of their updates and relay those maps to other players.....then the clients can tween the values against current positions and increase/decrease speeds as needed in order to pinch position faster for sighting other players. Any "pinpoint accuracy" measurements can be checked by the server through the same tween algorithms to determine if the player actually was "on target" to another player during that timestamp. Since velocity maps are checked against timestamps, speed hacks are found quite easily. Auto-aim bots are not as easy with this, but that can be checked based on precision movement checks through obstructions. No jitter, no forced movements, and everything is quite smooth. The only downside is clipping of players when tweening values if they get too close to other objects when making turns....you could use a spline tween, but it can look unnatural sometimes.
You say there's an "easy solution", but then proceed to describe what arguably sounds _more_ (certainly not less) complex & time-consuming to implement, while being less secure...but if that's how you want to do it, go ahead :P I'm also not sure that it makes much sense to apply the term _dead-reckoning_ to first person player movement, given that players can literally turn around and start going in the opposite direction on a dime-unlike boats, cars, planes, etc.
@@tomweiland code it, you'll realize what the "easy" part is. DR is what they call it, I don't know why, I really don't care, it's like 10 lines of code. Have fun.
My niave solution is to move the client position x% closer to the server position. It'll be smooth and generally not noticeable unless there's a significant difference. And since it averages the two systems (client and server) should get back in sync. This is mostly theory at this point tho.
The problem is that the client is simulating ahead of the server, so if you don't correct fully then your starting point for future tick is still incorrect and will lead to larger divergences more quickly. What you _can_ do is fully correct the player's collider/state, but add a bit of delay to the visual so you can smoothly interpolate to the new position.
Anyone else work on a coding project give up for the night, then go to sleep, then suddenly wake up in the middle of the night with either the solution or at least a potential solution you just couldn't think of until you took a break.
I can't say I've woken up in the middle of the night (I rarely wake up at night), but I have woken up in the morning with potential solutions in mind. I also frequently can't fall asleep because my brain is still working on a problem :P
That's why I chose to do LAN multiplayer. That way, if a cheater is stealing your fun you can just go to him and punch him in the face.
😂
Like that: 1EJXTh4HMAE
It's a classic clip that was actually shared in LAN parties quite often. I think I still have it somewhere on a HDD. Yes, the time before RUclips was a thing
@Bunny99s I remember learning why you shouldn't set your drive on a subwoofer. Also to make backups
@@richardwelsh7901 will it get wiped?
Smart Man!
"Give a man a software he will enjoy it, teach him to code he'll never enjoy in his lifetime'
-Suz Tzu art of coding
Probably gonna go die of a truth overdose, brb.
Give a man a game and he will be happy for a night. Teach him how to make games and he will never be happy ever again
If this is the case games would stop existing
@@caronfernandes4625 exactly. That’s why games don’t exist.
That's why I never learned it from school, it was just not fun
"It doesn't work and I don't know why "
"Now it works and I don't know why"
-every programmer's cycle in a nutshell
The former is frustrating and the latter is fear-inducing 😂
DELETE THIS
to relatable to be said out-loud
This is my last 3 months in a nutshell 😆
And I'm only through the building system and inventory and connecting ui 😆
@@tomweiland i was following a tutorial and it had 35 errors
here is the tutorial i followed: ruclips.net/video/oyvt7RacVoo/видео.html
here is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public bool CanMove = true;
public CharacterController PlayerController;
[Header("Camera")]
[SerializeField] private Camera playerCamera;
public float MouseSensivity = 5f;
public float XRotation = 0f;
[Header("Walking Params")]
public float WalkSpeed = 4f;
private void Awake()
{
Curser.lockState = CurserLockMode.Locked;
}
public void Update()
{
Move();
HandelCamera();
}
private void Move()
{
if (!CanMove)
return;
Vector3 moveDirection = transform.right * Input.GetAxisRaw("Horizontal") + transform.forward * Input.GetAxisRaw("Vertical");
PlayerController.move(moveDirection * WalkSpeed * Time.deltaTime);
}
public void HandelCamera
{
XRotation -= Input.GetAxis("Mouse Y") * MouseSensivity;
XRotation = Mathf.Clamp(XRotation, -90f, 90f);
playerCamera.transform.localRotation = Quaternion.Euler(XRotation, 0f, 0f);
float YRotation = Input.GetAxis("Mouse X") * MouseSensivity;
transform.Rotate(new Vector3(0f, YRotation, 0f));
}
}
Players unfortunately don’t now about all these complications…
Yeah for sure. So much work goes into the (mostly) seamless multiplayer experiences we all play nowadays, and I think most people take it for granted how ingenious the systems that make it possible really are. Working with multiplayer stuff for the last ~4 years has really changed how I view games :P
@@tomweiland True
They b like : where content
@@038alpha precisely 😅
IF ONLY THEY KNEW !!! 😭😭😂😂
Thank you so much for making this. Ever since release its my go to video when players ask "Why don't you just add online"
LMAO 🙌
Hi neverjam
@@mangolover1 Hello
"Just do the thing." - Your boss.
no way its the spiderheck
"What better way to fix a bug than working around it?"
-Every Programmer Ever
Exactly :P
Yeah because that won't possibly go horribly wrong after a month into the thick of it😂😭
Making it a feature.
It's not a bug, it's a feature
until you realise none of your code works without it
I fricken love this channel! Anyone that can do networking is a god.
Haha I'm glad you like it! Despite what this video seems to suggest, I do think that anyone that's interested enough can certainly learn at least the basics of networking :)
@@tomweiland Completly true! 4 Months back i knew literally nothing and your tutorials helped me a lot! Im not using it for games tho
I agree
Even if it's photon?
Networking is nowhere near as complicated as game design imo
This is very relatable. Great video.
Whenever I tell people about how annoying it is, I don't feel like they comprehend the full extent of it. Even this video didnt fully give it justice.
It's feels like you are slowly driven mad by some eldritch god. Stuff stops making sense but it kinda does, sometimes... You start to understand why online games seem so limited sometimes.
Make sure to take care of your mental health. Take breaks and do other stuff that gives you joy and purpose in life.
For sure. This stuff can really bend your brain around...
And yeah, mental health is something to be aware of when dealing with this madness. Although honestly 90% of the last 3 months that I "spent working" on this were actually spent either enjoying the summer or procrastinating tackling this problem 😅
It's like quantum physics. But with better excuses.
Latency is worse than you think. Your processor has the speed of a 486 if you disable its caches. It is essentially playing a multiplayer game with itself since RAM is so hideously slow and instructions are pipelined over multiple clocks. Memory has kept up on bandwidth by taking many memory cells that operate slowly and multiplexing their output into something with a high clock frequency; but latency is scarcely better than 1998 because the individual cells are still slow. Even if latency of RAM was 1 clock instead of hundreds of clocks your CPU is pipelined; this means every instruction is chopped up into many stages and microops which can execute in parallel or out of order. Multiple instructions that use the same resources can be in flight at once as long as they are in different stages or in a different execution unit. To get around the latency problem the CPU is executing instructions out of order; as long as they don't depend on a prior result; and for every branch (think while-loop, if statement or for-loop) it is predicting if that branch will be taken or not and executing instructions on that basis. If ever it is wrong it needs to undo hundreds of instructions and their effects on several levels of cache as well as RAM which all have different latencies. And it gets worse; for legacy reasons the CPU has few registers and it is getting around this by renaming registers on the fly and having more physical registers than it has software addressable registers. So if you put the result of a calculation in EAX and store its value to RAM, then write something else to EAX and use that to do another computation; your CPU is aliasing EAX to different physical registers and trying to execute those things in parallel. Now there are also multiple cores which are using the same cache (L3 and RAM) in parallel and there are multiple levels of cache that have to be kept synchronized and the bigger they are, the slower they are.
And this is hardware; so this either works perfectly on the first try when you release it to the consumer or you are down billions of dollars if you release a defective product that has to be recalled. High performance processors are pure nightmare fuel.
It happens delete the glitchy function and rewrite from scratch spent two days trying to debug nuked the code and redid it all of a sudden it works.
Oh Jesus, my notifications reminded me of this cringe comment I made 2 years ago. I learned a ton since then. It can definitely help if keep things simple and rely on existing systems and tools to sync stuff. But even with a lot more experience, my comment still holds truth. Always remember to code defensively! Also log errors and important events.
The best thing is swapping a semicolon for a Greek question mark in a friend's code
That is _evil..._
@@tomweiland Look at mimic by reinderien. But don't touch it, or it may plunge your soul into darkness.
You my good man, are the devil's right hand man.
; ;
Switching from a physics based system to a simple parenting system when stepping onto the ship is actually genius. I had a stupid grin on my phase when i saw that part in the video cause i was also like "wait, how does one fix this actually?". And then my brain was like: "ah of course, why did i not think of that!" :D
It's an okay solution, but it has its issues. The jitter when getting on and off the boat being one, but I also foresee it complicating things when I get around to dealing with lag compensation. I'm strongly considering just predicting the ship's movement as well-that'd avoid the problem in it's entirety and is probably a simpler, easier to maintain solution 🤔
@@tomweiland Yea i guess that makes sens. But it's still a novel solution to safe on resources imo!
@@tomweiland Why not incorporate some allowed error margin for the client calculation on the server and be like "ah yes this sounds within the realm of possibilities, hereby I declare you not a cheater and I accept this update"
@@gzxmx94 I mean that would still allow for speed hacks and whatnot they would just be slower
@@lock6562 Most likely, but as long as you give them a sort of "Vector3D positional_errors_accrued" variable that slowly returned to (0,0,0), you could see if someone gets too many errors in quick succession is probably cheating. With that, people would only be able to hack in a very small advantage at best since the rate of their advantage is limited to not accede the resetting speed of the positional_errors_accrued or it's max value.
I tried making a multiplayer fps and gave up because of these things. It's really hard to conceptualize what this sort of entails until after it starts bending you over.
😂
> Spend forever making functioning multiplayer game/modes.
> Half the playerbase only plays singleplayer.
Social anxiety, the hardest challenge of all.
0:16 Yeah its such a good feeling when you rewrite all of that code but in a different way beause you thought your other way is stupid and didn't work BUT! then you see that you didn't type () or added an extra space
Great video btw Hope we can see more videos soon. Love the progress so far Good luck!
Yeah it's always nice when issues are quick one word fix...except when you spent 3 days trying to _find_ the issue in the first place :P
Glad you enjoyed the video-I'd definitely prefer not to go another 3 months before the next one, so hopefully soon!
That cliff hanger tho! I was on the edge o' me cap'n seat. Great video like always matey :p
I can't tell if the pirate speak is improving or getting worse every time 😂
The most honest insight I have seen into what it’s like to develop a game
😅
Brilliant to see you've got this going! Client prediction was a major reason why I gave up last time I tried networking.
It's definitely not a fun problem to be solving, and of course I had to make it even more complex for myself by having moving boats in my game 😂
@@tomweiland The boats sound like they make it significantly harder. I believe sea of thieves switches players to local coordinates for the ship. Do you think that is similar to your duplicate ship approach?
Hey, I ran into similar issues while developing pantropy. We had the player move on ground and flying/moving bases here are my tips:
1. DO NOT use a rigidbody to move your player. Physics movements are never equal on server and client. Use a CharacterController instead. The characterController.move function is always accurate and the player will move an equal distance on server and client.
2. Don't use the characterController for ground collisions. Use a raycast and keep the player a given distance away from the ground. Move the player downwards if the ray doesn't hit anything.
3. Set the player's transform as a child of a moving object (like your boats) on server and client when he enters it. You will not have any weird physics glitches thanks to the "groundray".
Hope these helped, this wroked for me flawlessly.
1. The problems I've been dealing with aren't related to a lack of physics determinism. You can actually make Unity's physics deterministic on the same machine by enabling the "enhanced determinism" option in the physics setting, and I've really only been developing & testing with both client and server on my computer. I also want to be able to easily apply forces to players, and I don't like how the CharacterController is basically a black box-no idea of/control over what goes on under the hood.
2. Again, not really a fan of CharacterController in general.
3. Making the player a child of the boat would give largely the same result that I ended up with at the end of this video. When getting on and off boats it would still jitter, and I kind of prefer my solution because I really didn't want the player to be a child of the boat.
Thanks for taking the time to make suggestions though :)
This is great advice thank you, I will be using this!
I did actually come back for this advice, and I did use it. In standard cases, this would be a perfectly fine solution. Unfortunately, my case turned out not to be standard.. of course.
As a RUclips commenter with absolutely zero game coding experience, this seems fairly good 👍, thank me later and yes I know my opinion is highly sought after
Try using a downward SphereCast and/or CapsuleCast over a single Raycast. While that solution seems to work for you, there are many scenarios where it can break. A great example are slopes. Granted, if you use the CharacterController component, slopes are automatic. But if you make your own kinematic character controller, you need to detect slopes on your own. Using something like CapsuleCast provides fantastic results. But I'm not gonna lie, creating a kinematic controller is probably the hardest thing I've ever done is game dev. It still doesn't even work tbh. There is SO much math involved. At least I learned a ton lol.
*Check out the next devlog:* ruclips.net/video/cYLnVp1ngwA/видео.html
So yeah...this is where I've been for the last 3 months (although I did also enjoy the summer a bit). Thanks for watching :D
If you're interested in learning more about client prediction/reconciliation, check this out: www.gabrielgambetta.com/client-side-prediction-server-reconciliation.html
Wow bro. Just wow. You've ran into your first major learning curve I'd say.
Prior to this you've done splendidly and really.broufht something great to the table.
Now though.
Your gonna have to learn how the big guns do it i suppose.
Why not contact aome AAA companies and ask about it through their human resources.
The Internet is obviously failing to provide decent documentation for you.
So ask how the big guys do it.
Might be a few neat tricks they use thar you can implement.
Just a thought bro.
I'm not even gonna attempt networking until next years project.
Was thinking about starting with your tutorials
@@BadBanana definitely not the first learning curve 😅
There's also plenty of resources out there on how prediction/reconciliation should work, but virtually nothing about how to ensure it works while standing on moving objects like ships. The only other game that comes to mind which would have had to deal with this is Sea of Thieves, but I'm about 95% sure they solved it the same way I did (with a "proxy" for the boat).
Hey to hype the game you should try recording the gameplay and uploading it
Did you use interpolate at movement? This a little trick can help you
@@myfantasycool yes.
I just made my first game in unity, and honestly the coding part seems kinda intimidating but i'm somehow enjoying the learning process.
Congrats! It can definitely be intimidating at the beginning, but I'd say it's definitely worth it :)
Do you guys recommend unity or unreal engine? I’m completely new and I want to get into game development.
I personally use Unity and like it a lot, but I haven't used Unreal Engine so I'm probably at least a little bit biased.
I think the most important difference is the programming languages they use-Unity uses C# which I _love,_ while Unreal uses C++ which is apparently one of the hardest programming languages to learn. You can use blueprints in Unreal instead of C++ which is like visual scripting, but I've never really been a fan of that. Both engines can be used to do a lot of the same things, but I'll probably always recommend Unity because it uses C#.
@@juju8470 I've worked in Unity and Unreal and as Tom says coding in C# is really nice and C++ usually is a slower and more tedious process and yes its difficult to get into. Unreal has a lot of build in systems similar to unitys monobehaviour but its so massive and that can be really hard to get into, so lots of trail and error early on. Blueprints is actually also pretty enjoyable to work with until you have to make massive system for your game, it can get rough to keep track of the code. Unreal also offers a lot of shortcuts and more dedicated support for artists, and level designers to get going. Unreal also has a more integrated multiplayer systems, haven't touched it myself but compared to unity its very much an engine feature.
Imo I've had less issues working in unreal on a engine error level, and the experience has been smoother working in unreal but Im still much more comfortable with unity.
@@tomweiland Be aware of using Unity networking library to develop multiplayer games, they change the API every several years mainly because not many people use it. I think it's totally not necessary, they just have to improve the API not abandon it! Unreal use the stratege and it works just fine.
I love how it just ends xD
haven't had to deal with server authority before, looks like a lot of fun ;) enjoy your next few weeks fixing more bugs!
"Fun". Yes, that...
Fun, so fun still exists
Fancy to see you here, I asked you about how you networked redmatch 2 in steam comments a while ago. Been a rough learning for me but fun nonetheless. Seeing this video just adds a layer of terror to the ordeal but it will be done...
@@kodi0223 xD Glad you're having fun!
@Limeify lol thats great
Godspeed my friend, that's why I'm sticking to single player for the foreseeable future! Also the music that kicks in at 0:30 made me think That Chapter and I was worried someone was going to end up dead by the end of the video
A wise choice 😅
These problems are why I probably wouldn't recommend a multiplayer game for a first project (unless it's local multiplayer). It's a real headache to figure out the proper way for networking in games, and when you're also doing everything else for the first time, it becomes a whole lot to handle.
Yep, 100% agree.
Agree! it's always good to learn the basics and then go for the multiplayer aspect after
I wouldn't even recommend local, as it makes playtesting way more of a pain.
Great video, Tom! Really enjoyed this one, and I love how you're so concise and clear with everything you say! Awesome work :D
Really glad you enjoyed it :D
ayoooooo
icoso spotted in the wild?
nice :D
hope you're doing good man
This is a great video. Very good and clean explanation of an otherwise very complex topic.
A few things from my several years experience:
- there's no need to "compare" for misprediction... just overwrite with server data and resimulate forward (maybe this is what you do already) with the local input buffer...
- for moving boats, and all moving platforms in that sense, it gets trickier because you could place the boat in predicted timing as well (if you also predict/rollback physics, which you can do), but this would create a problem for proxies (view of other players) as they are generally on interpolated time.
One thing that may work for proxies is to predict just their gravity and move-with-platform part... But in either case or solution you will loose one thing, which is the capability of doing accurate lag compensation... but that is another story...:)
Thanks for watching :)
You're right about not needing to compare positions-I don't actually do that in my code, but since I didn't want to get into the whole rewinding-and-resimulating part I figured that'd be the easiest way to explain what happens from there in a single sentence.
I definitely thought about predicting the boat movement as well, but that would've then meant also predicting the waves, and it sets the precedent of having to predict anything that moves which the player might end up standing on. Then again I suppose I've set a similar precedent in the sense that if I want to avoid jittering on other moving objects, they're going to need "proxies" as well...
"You realize that you didn't read the documentation properly". Oh, if only! I can't even begin to count the hours I've wasted on following incorrect documentation.
The pain 😫
Great thumbnail :)
Lol only just started watching and it’s already great
Glad to hear it :D
can't tell if i'm inspired to make a game or heavily deterred
love the videos!
Glad you enjoyed it! I can at least see the light at the end of the tunnel now, so maybe take it as inspirational with strong warnings about what you're getting yourself into? :P
I feel your pain Tom, good luck with fixing the issues!
Your game looks sick :D
Thank you :D
just found you because of this video and got sucked into the rest of your videos watching your progressing of your game. Gave me inspiration man!
That's awesome! Glad to hear you've enjoyed the videos :)
You are doing great work man. The fact that you have gotten this far this quickly already puts you light years a head of others in the industry. To top it all off you are teaching yourself all this. That puts you even farther. I can't wait to see any tutorials that you (hopefully) put out for the new netcode.
Thanks for the kind words, that means a lot to hear :)
I really appreciate learning from your experiences. Thank you so much for sharing your progress.
I'm happy to! Thank _you_ for watching :D
It's interesting to hear your experiences with implementing multiplayer. I'm writing a multiplayer game myself in Unity but it's simultaneous turns on a grid-based map so I'm not feeling the pain of realtime play, I'm sure I'll discover my own pains as I progress though. Anyway, I always liked this quote from Michael Abrash's Black Book on reducing player latency in Quake - Reduced latency also often makes for more frustrating play. It’s actually not hard to reduce the latency perceived by the player, but many of the approaches that reduce latency introduce the potential for paradoxes that can be quite distracting and annoying. For example, a player may see a rocket go by, and think they’ve dodged it, only to find themselves exploding a second later as the difference of opinion between his simulation and the other simulation is resolved to his detriment.
Yeah, hiding latency introduces a whole other set of problems to deal with...can't wait!
It's very wise of you to work on a game that doesn't require realtime play 😂
@@tomweiland Yeah, well actually no, I should have edited that. It is realtime but not realtime realtime. As in the players move in realtime simultaneously during their turn but they're restricted to a grid so I don't have to worry about little annoyances like physics and collisions. I've probably got it easy compared to you but there's still plenty to think about. It is at the same time both a 'fun' challenge and an interesting learning experience.
just amazing man , love this channel , ur multiplayer series was amazing , i loved it , ty so much
Thanks for the kind words, glad you're enjoying the channel!
I am soo happy I kept it ad 2d without physics and to something where single milliseconds don't matter that much. I really am feeling with you though, network-code is the worst to debug. Especially if you went insane like me and introduced multi-threading in the process, please just end my eternal suffering.
Multi-threading is asking for trouble 😂
Nice video, keep trying with the multiplayer, you'll get there eventually.
Yep, I can at least see the light at the end of the tunnel now, so I'm hoping things will start getting less frustrating 😅
Yo, you finally got into the same problems I have been working on for the past 3 months. I was almost getting angry seeing you not having to deal with any of those. 😂
Why try solving problems when you can just _avoid_ them instead 😅
@@tomweiland Jittering is not a bug, it's a feature. It defines the status of chaos of the world making the player feel the uncertainty and instability of life. Latency also is important, it teaches the player to wait and have patience or to take initiative and get a better connection.
Ah yes...patience. Precisely what the gaming community is known for...
Oh my god that is the most hacked together solution I've seen in a long time. I love it!
😅
Wow! Amazing video. From the beginning to the end I was engaged and entertained. The only thing that could've improved this video was your jawline.
_Epic_ 🙌
Sorry for enjoying watching your struggles on RUclips :D Keep trying, it will eventually succeed (if it doesn't drive you mad).
Remembers me when my friend and I had had to use an obscure front framework and the correct data wasn't showing, it took us 3 weeks of heavy sweating and nightmares to discover it was expecting some weird null instentiatiation with no data to work...
"3 weeks of heavy sweating and nightmares" should be part of programmers' job descriptions 😅
This was a really good video Tom. Great video editing as well. You can see the effort you put in. Good luck with the continued efforts and we all look forward to more updates in the future!
Thanks, really glad you enjoyed it! I definitely think this was my best video, despite being about a topic that can easily be very boring.
Hey Tom! Has been a while since I dropped in to watch a video by yours.
It changed, in a good way. You made me chuckle and it was informative.
Keep up the work, mate!
Glad to hear you like what has changed :D
Man, I am glad I'm only doing singleplayer.
I think if/when I eventually finish this game, I will build a singleplayer game next. Or at least a multiplayer game that doesn't require hiding latency to ensure a good gameplay experience. Maybe a top down RTS or something 😂
Or you can try building coop games where the client-side authority is usually enough
As a person who's just jumped into the ship of game development, I've decided that I want to make a multiplayer game at some point. So, I will absorb all of the videos that you have with issues and explanations/solutions to these issues. I've subscribed waiting for for the next video lol
I'm hoping to upload a new one in the next few weeks 🤞
Good luck with your game dev journey!
The irony that UE4 does movement prediction for you with very little effort. You just tell the server and client to move. And it solves the rest.
I mean that's nice I guess...but totally useless in my case. A generic prediction solution would have the exact same issues on boats that I'm having, so I would end up needing to heavily modify it (at which point it'd probably just be easier to write my own). I'm also using Unity and don't plan on switching-I like C# and don't feel like learning C++ right now, and blueprints are quite unappealing to me.
It's also worth noting that Unreal's netcode out of the box is really only good for small arena shooters with less than like 20 players (my game is not one of those). Epic themselves had to make modifications to get Fortnite to be able to handle 100 players on the same map.
@@tomweiland Yeah that's true, the MMORPG Ashes of Creation is being made on UE4 and they had to make their own proprietary networking to make UE4 capable of supporting a massive concentration of people (the Massive on MMO :P)
@@Hunsenbargen I would think this is mostly about reducing fidelity. Players that are far away don't need 60 updates per second or even 30. Even 1 update per second will go very far as long as they are running in a somewhat straight line or turning smoothly. You therefor only need to send frequent updates if they are doing something unexpected. As the number of players increases the naive solution is an O(N^2) problem.
I was going to say. A lot of these issues (not all) are solved in UE out of the box. I actually found it very easy to set up a multiplayer replicated movement model.
Us old hats remember Internet 0.4 beta, before the latency feature was added
The good old days :P
Making multiplayer games with Unity is just a pain, it's so simple if you're aware of networking basics in Unreal ^^
🤷♂️
3:34 - You must have never been playing GTA5, and been riding in a car with someone as they smash into a wall, only to find that it was your client mis-calculating, then have the car magically appear back on the road, once the server updates the real position.
I mean...this happens in plenty of games, not just GTA. However you are correct, I haven't played GTA5 😅
Even worse when you're in a roleplay server and react out loud to the crash, only to find that you're the only one that experienced it lmao
"Take 2 days to fix the error"
Me trying to upload my game to google play from past 2 days
1. Keystore
2.some random arc64
3.150mb limit
4. api
time taken 1- week
😬
Great video! Despite being much shorter, it was definitely your best!
I agree! Analytics seem to be reflecting that too, it's doing twice as well as my videos usually do in the first 12 hours :)
@@tomweiland glad to hear that! I hope to see more like this.
The pain which every gamer and program feels
rip my guy
It's been a looong 3 months 😂
Thanks for the link to the articles. Very helpful.
Great!
Don't lie. DO NOT lie. No one said coding would be fun 😂
Touché :P
Coding is fun for m-
Great video and I've actually been confronted with this issue today too...
My solution is very game specific, but it works out pretty well
Nice, glad you enjoyed it :)
Oh if only the players knew what we go through to make the multiplayer experience at least on the "acceptable level".. #PrayForNetDevs
True. I think we are under-appreciated :P
This is actually a great explanation why standing on a vehicle in any multiplayer game like Battlefield series was always normally fine, but when it was moving, things would go spasmatic and probably end in phasing through the vehicle or dying for no reason.
Makes sense-as long as it's not moving, you don't experience the effects of objects from different "time streams" interacting. Once it moves though, 💩 hits the fan :P
I did laugh with you at a couple of points. Streaming gaming services can't come fast enough. Your description is excellent, I think it was wise too stop before you got into estimating latency and forward calculating at the server. "Time streams" was a great phrase.
Still enjoying your vids, sorry it's being such a pain.
Glad my humor hasn't been stripped of me along with my sanity 😂
I'll figure it out eventually, I have the bulk of the pain out of the way now, so I at least see the light at the end of the tunnel :)
I'm hoping I explained things well enough with enough visual aids to keep people interested even if they're not familiar with programming and multiplayer.
@@tomweiland you explained it well enough for me to not build my own!!! 😂
LOL
Your wisdom clearly exceeds mine.
Now i understand why there was a weird lag when i jump off from boat Vanilla Wow.
Possibly :P
"They" is every single non-programmer ever.
You may have a point 🤔
0:59 lol my ethernet cable came loose and made the video buffer while he was talking about latency
What a strange coincidence :P
Good thing channels like this exist that talks about painful topics, having a beer beside you does wonders 🤣
😂
5:09 Little tip for recording long texts where you run out of breath:
take little stops inbetween to breathe and cut it out in editing so you have a more chill recording experience :)
Thanks, but it was honestly just a joke :P
@@tomweiland considering how often I need to cut down my audio, I honestly related too much to see the joke 🤣
Glad to see you're back.
Yeah...only took 3 months :P
@@tomweiland progress is progress, my dude.
You're really good with analogies!
Thanks 😅
Sounds like fun :D Sorry you went through these issues but this was very informative! It starting to sound like the Marvel Multiverse with all the client and server prediction stuff haha. Glad you got a lot of the latency/jitters fixed, at least with a single player in!
Welcome to the Unnamed Pirateverse 😂
Thumbnail is awesome xD
Haha great :P
You probably want to keep your control over the server, but if you ever decided to switch to Photon, it has an option for extrapolation to enable Photon's server to predict where a player's transform may be in its Photon Transform View Classic documentation. I'm unsure of how well this will work for your game, but in case you weren't aware of this option, thy has presented it.
Wait, it predicts the location of _other_ players? That's normally a major no-go in first person shooter games...
@@tomweiland I see, I've never needed to use the option myself, so thanks for letting me know
that intro spoke to my soul
I'm sorry to hear that 😔😂
I had the same problem when I created my first multiplayer game too, but I found out that letting the player move only after getting the move message from the server worked better than trying to predict the player’s future position on both the server and the client at the same time. The process was: player presses W -> sends it to server -> server check if the move is valid and instantly sends back command to tell client to move the character.
The latency can be forgiven because most of the time it happens in less than one frame. That way, I can focus on reducing the message size instead of trying to correct the player position, which is a dead end.
Waiting for a response from the server before moving quickly leads to an experience that is sufficiently unresponsive for it to feel awful. A 50ms round-trip time is plenty for the delay to be noticeable, and I'd argue that it's unreasonable to expect most players to have less than that, especially when you factor in the added delay from your tick rate (lower tick rates mean bigger gaps between ticks, which effectively increases the time it takes for the server to respond) and from slightly buffering positions so you can interpolate them and have the movement look smooth.
Players with powerful rigs and high refresh rate monitors will also be more likely to notice delays than players whose monitors max out at 60hz.
_"The latency can be forgiven because most of the time it happens in less than one frame."_
This is just not true in my experience, unless you're testing with the server and client on the same network. At 60hz you have a frame time of ~16ms, and the vast majority of your players will almost certainly not have a round trip time that's less than that. Someone with a 144hz monitor will have a frame time of just ~7ms, so even if they somehow had a mere 25ms round trip time on their connection, at least 4 frames would pass before they see the result of a key press.
I think player movement can be handled locally, but if the player moves beyond the sphere of allowable mismatch and for too often, it can be verified more and more by the server.
I used something like a "suspicion" tracking variable, where someone speed hacking or teleporting quickly finds their movement entirely server-authenticated.
So it trusts the client initially, but the trust can be lost for a time.
Multiplayer coding is absolute hell, just getting a game to finally accept connections was a whole endeavor...
The problem is that checking speed or distance traveled doesn't account for things like collisions, and those metrics really say very little about whether the movement is "acceptable". A system like that wouldn't catch someone who's walking through a wall, or someone who slows their gravity down so they fall slowly, and making the system capable of detecting those things essentially requires simulating all of the movement logic on the server.
At that point, it's arguably easier and less work to just give the server full authority, and by doing so you'll also avoid dooming yourself to playing the cat & mouse game of hackers finding ways to exploit/evade your detection systems and you having to react. At the end of the day it just comes down to what tradeoffs you want to make-I prefer giving cheaters as little chance as possible to gain an advantage :P
Before you got to the part where you wanted to get back to the practical side of things 4:13, I immediately thought "why not use a decimal data type and clamp the position to the nearest median? The difference is negligible." Also, to fix your new problem, it starts off with how you tackle the problem. First off, depending on your set up, the water becomes the parent and the objects such as ships and the terrain to walk on become the children of the sea. When the boat sails out to the sea and hits a certain local distance in the water, the land itself moves away from the boat and the water instead; This has the server calculate the position of the static land (and local position of the player), not the boat.
_"I immediately thought 'why not use a decimal data type and clamp the position to the nearest median? The difference is negligible.'"_
What exactly would this accomplish/solve?
_"When the boat sails out to the sea and hits a certain local distance in the water, the land itself moves away from the boat and the water instead; This has the server calculate the position of the static land (and local position of the player), not the boat."_
Are you suggesting that I make the boat stationary and move the land and water around it in order to make it _look_ like the boat is the one moving? That sounds _at least_ as complicated as the solution I ended up with, and it has many more problems. What should happen if one player is standing on a boat and another is on land? What should happen if there are 2 boats? Which one should everything move in relation to?
Best choice I made when creating my multiplayer game was switching over to Unreal. I've used Unity for years, learning all the ins and outs, but it lacks the tools for multiplayer development. Unreal has a ton of great features for multiplayer like profiling, viewing net corrections (aka where you f'ed up), controlling multiple players and simulating latency and packet loss. The cons are that it can be tough to find documentation on stuff and there are some videos out there that give bad advice (such as using blueprints for multiplayer; DON'T use blueprints for player movement, C++ is the correct way). Luckily, there are great videos out there that give awesome advice on how to do it properly.
Unfortunately I love C# and don't really want to spend a ton of time learning C++ just so I can use Unreal's multiplayer. Also, while I haven't used Unreal's netcode myself, I've talked to others who've said it's really not as great as most people make it out to be. Either way though, I'm not sure their out-of-the-box solution would take care of the problem I had here, so it's very possible I'd just end up having to solve the same issue, just this time using a language and engine that I'm not at all familiar with.
Nice solution for the boat moving calculation!
Thanks, though it's a mess. If I come back to the project I'll definitely be switching to just predicting boat movement on clients.
Thanks for the heads up. I find struggle in every corner so I'm not surprised
Good luck :)
Hahaha I haven't even tried multiplayer yet, but I feel your pain. It's always some small error that you spend most of your time trying to fix.. Nice video!
Yeah, the small things always cause the biggest problems...glad you enjoyed the video :)
Awesome video Tom!
Thanks for watching!
Funny, we made the exact same decision recently !! We’re going to onboard a networking specialist in our second release probably ! Nice content !
Wait, the exact same decision as what?
@@tomweiland sorry was a late night message ☕️ I meant we’ve started to look into client predictions as we are building a multiplayer element to our game - turns out to be a bigger can of worms than we expected 😖😂
I mean client prediction itself is still _relatively_ okay. The problems really come in when you need it to work on another moving object like a boat...
@@tomweiland yes we don’t have that issue so much.. for now….
And the world's best thumbnail award goes to:
Hmm you really think so? 🤔
Bro, I feel you so much rn, I am literally stuck at client prediction in my own game right now xd
Oof, good luck!
If I understand game networking correctly, there are 2 general approaches of syncing client's state with server's state.
1) Delayed input - you submit input and wait until your world state is set by server. It allows world behave smoothly on all clients, but your inputs are now less responsive.
2) Client prediction - you submit input and instantly simulate what should happen. Server then modifies your past world state and you reapply your input history, effectively correcting the present. It makes your inputs responsive, but since each new modification skips some of it's personal time, sudden events now look abrupt unless you somehow awkwardly interpolate them. Or instead of reapplying history you could accumulate error between client's and server's predictions, and then slowly/instantly use it to displace values.
You can use both of them, each for it's own system. Delayed input may be used for walking around, and client prediction - , with "server feedback" part possibly omitted, - for moving your head around.
And only in cases when ping is above 30-40 ms differences between those two methods become clear to a user.
With first approach you'll have slower inputs, and second one will make everyone around you walk a bit weirdly. First approach is simple to implement, and second one requires you to remember an input chronology, timeline of entities that can move and are near you; but it also allows for competitiveness in platformers or shooter games (although it takes some extra cpu).
=================
Also, some notes:
- You have to account for high-ping cases. Ping changes over time - it may suddenly skyrocket and then fall down, and it isn't always low between two computers of the very same country. Be cool and expect the unexpected.
- Not everything at all times should be broadcasted to everyone. You should only frequently update objects/features, that are close to respective clients and are hardly predictable. And you also shouldn't forget to have even minor details updated from time to time (positions, lists of existing entities), or else you may end up with severe desync. Especially if you often use UDP.
- Server world state may intentionally lag behind players (or players may simulate ahead of time) just to accumulate player inputs and resolve conflicts when two players press key practically at the same time.
- When some continuous non-physical state (eyeAngle, walkDirInput) is received by client, it should be interpolated or extrapolated.
- Server may calculate some events (headshotting someone) from perspective of what player had seen during input submission. This is called lag-compensation, and should not be used when player's ping is far too high. And it may be useless if server-state stays behind on timeline, and so it knows what both players were doing during the headshot tick (or so I think).
=================
^I didn't write it just now, it's something I entirely made a year ago
Yeah latency itself is annoying, but on top of that you have to account for a lot of unpredictability-ping fluctuations, lost packets, duplicate packets, etc.
It's painful how relatable this is, how the video ends in basically failure and a long list of issues to fix in the morning xD
Hahaha :P
First one minute is all i need - blaming own lack of experience for problems
Now dont get me wrong, software development is extremely vast and complex domain. Networking especially, its one of the most complex stuff out there.
But cant blame own lack of skills/experience for stuff not working
tenor.com/view/nick-young-question-mark-huh-what-confused-gif-4995479
I use a quantum entangled network card for my laptop, it has no latency. Then I just coded my game as if it was a split-screen game. 10/10.
Where do I get one of those :P
Why does seeing how painful making a game is actually makes me want to make one
Misery loves company :P
It might be very difficult but once you fix a problem it's so satisfying. And then there's 20 other problems after you fix one
99 little bugs in the code,
99 little bugs.
Take one down, patch it around
127 little bugs in the code...
I don't really understand how the solution of the second boat not moving works but that's cool as hell that it does.
😅
wow the end got me dying lmfao, my everyday struggle and im not even as good as you.. It's a pain.
Welcome to multiplayer game dev 😂
@@tomweiland hahaha, you're the man tho, i really appreciate your work, i can watch your tutorials to understand a bit more about how things are done. Keep it up! :)
interesting idea with syncing the player position relative to the boat, but you could skip the floating boat, just synch a parent id + relative position over the network!
The problem with that is that it doesn't account for the discrepancies/delay in the boat's rotation, which would still lead to jittering/mispredictions an various situations. That's part of the reason why I went to the trouble of adding a "proxy" boat-it doesn't need to rotate so it just avoids that issue entirely.
If the boat has quasi-deterministic physics there should be no problem in simulating its position on the client side.
That's something I may try in the future, but I didn't want to deal with another predicted element on the client, especially because then I'd have to deal with problems that arise from seeing other players in the past (impossible to predict because of the nature of FPS movement) while having them collide with boats that are comparatively in the future.
@@tomweiland afaik multiplayer games (including fps) should predict as much as possible on the cilent side, you should really dig into valve docs on networking, good luck btw, networking is one of the hardest things to do in games, theres a reason why those tutorials were made by a team of industry veterans at valve
The client needs to emulate the server. Inputs made after the last received server frame needs to be re-processed (and the physics system needs reprocessing). You then need another system that interpolates all moving entities "current" position to the new one calculated after physics is re-processed. (Each entity has multiple positions and velocities: last server frame, predicted position/velocity, and visual position/velocity)
What the player sees is effectively always in a parallel universe that is very very close to the server's ground truth (separated by about 1/5th of a second of predicted state).
Did you mean to just explain the video in your own words, or was there a point you wanted to make? I can't tell 😅
@@tomweiland It didn't sound like you were doing that at all from the video. If you were emulating the physics and interpolating the predicted truth with the visual truth, why would there ever be choppiness?
@@tomweiland Maybe I didn't explain it well, but you would never have collision problems from the boat if you were properly replaying input and recalculating physics.
"Choppiness" wasn't the problem, at least not due to a lack of interpolation.
_"you would never have collision problems from the boat if you were properly replaying input and recalculating physics."_
Yes you would, because the problem is that clients see the boat in the past compared to the server, resulting in what is effectively a misprediction. The only thing that _really_ solves that is predicting the boat's movement as well (which is what I'll be doing in the future) so that it exists in the same "time stream" as the player on the client's end.
@@tomweiland Why would a misprediction cause any choppy problems?
If the server says "10 frames ago, this is the state difference of all objects" and then the client says "okay, i'll replay the user inputs for 10 frames" you then have a new true player xyz position. You then interpolate the visual xyz position to the true player xyz position over the next 10-20 frames. Where does the choppy part come from? At no point displayed to the screen does the player ever get thrown to a new xyz position because the visual xyz position is decoupled from the true xyz position.
Petition to make speed of light 10x time faster, so that we don't have to mess with all of this, bruh
If only...
made a Multiplayer game for my college thesis, i made many Multiplayer projects and i have the programming part figured out, the problem is... design, you need a solid design document before the first line of code written, because retrofitting features in multiplayer code is nightmare.
_"because retrofitting features in multiplayer code is nightmare"_
In my experience, adding features down the line to a multiplayer game is actually not much of an issue-at least not significantly more than adding a feature to a singleplayer game. What _is_ a nightmare is taking a singleplayer game and then trying to make it multiplayer.
But yes, having a solid idea of what features you want to include from the beginning is usually helpful as it allows you to build things with the future in mind. That goes for both singleplayer and multiplayer games.
Great video, thanks for sharing. Funny as well, which helps 😃
Glad you enjoyed it!
Oh god the "Hey it seems to work really well on the host lets try it out on a separate client, too! ... oh this will take hours to fix won't it" is just the pure joy of creating multiplayer games.
😭
Tom posted = day saved
😳
Best devlog vídeos on youtube.
I'm honored 😅
I had a very similar experience working on a multiplayer FPS i never ended up finishing. I avoided the issue with player-movement by using a character controller, however, I was having lots of issues with rigid-body projectiles. It was such a pain in the head I ended up scrapping most of them.
Hmm, you must have had a different problem then, because using the CharacterController instead of a rigidbody controller wouldn't change anything. I'd still have the exact same issues...
I feel your pain, and I haven't even started making my game multilayer
Oof.
I started, but hoping my game doesn't have anything complicated to run into these issues! lol
That last part gave me goose bumps, and not the good ones...
😬
Basic dead-reckoning problem, easy solution actually. You always use the client to determine their own position, the server's job takes the incoming movement data to determine velocity maps while testing to ensure players are within margin of where they should be given timestamps of their updates and relay those maps to other players.....then the clients can tween the values against current positions and increase/decrease speeds as needed in order to pinch position faster for sighting other players. Any "pinpoint accuracy" measurements can be checked by the server through the same tween algorithms to determine if the player actually was "on target" to another player during that timestamp. Since velocity maps are checked against timestamps, speed hacks are found quite easily. Auto-aim bots are not as easy with this, but that can be checked based on precision movement checks through obstructions.
No jitter, no forced movements, and everything is quite smooth. The only downside is clipping of players when tweening values if they get too close to other objects when making turns....you could use a spline tween, but it can look unnatural sometimes.
You say there's an "easy solution", but then proceed to describe what arguably sounds _more_ (certainly not less) complex & time-consuming to implement, while being less secure...but if that's how you want to do it, go ahead :P
I'm also not sure that it makes much sense to apply the term _dead-reckoning_ to first person player movement, given that players can literally turn around and start going in the opposite direction on a dime-unlike boats, cars, planes, etc.
@@tomweiland code it, you'll realize what the "easy" part is. DR is what they call it, I don't know why, I really don't care, it's like 10 lines of code. Have fun.
My niave solution is to move the client position x% closer to the server position. It'll be smooth and generally not noticeable unless there's a significant difference. And since it averages the two systems (client and server) should get back in sync. This is mostly theory at this point tho.
The problem is that the client is simulating ahead of the server, so if you don't correct fully then your starting point for future tick is still incorrect and will lead to larger divergences more quickly. What you _can_ do is fully correct the player's collider/state, but add a bit of delay to the visual so you can smoothly interpolate to the new position.
Anyone else work on a coding project give up for the night, then go to sleep, then suddenly wake up in the middle of the night with either the solution or at least a potential solution you just couldn't think of until you took a break.
I can't say I've woken up in the middle of the night (I rarely wake up at night), but I have woken up in the morning with potential solutions in mind. I also frequently can't fall asleep because my brain is still working on a problem :P