How to best implement character physics in the style of Black & White?

Godot Version

4.2

Question

For those of you who know the classic god game Black & White, I am essentially trying to implement a system in which the player can pick up and throw villagers around, as well as have villagers react to other objects being thrown at them. I researched a few approaches but couldn’t get a satisfying result yet. The approaches I can come up with are:

  1. Make villagers inherit from CharacterBody3D and implement any kind of physics responses to being thrown or getting hit myself. I haven’t tried this as I imagine it to be quite involved and cumbersome to implement a faux physics system and get a good looking result.

  2. Make villagers inherit from RigidBody3D set to frozen in kinematic mode when they are just moving around normally and implement my own version of move_and_slide. This way I could make proper use of the physics system that is already in place when throwing villagers around. However, I don’t know if there are any substantial performance costs to having potentially hundreds of rigid bodies running around, even if most of them are frozen most of the time.

  3. I could utilize the ragdoll system by making the villagers CharacterBodies with PhysicalBones. However, in my initial tests I noticed that the CharacterBody3D root node does not actually get translated when throwing a villager. Rather, it’s the PhysicalBones themselves that move relative to the root node and the villager’s mesh moves with them because it is skinned to the bones. When I disable the physics simulation after the villager reaches a resting position, its mesh gets reset to where the CharacterBody root node is. I tried moving the root node to where the mesh ended up after throwing it, but that sometimes leads to the villager’s collision shape intersecting with the terrain and the villager getting flung into the stratosphere as the physics system tries to resolve it.

  4. Finally, if I decide to bite the bullet and go deep, I could try implementing my own RigidCharacterBody3D in C++ as a child of PhysicsBody3D, essentially taking the parts I need from CharacterBody3D and RigidBody3D and combining them.

I’m curious if any of you tried something similar before, see any approaches I am not seeing, or have any opinions on the approaches above. The second approach using RigidBodies frozen in kinematic mode seems the most cost and time effective at the moment, so I’ll try that next and see how it scales to hundreds of villagers.

Just saw in the source code that a CharacterBody3D is actually initialized as a PhysicsBody3D in kinematic mode here, so there shouldn’t really be any performance cost compared to a frozen RigidBody3D in kinematic mode if I’m not mistaken.