Prop Component: Procedural Components, Damage System, Gib Spawning, and DamageInfo Patterns
Prop Component: Procedural Physics, Gibs, Damage, and Network Patterns
The Prop component is a high-level s&box component that automatically creates ModelRenderer, ModelCollider, and Rigidbody components based on the assigned model. These are "procedural" components — they are not saved to disk and are recreated on enable.
How Procedural Components Work
Prop maintains a ProceduralComponents list (marked [Property, Hide]). When enabled (and not a proxy), it calls ClearProcedurals() then UpdateComponents() to recreate the renderer and physics components. These components have ComponentFlags.NotSaved behavior — they are not serialized.// Prop automatically creates these based on the model:
// - ModelRenderer or SkinnedModelRenderer (if model has bones)
// - ModelCollider (static or dynamic)
// - Rigidbody (if model has single physics part)
// - ModelPhysics (if model has multiple physics parts = ragdoll)Damage System
Prop implements Component.IDamageable:[Sync] public float Health { get; set; }
[Sync] public bool IsOnFire { get; protected set; }
[Sync] public GameObject LastAttacker { get; set; }
public void OnDamage( in DamageInfo damage )
{
LastAttacker = damage.Attacker;
if ( IsProxy ) return; // only owner processes damage
Health -= damage.Damage;
if ( Health <= 0 ) Kill();
}Key pattern: if ( IsProxy ) return — only the owner/host processes damage. The Health property is [Sync] so all clients see the current health.
Gib Spawning Pattern
[Rpc.Broadcast( NetFlags.OwnerOnly )]
public void NetworkCreateGibs()
{
CreateGibs();
}Gibs are spawned via [Rpc.Broadcast( NetFlags.OwnerOnly )] — only the owner can trigger this, but it runs on all clients. Client-only gibs (debris) are tagged "debris", "clientside" and not network-spawned.
DamageInfo
DamageInfo is a class (not struct) so it can be subclassed for custom damage types:var damage = new DamageInfo( 50f, attackerGo, weaponGo )
{
Position = hitPosition,
Origin = shooterEyePos,
Shape = hitShape,
Hitbox = hitbox
};
damage.Tags.Add( "bullet" );
// Apply to a component implementing IDamageable
target.Components.Get<Component.IDamageable>()?.OnDamage( damage );Explosion Pattern
When a prop breaks and is explosive, it clones an explosion prefab and configures it via RunEvent:
go.RunEvent<RadiusDamage>( x =>
{
x.Radius = radius;
x.DamageAmount = damage;
x.Attacker = LastAttacker;
x.DamageTags?.Add( "explosion" );
}, FindMode.EverythingInSelfAndDescendants );This is a common s&box pattern: clone a prefab, configure components via RunEvent, then enable and network-spawn it.