PDA

View Full Version : Spawning the same thing on server and client..



Crusha K. Rool
10-19-2010, 08:39 AM
I worked through the Weapon code to see if I could find some inspiration on this problem, but nothing came along my way.

My goal is to offer the LD the possibility to spawn a KActor when the UltimateDestroyableEnvironment took enough damage. In order to do that, I created a custom subclass of the Karmathing (a KActor that replicates it's movement to the client, see here (http://wiki.beyondunreal.com/UE2:KarmaThing) for code) that is bStatic = False and bNoDelete = False.
Then I want to spawn it in the TakeDamage()-function of the UDE (which is bNoDelete=True btw, so all mapper-defined variables should be known on the client), which I declared simulated:


simulated function TakeDamage( int NDamage, Pawn instigatedBy, Vector hitlocation,
Vector momentum, class<DamageType> damageType)
{
[…]

// Spawn KActors
for (j = 0; j < LevelOfDestruction[i].KarmaDeco.Length; j++)
{
if (LevelOfDestruction[i].KarmaDeco[j].KActorStaticMesh != None)
{
SpawnedKActor = Spawn(class'DynamicSpawnableKarmaThing', self,,
Location + LevelOfDestruction[i].KarmaDeco[j].SpawnOffset,
Rotation + LevelOfDestruction[i].KarmaDeco[j].RotationOffset);
if (SpawnedKActor != None)
{
SpawnedKActor.LifeSpan = LevelOfDestruction[i].KarmaDeco[j].KActorLifeSpan;
SpawnedKActor.SetStaticMesh(LevelOfDestruction[i].KarmaDeco[j].KActorStaticMesh);
SpawnedKActor.MaxNetUpdateInterval = Max(LevelOfDestruction[i].KarmaDeco[j].KActorMaxNetUpdateInterval, 0.25);
}
}
}
}

// ================================================== ==========================
// GainedChild
//
// This is the only place where we can assign our custom KParam as KParam of
// the spawned KActor before the Karma physics are initilizing.
// ================================================== ==========================

simulated function GainedChild(Actor Other)
{
if (DynamicSpawnableKarmaThing(Other) != None)
{
DynamicSpawnableKarmaThing(Other).KParams = LevelOfDestruction[i].KarmaDeco[j].KActorParameters;
}
}


Works all fine in offline play, but nothing is spawned online (and it doesn't feel like it's spawned on the server as well because I have no invisible collision anywhere). I imagine it pretty hard to spawn exactly the same object on server and client, but it needed to be done this way in order to keep the things synced, I guess.
Any ideas?

Ok, maybe I need to do something with PostNetReceive and some bools that get replicated in order to spawn it on the client, but that doesn't solve the sync problem, does it?

meowcat
10-19-2010, 11:43 PM
TakeDamage is only ever called on the server (because in general the code calculating and dealing damage, whether from an instant hit trace or "foreach RadiusActor" check is only performed on the server's copy of the actors). Declaring a function simulated only permits it to be executed on a client's copy of the actor, it does not automatically replicate it.

Also, spawning an actor on the server is typically all that is needed (it will automatically be "spawned" on the client if its RemotRole does not equal ROLE_None). There is no need to (or way to) separately spawn the exact same object. You would only ever want to spawn the object clientside if it were only going to be a clientside only effect/thing.

I'd recommend adding some logging statements to make sure that it is being spawned on the server. Is there anything in the log file (Ut2004.log or Server.log) that indicates the object is being spawned and the destroyed?

Wormbo
10-20-2010, 03:16 AM
Very true. In fact, TakeDamage must be ignored clientsidely except for non-authoritative effects related to clientside-only actors. Particularly applying momentum or rotation on a client will either bring the actor out of sync with the server's copy or will soon be overridden by the server via replication, which looks bad.