Component that breaks a GameObject into debris fragments. Applies structural stress damage, spawns a number of fragment GameObjects with model, collider and rigidbody, gives them randomized position/rotation/velocity, then destroys the original and removes fragments after a delay.
using Sandbox;
using System;
using System.Collections.Generic;
public sealed class MeshSlicer : Component
{
[Property] public bool BreakOnImpact { get; set; } = true;
[Property] public float MinBreakVelocity { get; set; } = 300f;
[Property] public int FragmentCount { get; set; } = 6;
[Property] public Model DebrisModel { get; set; }
public void SliceOrBreak( Vector3 point, Vector3 forceDirection )
{
var stress = Components.Get<StructuralStress>();
if ( stress.IsValid() )
{
stress.ApplyStressDamage( 50f );
}
// Создаем импульсные куски при разрушении
for ( int i = 0; i < FragmentCount; i++ )
{
CreateFragment( point, forceDirection );
}
GameObject.Destroy();
}
private void CreateFragment( Vector3 point, Vector3 forceDirection )
{
var fragment = new GameObject( true, $"fragment_{Game.Random.Int( 100, 999 )}" );
fragment.Transform.Position = point + Vector3.Random * 15f;
fragment.Transform.Rotation = Rotation.Random;
fragment.Transform.Scale = Transform.Scale * Game.Random.Float( 0.2f, 0.5f );
var mr = fragment.Components.Create<ModelRenderer>();
if ( DebrisModel != null )
{
mr.Model = DebrisModel;
}
var rb = fragment.Components.Create<Rigidbody>();
var collider = fragment.Components.Create<BoxCollider>();
// Выталкиваем фрагмент
Vector3 explodeForce = (forceDirection.Normal + Vector3.Random * 0.8f) * Game.Random.Float( 200f, 500f );
rb.PhysicsBody.Velocity = explodeForce;
// Запускаем удаление осколка через задержку
DestroyAfterDelay( fragment, 4f );
}
private async void DestroyAfterDelay( GameObject target, float seconds )
{
await Task.DelaySeconds( seconds );
if ( target.IsValid() )
{
target.Destroy();
}
}
}