#Mover Crouching Capsule Half Height

1 messages · Page 1 of 1 (latest)

old lark
#

The "SmoothingMode" is probably not connected. I don't know of any Documentation. A customer of mine is using Mover for a year now and I had to alter it a lot to add feature, solve bugs and generally improve existing things. That includes the NetworkPredictionPlugin as a backend.

I don't know if you are using this for Multiplayer. I've been steering people away from Mover for a while now, because, as you say, it's experimental.
If you are good with C++ and you can alter Mover and NPP, then you can freely work with it and patch it up. That takes additional development time of course.
If you can't use C++ or you are a beginner, I would suggest you fall back to the CMC still, especially if you are using it for a Multiplayer game.

#

If you are using NPP as the backend (idk if the Standalone one is fully functional, I never used that), then I can tell you why you experience that issue.
Especially if you are using the FixedTick mode fwiw.
For SimProxies (so other Actors that local player sees, like a different player's Pawn), it gets the full state replicated every once in a while.
The SimProxy logic then interpolates between the current and the new state over time.
This happens in via the FMoverSyncState (and in theory AuxState), which has a Collection of Structs.
Each of those Structs implements said Interpolate logic. Most of the data can be interpolate (like Transforms, Floats, etc.) but there are also properties that are set directly (like booleans, enums, etc.).

By default, you are using the FMoverDefaultSyncState, which houses the Transform of the Player (or rather just the Location and Rotation (Orientation)).
The FMoverDefaultSyncState interpolates that (+- some teleporting when being too far away).

For FixedTick, Mover should have Smoothing by now. That is used to smooth the visual state between 2 FixedTicks, so that the Local Player doesn't see a stopmotion movie.
While the way the data is set is different, it also uses the Interpolate function on those Structs inside the Collection.
That means, naturally, whenever you move in FixedTick, or whenever you see another player, the Transform will be Interpolated.
If you switch stance to crouch, the resulting change in Location will be Interpolated.

#

I don't know how Epic is doing it atm, but in theory there is only one option, that is to set the Location during the Simulation to what is the expected new location with the smaller height.
Otherwise, you'd actually start falling, which I don't think Mover's implementation does. Why would you start falling? Just imaging in real live that in an instant you would pull your legs upwards.
There is clearing below you now, so you would fall. So mover should "pull your legs up", but also instantly move you downwards to the floor.

It's important to note that the Simulation and the Interpolation can differ. So while the Simulation lowers the CapsuleHalfHeight and instantly moves the pawn to be on the floor with the botto of the capusle, the actual Interpolation (also called PresentationState) doesn't have to instantly follow. If it would, you'd see the player teleporting.

#

Now, since the Location is interpolated, you'd see the body slowing moving downwards over time. The problem that you are facing comes from the CapsuleHalfHeight not being Interpolated.
The CapsuleHalfHeight is instantly changed to the new value.

#

Let's imagine the Simulation happens every 4th EngineFrame, so you have 3 GameFrames (+ the initial one) in which you interpolate before the next SimFrame happens.

Assuming we start in a SimFrame X, where we are still standing:

  • SimFrame X (EngineFrame 101)
    • Stance: Standing
    • CapsuleHalfHeight: 50
    • Location.Z: 50 (assuming the floor is exactly at Z = 0, for simpler math)

And the player now wants to crouch (not listing the GameFrames between the SimFrames as they aren't relevant for X to X+1):

  • SimFrame X+1 (EngineFrame 104)
    • Stance: Crouch
    • CapsuleHalfHeight: 35
    • Location.Z: 35

The these are the GameFrames between SimFrame X+1 and X+2, during which we interpolate from X to X+1 (always one frame behind):

  • GameFrame Y (EngineFrame 104)
    • Stance: Crouch (can't interpolate an Enum, so it's directly the target of the interpolation)
    • CapsuleHalfHeight: 35 (this property doesn't even live in the SyncState of NPP, so this won't be interpolated, it is instantly 35 on the Component)
    • Location.Z: 50 (assuming we have really stable FPS etc. just to make math easier, we interpolate over 4 frames towards 35, starting at 50)
  • GameFrame Y+1 (EngineFrame 105)
    • CapsuleHalfHeight: 50
    • Location.Z: 45
  • GameFrame Y+2 (EngineFrame 106)
    • CapsuleHalfHeight: 50
    • Location.Z: 40
  • GameFrame Y+3 (EngineFrame 107)
    • CapsuleHalfHeight: 50
    • Location.Z: 35

And then the next SimFrame happens.

  • SimFrame X+2 (EngineFrame 108)
    • Stance: Crouch
    • CapsuleHalfHeight: 35
    • Location.Z: 35
#

So how does one fix this? We fixed it by having a CapsuleHalfHeight property in the SyncState, so that we can interpolate it the same way the Location.Z is interpolated.

turbid dome
#

Hey eXi! I really appreciate the write* up! I didn't want to tag you cause I didn't know if it was late or not (it is over here!) and as it was quite figured you'd see it when you saw it, if you had time! Again, I am going to read over this, digest it and try to sort it. I sincerely appreciate the education/feedback and time on writing this up! I'm not sure I have any more juice in me to go tonight, it's 5AM, but I will try this tomorrow when I get around and i'll ping this thread with hopefully I'll follow up with a success; but either way, I'll post and let you know what happens!

As I read through, just some notes to respond to your feedback! (Mainly to rubber ducky; again I'd hate to waste your time after you've already gave me lots of info!)

  • using the single player variant of the backend, no multiplayer, I read it was probably worth experimenting with Mover /if/ doing so with single player; I don't remember where!
  • I am using the "independent" ticker, because I read somewhere (maybe it was readme for Mover, to give that a try)
  • re: teleport, yeah, I was digging around the source code and they actually invoke a teleport command post capsule adjustment (see screenshot)
  • I am a lifer engineer, but not in C++; but as I'm a newbie with UE, (4~months), I was looking to sort of educate on what the upcoming standards are (despite CMC having long time support as epic mentioned), I thought it would be cool to be a little brave, and use it to also acclimate myself with the plugin ecosystem, C++, and so on. It's a bit bumpy, but I am enjoying the ride! As I am doing single player, I think i'll try to stick it out a bit more until such time it becomes too silly to continue (and then maybe I'll just go work on something else, and see if epic releases anything in the upcoming year or so; I have lots of areas I need to educate on 😹 )
turbid dome
#

Hey @old lark, when you say you fixed it by having CapsuleHalfHeight property in the SyncState, how did you manage this? I get the idea of adding the property and even lerping (in the interpolate method, probably?), but I wasn't clear on the best way to add to/change the sync state. Did you extend the plugin itself? I looked for an api within mover to add a new sync handler (or add to) but it seems they've hard coded definitions of the MoverDefaultSyncState. I am sure I'm just being ignorant here, again, pretty new to the whole ecosystem in general, but thought I'd ask how you accomplished this.

The closest thing I found was adding a Persistent Sync State Date Type, but this isn't what I want, from what I can tell.

If this is going too deep into the woods, feel free to disregard; again I'm definitely a bit out of depth here, so I wouldn't be surprised if I'm just missing the very obvious. At any rate, I said I'd follow up, ^_^

old lark
#

We heavily modified the Plugin, yes. But for this you wouldn't necessarily. The FMoverSyncState has a Collection of Structs that inherit from the same Base Struct that the FMoverDefaultSyncState inherits from. You can make your own child struct and add it to said collection within a given MoverModes OnSimulationTick function (or whatever the name was).

#

The only problem is that you'd need to replace the whole existing setup for WalkingMode and the stuff they do to set the CapsuleHalfHeight.

#

You'd need to do that within FinalizeFrame of the MoverComponent instead.

#

It's not a small change fwiw.

turbid dome
#

Ah, affirmative. I appreciate the follow up and I'll probably tinker a bit more and then maybe move on to trying a very basic motion matching setup, rather then try to sort this; I figure eventually someone will come out with something remediating this or at the very least an example I can learn from rather then beat head against ^_^

Thanks again for all the insight/help, hope you have a great upcoming week!