Announcement

Collapse
No announcement yet.

Modular character out of sync when using Copy Pose From Mesh with physics simulation on

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

    Modular character out of sync when using Copy Pose From Mesh with physics simulation on

    Hello and thank you for your attention. Sorry for the somewhat long post, but I want to provide all my fidings.

    I have a modular character creator which generates characters by combining several different parts. I'm synchronizing animations with Copy Pose From Mesh, with one part serving as the master part. The whole reason I decided to go with Copy Pose From Mesh is that it allows skeletons to be extended, and theoretically works with the physics engine. Unfortunately, when I activate physics simulation on all the parts, the children lag behind the master by what I assume to be one frame. There seems to be no fixing it other than disabling physics simulation.

    I tried moving all the slave parts to a tick group that runs after the physics engine using SetTickGroup() and it doesn't work. I tried forcing all the slave parts to tick after the master part with AddTickPrerequisiteComponent() and it also doesn't have any effect. What does work is disabling physics.

    After re-reading the documentation, it seems Copy Pose From Mesh does not work properly when physics simulation is enabled:

    Additionally, if you want to use physics on the child, you may want to use the Rigid Body or AnimDynamics skeletal control nodes instead.
    This suggests I should be able to enable physics on the master part at least, as long as the child parts are not simulating. Sure enough, with only the master simulating, everything seems synchronized provided I move all the children to a tick group that runs after the physics calculations. I assume this is because enabling physics forces components to tick only in the ETickingGroup::TG_DuringPhysics step, so if I enable physics on everything, everything gets thrown there and the order of execution is unknown, with children that run before the master copying the last frame's data.

    In conclusion, am I correct to assume there is no way to enable physics on all the parts at once if one needs things to remain in sync? If so, what is the recommended approach to applying physics to the children? The Rigid Body node?

    Thanks for your time.

    #2
    Hello!
    I'm fighting with exactly the same problem.
    As a workaround, what I could do is to make an AnimBP:
    Input Pose -> Local To Component -> RigidBody -> ComponentToLocal->Output Pose

    On the rigid body, I set the Simulation Space to World Space, and setup the overlap channel ( i have this on custom ). Then I set this animBP to my hair mesh as Post Process Anim Blueprint.
    This way even if the main body is physics controlled, the hair physics works.

    However, this "RigidBody" physics is really unrealiable. I have a lot of stretching, many joints ignored, etc. I dont like this method, but at least it works.

    If you find out how to get the normal simulated physics working, let me know!

    Comment


      #3
      Try master pose component.

      https://www.youtube.com/watch?v=bE0g_djR12s

      Seems to me the copy pose would lag as by the time the pose is copied from one to another the original pose has changed.
      Clarke's third law: Any sufficiently advanced technology is indistinguishable from magic.
      Custom Map Maker Discord
      https://discord.gg/t48GHkA
      Urban Terror https://www.urbanterror.info/home/

      Comment


        #4
        Master pose doesnt work if the slave does not have exactly the same bones as master.

        And somehow my physics works now? Here is what I did, not sure if all of these are needed, but it's working for now, so I don't want to play with it anymore :P

        In my character.cpp constructor:

        This is the skeleton mesh, coming from ACharacter
        Code:
            GetMesh()->VisibilityBasedAnimTickOption = EVisibilityBasedAnimTickOption::AlwaysTickPoseAndRefreshBones;
            GetMesh()->PrimaryComponentTick.TickGroup = TG_PrePhysics;
            GetMesh()->PrimaryComponentTick.EndTickGroup = TG_PrePhysics;
        This is my attached mesh component, still in constructor
        Code:
                USkeletalMeshComponent* Component = CreateDefaultSubobject< USkeletalMeshComponent >( g_CharacterBodyPartNames[ iBodyPart ] );
                Component->SetupAttachment( GetMesh() );
                Component->VisibilityBasedAnimTickOption = EVisibilityBasedAnimTickOption::OnlyTickPoseWhenRendered;
                Component->PrimaryComponentTick.TickGroup = TG_DuringPhysics;
                Component->PrimaryComponentTick.EndTickGroup = TG_PostPhysics;
                Component->PrimaryComponentTick.AddPrerequisite( GetMesh(), GetMesh()->PrimaryComponentTick );
                Component->SetCollisionProfileName( TEXT( "ClothPhysics" ) );
                Component->SetCollisionEnabled( ECollisionEnabled::NoCollision );
                Component->PhysicsTransformUpdateMode = EPhysicsTransformUpdateMode::ComponentTransformIsKinematic;
                Component->bApplyImpulseOnDamage = false;
                Component->bReplicatePhysicsToAutonomousProxy = false;
                Component->bUpdateOverlapsOnAnimationFinalize = false;
                Component->bEnablePhysicsOnDedicatedServer = false;
        This is the default, I change the collision and turn on physics on later, when I equip something and it has physics asset:
        Code:
            USkeletalMeshComponent* BodyPartComponent = GetBodyPartComponent( BodyPart );
            bool bUsingMasterPose = false;
        
            BodyPartComponent->SetSimulatePhysics( false );
            BodyPartComponent->SetCollisionEnabled( ECollisionEnabled::NoCollision );
        
            BodyPartComponent->SetSkeletalMesh( NewMesh, false );
        
            if( BodyPartComponent->GetPhysicsAsset() )
            {
                BodyPartComponent->SetCollisionEnabled( ECollisionEnabled::PhysicsOnly );
                BodyPartComponent->SetSimulatePhysics( true );
            }
        And it... works? No more lagging behind. Probably the TickGroup and EndTickGroup settings fixed it. "ClothPhysics" is just a collision profile I made so it does not collide with the pawn's capsule collider, and so on.
        Hope this helps

        Comment


          #5
          Nevermind, it doesn't work, just reduced the lag a little. At fast movement it still detaches and it makes me a very sand panda.

          Comment


            #6
            if you have a character with different skeletal meshes, I found the only way to get the anims work in sync is to disable and re-enable them (in my case horse + rider + bow) by NoSkeletonUpdate (set to true, use a short e.g. 0.1s Delay, then set to false).
            Last edited by sivan; 01-29-2020, 07:57 AM.
            Edge of Chaos RTS
            "Age of Total Heroes" - RTS Pathfinding and Movement System for UE4
            RTS Camera C++ Tutorial

            Comment

            Working...
            X