# Is it ok to initialize an RB_ConstraintActor in PostBeginPlay?

I have a KActorSpawnable subclass that acts weird. In PostBeginPlay, I initialize an RB_ConstraintActor; the default is not to allow rotation. If I create one in the editor, it's fine, and won't rotate. If I spawn one, it rotates.

Here's the class:

class QuadForceKActor extends KActorSpawnable
placeable;

var(Behavior) bool bConstrainRotation;
var(Behavior) bool bConstrainX;
var(Behavior) bool bConstrainY;
var(Behavior) bool bConstrainZ;

var RB_ConstraintActor PhysicsConstraintActor;

simulated event PostBeginPlay()
{
Super.PostBeginPlay();

PhysicsConstraintActor = Spawn(class'RB_ConstraintActorSpawnable', self, '', Location, rot(0, 0, 0));
if(bConstrainRotation)
{
PhysicsConstraintActor.ConstraintSetup.bSwingLimited = true;
PhysicsConstraintActor.ConstraintSetup.bTwistLimited = true;
}
SetLinearConstraints(bConstrainX, bConstrainY, bConstrainZ);

PhysicsConstraintActor.InitConstraint(self, None);
}

function SetLinearConstraints(bool InConstrainX, bool InConstrainY, bool InConstrainZ)
{
if(InConstrainX)
{
PhysicsConstraintActor.ConstraintSetup.LinearXSetup.bLimited = 1;
}
else
{
PhysicsConstraintActor.ConstraintSetup.LinearXSetup.bLimited = 0;
}
if(InConstrainY)
{
PhysicsConstraintActor.ConstraintSetup.LinearYSetup.bLimited = 1;
}
else
{
PhysicsConstraintActor.ConstraintSetup.LinearYSetup.bLimited = 0;
}
if(InConstrainZ)
{
PhysicsConstraintActor.ConstraintSetup.LinearZSetup.bLimited = 1;
}
else
{
PhysicsConstraintActor.ConstraintSetup.LinearZSetup.bLimited = 0;
}
}

DefaultProperties
{
bConstrainRotation=true
bConstrainX=false
bConstrainY=false
bConstrainZ=false

bSafeBaseIfAsleep=false
bNoEncroachCheck=false
}


Here's the code I use to spawn one. It's a subclass of the one above, but it doesn't reference the constraint at all.

local QuadForceKCreateBlock BlockActor;

BlockActor = spawn(class'QuadForceKCreateBlock', none, 'PowerCreate_Block', BlockLocation(), m_PreparedRotation, , false);
BlockActor.SetDuration(m_BlockDuration);
BlockActor.StaticMeshComponent.SetNotifyRigidBodyCollision(true);
BlockActor.StaticMeshComponent.ScriptRigidBodyCollisionThreshold = 0.001;

BlockActor.StaticMeshComponent.SetStaticMesh(m_ValidCreationBlock.StaticMesh);


I used to initialize an RB_ConstraintActor where I spawned it from the outside. This worked, which is why I'm pretty sure it has nothing to do with the other code in QuadForceKCreateBlock.

I then added the internal constraint in QuadForceKActor for other purposes. When I realized I had two constraints on the CreateBlock doing the same thing, I removed the constraint code from the place where I spawn it. Then it started rotating.

Is there a reason I should not be initializing an RB_ConstraintActor in PostBeginPlay? I feel like there's some basic thing about how the engine works that I'm missing.

EDIT: I found roughly the same initialize code in Whizzle, the Psyonix game made purely with UDK for which the source is available: http://developer.download.nvidia.com/udk/Whizzle_Creation_Document_1_2.pdf

EDIT 2: The constraints are intialized by PostBeginPlay when loading the level, and that works for the placed objects. Just not for spawned objects.

This line

BlockActor.StaticMeshComponent.SetStaticMesh(m_ValidCreationBlock.StaticMesh);


Invalidates the constraint. Doing

BlockActor.StaticMeshComponent.SetStaticMesh(m_ValidCreationBlock.StaticMesh);
BlockActor.PhysicsConstraintActor.InitConstraint(BlockActor, none);


Fixes the issue.

I'm not sure of the order that things happen with KActors. It's possible that by PostBeginPlay() the KActor's physics haven't been fully initialized yet. As a test, you could try delaying creation of the constraint until the next Tick.

Alternatively, instead of spawning constraints you could try creating them in the defaultproperties section of your KActor. See UTVehicle_Hoverboard and its Content subclass for an example.

• I will try messing with that. But I found almost exactly the same initialization in Psyonix's Whizzle source code. – Almo Nov 9 '12 at 19:09
• The Hoverboard initializes its constraints in PostInitRigidBody. I tried putting that function into my class, and it doesn't get called. – Almo Nov 9 '12 at 19:19