Hi folks,
Does anyone have any tips / ideas for optimising rag doll performance on IOs?
I'm trying to get my game to 30fps on all 4th gen devices and I'm struggling a little with the IPod 4.
------
On a side note I get random crashes on IOs 5 (normally when loading a new level / bringing up the keyboard) but on IOs 4 my game works fine, I'm not getting anything in logs which is odd. I'm compiling from August 2011 if that makes any difference? Not seen many folks getting IOs 5 issues so I might be doing something daft...
I've put a sample pawn file with the physics code toward the bottom if it helps.
Many thanks for your time and help
Regards
Greg
Does anyone have any tips / ideas for optimising rag doll performance on IOs?
I'm trying to get my game to 30fps on all 4th gen devices and I'm struggling a little with the IPod 4.
------
On a side note I get random crashes on IOs 5 (normally when loading a new level / bringing up the keyboard) but on IOs 4 my game works fine, I'm not getting anything in logs which is odd. I'm compiling from August 2011 if that makes any difference? Not seen many folks getting IOs 5 issues so I might be doing something daft...
I've put a sample pawn file with the physics code toward the bottom if it helps.
Many thanks for your time and help
Regards
Greg
Code:
class RaptorPawn extends SimplePawn; var Pawn P2; var SoundCue BOOM; var ParticleSystem Eggsplosion; var bool bumped; var SoundCue raptordeath; var(NPC) SkeletalMeshComponent NPCMesh; var(NPC) class<RaptorAIController> NPCController; //extra animnodes var AnimNodeSlot CustomAnimNodeSlot; simulated event PostBeginPlay() { if(NPCController != none) { //set the existing ControllerClass to our new NPCController class ControllerClass = NPCController; } super.PostBeginPlay(); } simulated function tick(float DeltaTime) { super.Tick(DeltaTime); LockY(); } event TickSpecial( float DeltaTime ) { } function LockY() { local Vector NewLoc; NewLoc = Location; if(Location.Y != 32) { NewLoc.Y = 32; SetLocation(NewLoc); } } //find the neck animations need to set these up in the animtree editor simulated event PostInitAnimTree(skeletalMeshComponent SkelComp) { CustomAnimNodeSlot = AnimNodeSlot(Mesh.FindAnimNode('RaptorClaws')); } function JumpOffPawn(); function bool Dodge(eDoubleClickDir DoubleClickMove); function vector BotDodge(Vector Dir); function bool PerformDodge(eDoubleClickDir DoubleClickMove, vector Dir, vector Cross); function DoDoubleJump( bool bUpdating ); function bool DoJump( bool bUpdating ); //Remove feigndeath exec simulated function FeignDeath(); //Override dropped weapons function ThrowWeaponOnDeath(); simulated function TakeFallingDamage(); event StuckOnPawn(Pawn OtherPawn); event bool EncroachingOn(Actor Other) { return false; } event EncroachedBy(Actor Other); function CrushedBy(Pawn OtherPawn); simulated function SpawnGibs(vector HitLocation) { WorldInfo.MyEmitterPool.SpawnEmitter(ParticleSystem'KismetGame_Assets.Effects.P_BloodSplat_01', HitLocation, rotator(vect(0,0,1)), ); } State Dying { ignores Bump, HitWall, HeadVolumeChange, PhysicsVolumeChange, Falling, BreathTimer, FellOutOfWorld; simulated function PlayWeaponSwitch(Weapon OldWeapon, Weapon NewWeapon) {} simulated function PlayNextAnimation() {} singular event BaseChange() {} event Landed(vector HitNormal, Actor FloorActor) {} function bool Died(Controller Killer, class<DamageType> damageType, vector HitLocation); simulated singular event OutsideWorldBounds() { Destroy(); } Begin: //`Log("is in dying state"); SetDyingPhysics(); SetCollision(true, false); // the 2.0 = the time before the rag doll is removed... Sleep(2.0); PlayDyingSound(); Destroy(); } event TakeDamage(int Damage, Controller InstigatedBy, vector HitLocation, vector Momentum, class<DamageType> DamageType, optional TraceHitInfo HitInfo, optional Actor DamageCauser) { local int actualDamage; local PlayerController PC; local Controller Killer; if ( (Role < ROLE_Authority) || (Health <= 0) ) { return; } // just set this to the original damage type don't care about special ones in Dino Dude DamageType = class'DamageType'; Damage = Max(Damage, 0); if (Physics == PHYS_None && DrivenVehicle == None) { SetMovementPhysics(); } if (Physics == PHYS_Walking && damageType.default.bExtraMomentumZ) { momentum.Z = FMax(momentum.Z, 0.4 * VSize(momentum)); } momentum = momentum/Mass; ActualDamage = Damage; WorldInfo.Game.ReduceDamage(ActualDamage, self, instigatedBy, HitLocation, Momentum, DamageType, DamageCauser); AdjustDamage(ActualDamage, Momentum, instigatedBy, HitLocation, DamageType, HitInfo, DamageCauser); // call Actor's version to handle any SeqEvent_TakeDamage for scripting Super.TakeDamage(ActualDamage, InstigatedBy, HitLocation, Momentum, DamageType, HitInfo, DamageCauser); Health -= actualDamage; if (HitLocation == vect(0,0,0)) { HitLocation = Location; } // draw some particles on hit location SpawnGibs( HitLocation); if ( Health <= 0 ) { //`Log("take death less than or equal to 0"); PC = PlayerController(Controller); // play force feedback for death if (PC != None) { PC.ClientPlayForceFeedbackWaveform(damageType.default.KilledFFWaveform); } // pawn died Killer = SetKillInstigator(InstigatedBy, DamageType); TearOffMomentum = momentum; Died(Killer, damageType, HitLocation); } else { HandleMomentum( momentum, HitLocation, DamageType, HitInfo ); } PlayHit(actualDamage,InstigatedBy, hitLocation, damageType, Momentum, HitInfo); MakeNoise(1.0); } function bool Died(Controller Killer, class<DamageType> DamageType, vector HitLocation) { //`Log("gone through died bool"); // ensure a valid damagetype damageType = class'DamageType'; Health = Min(0, Health); // notify the gameinfo of the death if ( Controller != None ) { WorldInfo.Game.Killed(Killer, Controller, self, damageType); } // notify inventory manager if ( InvManager != None ) { InvManager.OwnerDied(); } // push the corpse upward (@fixme - somebody please remove this?) Velocity.Z *= 2.3; PlayDying(DamageType, HitLocation); return TRUE; } simulated function PlayDying(class<DamageType> DamageType, vector HitLoc) { //`Log("playing dying effects like feigndeath"); PlayFeignDeath(); GotoState('Dying'); PlaySound(raptordeath); bReplicateMovement = false; bTearOff = true; Velocity += TearOffMomentum; SetDyingPhysics(); bPlayedDeath = true; } function SetDyingPhysics() { if( Physics != PHYS_RigidBody ) { SetPhysics(PHYS_Falling); } } simulated function SetPawnRBChannels(bool bRagdollMode) { if(bRagdollMode) { Mesh.SetRBChannel(RBCC_Pawn); Mesh.SetRBCollidesWithChannel(RBCC_Default,TRUE); Mesh.SetRBCollidesWithChannel(RBCC_Pawn,TRUE); Mesh.SetRBCollidesWithChannel(RBCC_Vehicle,TRUE); Mesh.SetRBCollidesWithChannel(RBCC_Untitled3,FALSE); Mesh.SetRBCollidesWithChannel(RBCC_BlockingVolume,TRUE); } else { Mesh.SetRBChannel(RBCC_Untitled3); Mesh.SetRBCollidesWithChannel(RBCC_Default,FALSE); Mesh.SetRBCollidesWithChannel(RBCC_Pawn,FALSE); Mesh.SetRBCollidesWithChannel(RBCC_Vehicle,FALSE); Mesh.SetRBCollidesWithChannel(RBCC_Untitled3,TRUE); Mesh.SetRBCollidesWithChannel(RBCC_BlockingVolume,FALSE); } } exec function PlayFeignDeath() { //local float BaseTranslationOffset; //GotoState('FeigningDeath'); //SetTimer(3.0, false, 'die'); //`Log("attempted feign death"); GotoState('Dying'); if(Mesh.PhysicsAssetInstance != None) { // if we had some other rigid body thing going on, cancel it if (Physics == PHYS_RigidBody) { //@note: Falling instead of None so Velocity/Acceleration don't get cleared setPhysics(PHYS_Falling); } // Ensure we are always updating kinematic Mesh.MinDistFactorForKinematicUpdate = 0.0; SetPawnRBChannels(TRUE); Mesh.ForceSkelUpdate(); // Move into post so that we are hitting physics from last frame, rather than animated from this Mesh.SetTickGroup(TG_PostAsyncWork); PreRagdollCollisionComponent = CollisionComponent; CollisionComponent = Mesh; // Turn collision on for skelmeshcomp and off for cylinder CylinderComponent.SetActorCollision(false, false); Mesh.SetActorCollision(true, true); Mesh.SetTraceBlocking(true, true); SetPhysics(PHYS_RigidBody); Mesh.PhysicsWeight = 1.0; // If we had stopped updating kinematic bodies on this character due to distance from camera, force an update of bones now. if( Mesh.bNotUpdatingKinematicDueToDistance ) { Mesh.UpdateRBBonesFromSpaceBases(TRUE, TRUE); } Mesh.PhysicsAssetInstance.SetAllBodiesFixed(FALSE); Mesh.bUpdateKinematicBonesFromAnimation=FALSE; // Set all kinematic bodies to the current root velocity, since they may not have been updated during normal animation // and therefore have zero derived velocity (this happens in 1st person camera mode). Mesh.SetRBLinearVelocity(Velocity, false); // reset mesh translation since adjustment code isn't executed on the server // but the ragdoll code uses the translation so we need them to match up for the // most accurate simulation //Mesh.SetTranslation(vect(0,0,1) * BaseTranslationOffset); // we'll use the rigid body collision to check for falling damage Mesh.ScriptRigidBodyCollisionThreshold = MaxFallSpeed; Mesh.SetNotifyRigidBodyCollision(true); Mesh.WakeRigidBody(); } } defaultproperties { NPCController=class'DinoDude.RaptorAIController' raptordeath=SoundCue'DinoSounds.Rex_Die_Cue' // set the bump for the raptoraicontroller bumped = false; Begin Object Class=DynamicLightEnvironmentComponent Name=MyLightEnvironment ModShadowFadeoutTime=0.25 MinTimeBetweenFullUpdates=0.2 AmbientGlow=(R=.01,G=.01,B=.01,A=1) AmbientShadowColor=(R=0.15,G=0.15,B=0.15) bSynthesizeSHLight=TRUE End Object Components.Add(MyLightEnvironment) Begin Object Class=SkeletalMeshComponent Name=PawnMesh CastShadow=true bCastDynamicShadow=false SkeletalMesh=SkeletalMesh'Raptor_Enemy.RaptorTest' AnimTreeTemplate=AnimTree'Raptor_Enemy.RaptorAnimTree' LightEnvironment=MyLightEnvironment AnimSets(0)=AnimSet'Raptor_Enemy.RaptorAnimSet' PhysicsAsset=PhysicsAsset'Raptor_Enemy.RaptorTest_Physics' HiddenGame=false BlockRigidBody=TRUE bHasPhysicsAssetInstance=true bUpdateSkelWhenNotRendered=False bTickAnimNodesWhenNotRendered=False bIgnoreControllersWhenNotRendered=True // commented out because not sure it does anything... //bUpdateKinematicBonesFromAnimation=true RBChannel=RBCC_Untitled3 RBCollideWithChannels=(Untitled3=true) RBDominanceGroup=20 End Object Mesh=PawnMesh Components.Add(PawnMesh) bcanpickupinventory=false Begin Object Name=CollisionCylinder CollisionRadius=85 CollisionHeight=150 Translation=(X=0.0,Y=0.0,Z=0.0) End Object CylinderComponent=CollisionCylinder //just some testing stuff, delete later GroundSpeed=800.000000 JumpZ=550.0 WalkableFloorZ=0.5 bCanCrouch=false bScriptTickSpecial = true MaxStepHeight=80.0 MaxJumpHeight=0.0 }
Comment