MeshSlicer.cs

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.

Native Interop
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();
		}
	}
}