Announcement

Collapse
No announcement yet.

Networked "Physics-Vehicle Movement Component": existing examples or implementation hints?

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • replied
    Originally posted by TheJamsh View Post
    Yeah see that's where my problem comes from. In my example it's technically already doing the 'prediction' client-side, since the client moves to a location instantly (in theory anyway) and the Server does the same with the same input data, albeit a few milliseconds later (in LAN at least).

    The server does the move then hard-sets the location on the Client, so in theory they should be 'close' to in-sync so the player won't notice the discrepancy. Over a network connection my example probably isn't going to hold up.

    Unfortunately since Unreal doesn't use Deterministic Physics (which I can understand, since it's bloody hard), it's also impossible to completely leave the movement up to the physics engine and just provide input in the hope they will remain the same. Even with the same fixed time-step and latency offsets, you'll still get slight differences. Especially when collisions occur too. I figured that the replication code for WheeledVehicleMovement would hold up but unfortunately I don't think it will for very long, especially when I'm not testing via LAN or on the same PC.

    I will start work on this again soon, since I'd like to get a demo of my game out asap. Unfortunately Quadtrees are taking up my time atm
    Yepp, that'll fall apart in some LAN configurations - when I was developing my old space game, I had a lot of problems with packet ordering (it was at a college, with an 'interesting' setup that ran all connections through several firewalls and routers elsewhere in the building and then back). If you just hard-set your positions, that's gonna get gross. It will be impossible over the internet.

    The idea isn't that the server and client are absolutely matched and deterministic when it comes to physics simulations. Instead, you just want to get them as close as possible.
    When you 'provide' the input to the server, you include the timestamp the input was recorded, as well as storing that input in a local buffer. When the server sends back physics info, it includes that timestamp, as if to say "here's your new physics data, and THIS is the latest input I've processed from you". The client gets this info, and uses that position as the starting point, resimulating every input in the buffer from that returned timestamp onwards. The position after the input is all resimulated is where the client 'should' be. The difference between where it originally thought it should be and that position that it calculates from the input buffer needs to be as small as possible - you'll end up lerping between them to cover any slight mistakes.

    Hopefully that makes sense. It's a more clumsy description of client-side prediction and server reconciliation than what's available here.

    Leave a comment:


  • replied
    Yeah see that's where my problem comes from. In my example it's technically already doing the 'prediction' client-side, since the client moves to a location instantly (in theory anyway) and the Server does the same with the same input data, albeit a few milliseconds later (in LAN at least).

    The server does the move then hard-sets the location on the Client, so in theory they should be 'close' to in-sync so the player won't notice the discrepancy. Over a network connection my example probably isn't going to hold up.

    Unfortunately since Unreal doesn't use Deterministic Physics (which I can understand, since it's bloody hard), it's also impossible to completely leave the movement up to the physics engine and just provide input in the hope they will remain the same. Even with the same fixed time-step and latency offsets, you'll still get slight differences. Especially when collisions occur too. I figured that the replication code for WheeledVehicleMovement would hold up but unfortunately I don't think it will for very long, especially when I'm not testing via LAN or on the same PC.

    I will start work on this again soon, since I'd like to get a demo of my game out asap. Unfortunately Quadtrees are taking up my time atm

    Leave a comment:


  • replied
    Originally posted by TheJamsh View Post
    Not really! I made the Center of my mesh at 0, 0, 0 in the model which works well for me!



    It's been a while since I looked but you might be right, the issue is that Clients can only call RPCS on objects that they 'Own'. However I have been sending RPC's in a component of my own in another case without issue, so I think so long as you own the Actor that owns the Component, you're fine. It might just be the way they did it since it worked better for them, or possibly when they implemented it, you couldn't call RPC's on Actor Components! No idea on that one though...
    Ahh yeah fair call.

    I've been looking into client-side prediction and server reconciliation for physics-based games in UE4, and it's been pretty difficult.

    For example, when you receive an authoritative update from the server, you'd need to roll-back to it and re-simulate your inputs from that time onwards. How are you doing this in your game? I got it working by using my own physics (i.e. something dumb like position += velocity * DeltaSeconds) and a fixed timestep (DeltaSeconds in that formula is always 0.016666666f or similar). It'd be nice to use PhysX for this, but I couldn't see a way to manually resimulate x number of physics frames within one Tick, and physics updates are occurring at different rates/timesteps due to variable framerates between server and client. Because of this, the server and client should often disagree about where the client should end up, and so you'd often be correcting the results on the client's end.

    Would be interesting to hear how you've gone!

    Leave a comment:


  • replied
    Originally posted by HateDread View Post
    Okay cool. Just thought you might've done so to make your tanks rotate as desired. Any tips for configuring pawn/mesh rotation? As in, center of mass / axis of rotation stuff.
    Not really! I made the Center of my mesh at 0, 0, 0 in the model which works well for me!

    Originally posted by HateDread View Post
    Just looking into making my own pawn movement component, and looking at the character's; it doesn't seem to itself be replicated? I would've thought it'd be receiving RPCs and replicated variables in order to handle it internally and adjust the character's position, but it seems not! Seems totally crazy to me. Am I right in thinking that the the pawn/character should handle the RPC/replication, and then hand that off to the movement component to let it do correction/smoothing?
    It's been a while since I looked but you might be right, the issue is that Clients can only call RPCS on objects that they 'Own'. However I have been sending RPC's in a component of my own in another case without issue, so I think so long as you own the Actor that owns the Component, you're fine. It might just be the way they did it since it worked better for them, or possibly when they implemented it, you couldn't call RPC's on Actor Components! No idea on that one though...

    Leave a comment:


  • replied
    Originally posted by TheJamsh View Post
    The root object of my Tanks are the meshes themselves, so there's no trickery

    What I do is multiply my Torque / Angular velocity values by the Front, Right and Up vectors (depending which axis I want to rotate around), which ensures it always pivots around it's correct axes, and also prevents any 'gimbal lock' issues that you'd otherwise have to use Quats for. In the example code above for example:

    Code:
    Alpha += Up * SteerVal;
    I'm adding to Angular Acceleration (Alpha) here, which is just the Up axis of the actor (well, the UpdatedComponent) multiplied by whatever the steer value currently is (pretty much straight off of the mouse).

    I get the axes like this btw (every frame):

    Code:
            FVector Front = UpdatedPrimitive->GetForwardVector();
    	FVector Right = UpdatedPrimitive->GetRightVector();
    	FVector Up = UpdatedPrimitive->GetUpVector();
    Okay cool. Just thought you might've done so to make your tanks rotate as desired. Any tips for configuring pawn/mesh rotation? As in, center of mass / axis of rotation stuff.

    Just looking into making my own pawn movement component, and looking at the character's; it doesn't seem to itself be replicated? I would've thought it'd be receiving RPCs and replicated variables in order to handle it internally and adjust the character's position, but it seems not! Seems totally crazy to me. Am I right in thinking that the the pawn/character should handle the RPC/replication, and then hand that off to the movement component to let it do correction/smoothing?

    Leave a comment:


  • replied
    The root object of my Tanks are the meshes themselves, so there's no trickery

    What I do is multiply my Torque / Angular velocity values by the Front, Right and Up vectors (depending which axis I want to rotate around), which ensures it always pivots around it's correct axes, and also prevents any 'gimbal lock' issues that you'd otherwise have to use Quats for. In the example code above for example:

    Code:
    Alpha += Up * SteerVal;
    I'm adding to Angular Acceleration (Alpha) here, which is just the Up axis of the actor (well, the UpdatedComponent) multiplied by whatever the steer value currently is (pretty much straight off of the mouse).

    I get the axes like this btw (every frame):

    Code:
            FVector Front = UpdatedPrimitive->GetForwardVector();
    	FVector Right = UpdatedPrimitive->GetRightVector();
    	FVector Up = UpdatedPrimitive->GetUpVector();

    Leave a comment:


  • replied
    Originally posted by TheJamsh View Post
    Not solved yet, currently working on a Radar system before coming back to this... needed a break The code above is part of a pretty basic PawnMovementComponent of my own, though honestly what I've done could just be done as part of the Pawn right now. I just wasn't sure how tarted up it was going to get, especially when it comes to pathing and prediction etc.

    You're pretty much right, the Replicated Movement and Client simulation are fighting each other, which is why I get the latency from the controls. Other than that though, it all works. The trick is that the Physics function is being called on tick both Client & Server side, so that keeps them from going out of sync since velocity and angular velocity are always being updated. I also handle damping and drag in there as well, so when a collision happens, the drag affects the calculation on both ends and causes position/rotation updates to be sent out from the server, causing them to remain in sync. If I switch off the movement simulation and a collision occurs client-side, they stay out of sync until the server sends a position update.

    I really want to look more into CMC's system, since I want to implement based-movement (e.g., moving with the object I'm hovering on) and imparted velocity. This is still just the beginning Any progress I make though, I'll post here in one form or another!

    Unfortunately since Unreal doesn't use deterministic / seeded physics, I have to use replicated movement or otherwise I just risk client-side collisions not being handled the same way.
    Okay thanks, I'll have to spend some time parsing this thread and your post.

    How have you setup your component hierarchy for the hover tanks, and how do you ensure that they rotate around the right point? For reference, when I apply torque to my root bone: http://i.gyazo.com/542581caffce3ab890b2c906e9829f94.gif Just wondering if your tanks are skeletal/static meshes attached to a basic sphere or something, and then offset, with the torque/force added to that sphere rather than the mesh, so you can tweak the point around which it rotates? Not sure which way to go with this part.

    EDIT: The above was made in a rush, hope it makes sense. I ask only because your project is an example of the type of physics-driven movement not many are doing. The rotation in my gif is how it used to work in my old game, and it'd be a nice thing to fix
    Last edited by HateDread; 07-11-2015, 05:31 AM.

    Leave a comment:


  • replied
    Not solved yet, currently working on a Radar system before coming back to this... needed a break The code above is part of a pretty basic PawnMovementComponent of my own, though honestly what I've done could just be done as part of the Pawn right now. I just wasn't sure how tarted up it was going to get, especially when it comes to pathing and prediction etc.

    You're pretty much right, the Replicated Movement and Client simulation are fighting each other, which is why I get the latency from the controls. Other than that though, it all works. The trick is that the Physics function is being called on tick both Client & Server side, so that keeps them from going out of sync since velocity and angular velocity are always being updated. I also handle damping and drag in there as well, so when a collision happens, the drag affects the calculation on both ends and causes position/rotation updates to be sent out from the server, causing them to remain in sync. If I switch off the movement simulation and a collision occurs client-side, they stay out of sync until the server sends a position update.

    I really want to look more into CMC's system, since I want to implement based-movement (e.g., moving with the object I'm hovering on) and imparted velocity. This is still just the beginning Any progress I make though, I'll post here in one form or another!

    Unfortunately since Unreal doesn't use deterministic / seeded physics, I have to use replicated movement or otherwise I just risk client-side collisions not being handled the same way.

    Leave a comment:


  • replied
    Hey TheJamesh, thanks for sharing that! I'm looking at getting back to my 6DOF movement stuff (the old way was all Client-authoritative and only worked on LAN).

    Before I get into your code in the morning, I had a few quick questions. I apologise if you've explained this (it's late!), but are you using a Character? I wasn't sure if you were replacing the default CharacterMovementComponent or just adding one to a Pawn. The latter definitely makes more sense though.

    Additionally; how can you be replicating movement with the default checkbox, yet have your system at the same time? Are they not at odds?

    Thanks again for the code. Did you manage to solve the problems you were talking about?

    EDIT:

    piinecone, did I ever explain the time sync stuff to you? I can't remember if we talked about it at some stage.

    Leave a comment:


  • replied
    - Post Redacted - Some Content now NDA
    Last edited by TheJamsh; 09-19-2015, 09:07 AM.

    Leave a comment:


  • replied
    Originally posted by HateDread View Post
    Not sure on that either! Could work out well or be totally terrible. Do you have any idea how you'd sync a time value across the network? Think about the value you get from GetRealWorldSeconds(), and the fact that it'll differ on clients and server, so you could calculate an offset maybe an apply it? Maybe
    I still haven't had much time to implement this (or even think about it), but it occurred to me that I could send the client move timestamp with the move, and the server would return the same move's timestamp when it returned the result of the move to the client. Seems like it can all remain relative since the purpose is to ack the move request/response for correction - the client doesn't need to know what time it is on the server, just needs to know if the server disagrees and which move it's talking about. Think that would work? I'm hoping to find time to try it out in the next week or so.

    Leave a comment:


  • replied
    Glad to find this thread - I'm going to need to implement a vehicle 6DOF MovementComponent implementing INetworkPredictionInterface soon myself.

    I've implemented a basic velocity and acceleration based movement in Blueprint but of course found it isn't good enough for anything greater than local latency.

    @TheJamsh - would you be willing to share your Hovertank Movement Component code with us? I'd be happy to share any adaptation of it for 6DOF movement back with everyone.

    Leave a comment:


  • replied
    Originally posted by piinecone View Post
    Very cool. Do you then replay the client's inputs since the client move that was executed on the server and received by the owning client again (in the case of a disagreement)? If so, what does the replay look like? Are you ticking the component outside of the owning actor's `Tick()`, or just reapplying deltas?
    No not yet, because 'Replicated Movement' just sets the actors location anyway, and usually the discrepancy is so tiny or non-existent than the movement is fine. In latent situations though that probably won't be the case, so I'll need something a bit more robust for that.

    Originally posted by piinecone View Post
    Character movement uses clientside prediction + rewind/replay, so the server lets the owning client know when it disagrees with the results of a move so the client can rewind back to the move in question, correct it, and replay all the clientside moves since then. If the moves aren't replayed, you'll notice the client's simulation snapping back to the last one received from the server, which is of course movement from the past as far as the client is concerned.

    I noticed with the wheeled vehicles that the controls start to get a bit floaty as soon as some normal latency is involved. I'm planning to give the client control, but I'll have to sort out replaying physics states and acking timestamps between client and server (might be pestering you about that soon, @HateDread).
    Yeah this is something I'm probably going to have to do eventually, the issue I have is because the Physics System in Unreal isn't deterministic - there's so much room for error. I still want to keep my physics-based movement because it's so lightweight and fluid, but I may simply have to bite the bullet eventually and switch to something like CMC.

    Leave a comment:


  • replied
    Originally posted by piinecone View Post
    Of course! I am very curious about the timestamp acking. When I implemented the moves buffer for projectiles I just used a move count. Not sure if that's a horrible idea or not.
    Not sure on that either! Could work out well or be totally terrible. Do you have any idea how you'd sync a time value across the network? Think about the value you get from GetRealWorldSeconds(), and the fact that it'll differ on clients and server, so you could calculate an offset maybe an apply it? Maybe

    Leave a comment:


  • replied
    Originally posted by HateDread View Post
    Thanks for the mentions, piincone

    I actually didn't get too deep into this stuff; we ended up switching to LAN-only, and I basically implemented Valve's buffer interpolation method, however to do so you need a nice synchronized timestamp system that works regardless of ping, so if you have trouble with that just let me know!

    I'm also happy to answer anything that I can. This stuff is tough at times, and I'm not envious of you guys trying to get wheeled vehicles to work! So, good luck
    Of course! I am very curious about the timestamp acking. When I implemented the moves buffer for projectiles I just used a move count. Not sure if that's a horrible idea or not.

    Leave a comment:

Working...
X