I want to have a ragdoll animation replicated over the network.
I implemented a state to achieve that.
Now, there are various problems that I so far failed to fix:
If a client causes the ragdoll for another client (a server function is being called for that),
it can see the ragdoll happening, but only when it was looking at the ragdolling pawn.
If the pawn is not visible in the view, it just freezes in the ragdoll animation.
I assume it is somehow related to the relevancy/rendering.
Same situation: Sometimes the ragdoll animation is skipped and the pawn lays on the ground as
if the ragdoll animation happened.. just that it didn't.. or that it was so fast that I couldn't see it.
I am testing with several clients and a listening server.
The server never shows any ragdoll animation. I have absolutely no idea why.
This is the relevant code:
Code:class DBPawn extends UTPawn; // Set in BeginState of state KnockedOut, used to tell other clients that this pawn is knockedout var repnotify bool bIsKnockedOut; // Called only if (Role == ROLE_Authority) simulated function reduceHealth(int amount) { if(bProtected) return; //TakeDamage(amount, kicker, Vect(0,0,0), Health = Max(0, Health-amount); // Tell server about shake, needed to let charge fail playHitEffect(); bSwitchHitEffect = !bSwitchHitEffect; // Shake the client //clientCamShake(); if(Health <= 0) { clientknockout(); GotoState('KnockedOut'); } } reliable client function ClientKnockOut() { GotoState('KnockedOut'); } state KnockedOut { simulated event BeginState(name PreviousStateName) { if ( Role >= Role_AutonomousProxy ) PlayerController(Controller).bIgnoreMoveInput = 1; bAlwaysRelevant=true; bUpdateSimulatedPosition = true; bNetDirty = true;; bSkipAttachedMoves = false; bIsKnockedOut = true; EnableRagdoll(); } simulated event EndKnockout ( ) { bIsKnockedOut = false; GotoState('auto'); } simulated event EndState(name NextStateName) { bIsKnockedOut = false; bAlwaysRelevant= false; if ( Role >= Role_AutonomousProxy ) PlayerController(Controller).bIgnoreMoveInput = 0; DisableRagdoll(); } simulated event Tick(float deltatime) { health = Min(100000, health + DeltaTime*1000); if (health >= 5500) gotoState('auto'); } simulated function bool CalcCamera( float fDeltaTime, out vector out_CamLoc, out rotator out_CamRot, out float out_FOV ) { local vector LookAt, x,y,z, ragdoll_pos; local rotator ragdoll_rot; /* out_CamRot = QuatToRotator(Mesh.GetBoneQuaternion('b_head')); GetAxes(out_CamRot,x,y,z); out_CamLoc = Mesh.GetBoneLocation('b_head') + z*10; */ CalcThirdPersonCam(fDeltaTime, out_CamLoc, out_CamRot, out_FOV); return true; } simulated function EnableRagdoll() { local int i; `log("Ragdoll: Role: "@Role); Mesh.MinDistFactorForKinematicUpdate = 0; //Mesh.SetTickGroup(TG_PostAsyncWork); // ensure that the physics sub system instances the physics asset for this skeletal mesh. `log("Hasphysics asset: "@Mesh.bHasPhysicsAssetInstance); // Change collision component to skeletal mesh CollisionComponent = Mesh; // Disable cylinder collision CylinderComponent.SetActorCollision(false, false); // ensures that the actor's location and rotation matches the root body's location and rotation SetPhysics(PHYS_RigidBody); // ensures that physics is blended in Mesh.PhysicsWeight = 1.0; Mesh.bEnableFullAnimWeightBodies = true; for(i=0; i<Mesh.PhysicsAsset.BodySetup.Length; i++) { Mesh.PhysicsAsset.BodySetup[i].bAlwaysFullAnimWeight = true; Mesh.PhysicsAsset.BodySetup[i].bfixed = false; } // Unfix the rigid body instance so it is dynamic Mesh.PhysicsAssetInstance.SetAllBodiesFixed(false); // Set collision channel for Mesh so it doesn't fall through the world Mesh.SetRBChannel(RBCC_Pawn); Mesh.SetRBCollidesWithChannel(RBCC_Default, true); // Ignore animation updates Mesh.bUpdateKinematicBonesFromAnimation=FALSE; // Update the skeleton even when we are not looking at it Mesh.bUpdateSkelWhenNotRendered = true; Mesh.bIgnoreControllersWhenNotRendered = false; Mesh.bTickAnimNodesWhenNotRendered = true; // Sync RigidBody location with mesh collation Mesh.bSyncActorLocationToRootRigidBody = true; // Force update the skel Mesh.ForceSkelUpdate(); SetMeshVisibility(true); if (Mesh.bNotUpdatingKinematicDueToDistance) { Mesh.UpdateRBBonesFromSpaceBases(true, true); } // Disable collision with other actors SetCollision(false, false, false); // Set Velocity at the sceletal mesh Mesh.SetRBLinearVelocity(Velocity, false); // Wake the rigid body Mesh.WakeRigidBody(); } simulated function disableRagdoll ( ) { Mesh.SetTickGroup(TG_PreAsyncWork); // Enable collision SetCollision(true, true, false); // Enable cylinder collision CylinderComponent.SetActorCollision(true, true); // Change collision component to cylinder CollisionComponent = CylinderComponent; // ensures that the actor's location and rotation matches the root body's location and rotation SetPhysics(PHYS_Falling); // Animation updates Mesh.bUpdateKinematicBonesFromAnimation=true; // Don't update when we are not looking at it Mesh.bUpdateSkelWhenNotRendered = false; Mesh.bIgnoreControllersWhenNotRendered = true; Mesh.bTickAnimNodesWhenNotRendered = false; // Don't Sync RigidBody location with mesh collation Mesh.bSyncActorLocationToRootRigidBody = false; // ensures that physics is blended in Mesh.PhysicsWeight = 0.0; Mesh.bEnableFullAnimWeightBodies = false; // Force update the skel Mesh.ForceSkelUpdate(); SetMeshVisibility(false); } } simulated event ReplicatedEvent(name VarName) { `log("Replication: " @ VarName); switch(VarName) { case 'bIsKnockedOut': if (bIsKnockedOut) GotoState('KnockedOut'); else GotoState('auto'); break; default: Super.ReplicatedEvent(VarName); break; } } replication { if ( bNetDirty && Role == ROLE_Authority && RemoteRole == ROLE_SimulatedProxy ) bIsKnockedOut; }



Reply With Quote



Bookmarks