Facepunch / sbox-issues

175 stars 12 forks source link

Moving Keyframed entities with multiple bones after switching to-and-from Dynamic does not move them visually #3384

Closed CarsonKompon closed 9 months ago

CarsonKompon commented 1 year ago

Describe the bug

If you create a Prop (or presumably any ModelEntity on the server-side) that has multiple bones, then use SetupPhysicsFromModel() to set the entity to PhysicsMotionType.Dynamic and then back to PhysicsMotionType.Keyframed, the entity will be in a very weird state.

Attempting to reposition the entity in this state will change it's position (presumably on the server-side) but visually the prop will not move to that position until you set it back to PhysicsMotionType.Dynamic.

The attached video shows/explains everything in much more detail.

To Reproduce

  1. Spawn a Keyframed Prop/ModelEntity that is a ragdoll or has multiple bones

    Prop prop = new Prop()
    {
    Position = position,
    Rotation = rotation,
    Scale = scale,
    Transmit = TransmitType.Always
    };
    prop.SetModel("models/citizen/citizen.vmdl");
    prop.SetupPhysicsFromModel(PhysicsMotionType.Keyframed);
  2. Set the prop to PhysicsMotionType.Dynamic and then back to PhysicsMotionType.Keyframed. In the video I link above I do this via a ConCmd.Server that allows the client to toggle between Dynamic and Keyframed like such:

    
    [ConVar.Server("home_set_placeable_physics")]
    public static void SetPlaceablePhysics(int networkIdent, bool enabled)
    {
      // Find the entity
      Entity entity = Entity.FindByIndex(networkIdent);
      if(entity is not ModelEntity model) return;
    
      model.SetupPhysicsFromModel(enabled ? PhysicsMotionType.Dynamic : PhysicsMotionType.Keyframed);

}


3. Now that the prop is Keyframed, try to set it's position. In my video this is also done through a Convar.Server like so:
```cs
[ConCmd.Server("home_try_move")]
public static void TryMove()
{
      // Check the player
      if(ConsoleSystem.Caller.Pawn is not HomePlayer player) return;
      if(player.MovingEntity == null) return;

      // Move the entity      
      player.MovingEntity.Position = player.PlacingPosition;
      player.MovingEntity.Rotation = player.PlacingRotation;
}
  1. Looking at the entity via the Inspector, you'll find that the position has indeed changed, but you'll also notice that the prop itself did not move visually. The collisions and logic will continue as if they are in the new location, but the prop will be stuck in it's old position until you set the prop back to PhysicsMotionType.Dynamic via a similar (or the same) method to step 2. Doing so will also instantly position the prop where it should have been visually if you had moved it while in the weird state.

Expected behavior

I expect that the prop should be moved properly when set back to Keyframed, but this could also be an unintended side-effect of props with multiple bones, as making the root entity Keyframed may be "freezing" each bone, causing the bones to stay in that position but the entity itself to be re-positioned (this is just my best guess as to what is happening since the problem doesn't arise with normal models)

Media/Files

https://github.com/sboxgame/issues/assets/5159369/076f1c46-92f4-4ce6-b722-b015c87a9329

Uncompressed Video: https://www.youtube.com/watch?v=CmfEFfcmYNk

Additional context

No response

CarsonKompon commented 9 months ago

rip entities 🎉