StickyTarZone.cs

A trigger zone component that simulates a sticky tar area. It tints model renderers of objects that enter, restores tint on exit, and slows physics rigidbodies and character controllers while inside.

Native Interop
using Sandbox;
using System.Collections.Generic;

public sealed class StickyTarZone : Component, Component.ITriggerListener
{
    [Property] public float SpeedMultiplier { get; set; } = 0.4f; 
    [Property] public float RigidbodyDrag { get; set; } = 0.85f;  
    [Property] public Color TarTint { get; set; } = new Color( 0.1f, 0.1f, 0.1f, 1f ); 

    private readonly HashSet<GameObject> _insideObjects = new();
    private readonly Dictionary<ModelRenderer, Color> _originalColors = new();

    public void OnTriggerEnter( Collider other )
    {
        if ( !other.GameObject.IsValid() ) return;

        var rootObj = other.GameObject.Root;
        _insideObjects.Add( rootObj );

        
        var renderers = rootObj.Components.GetAll<ModelRenderer>();
        foreach ( var mr in renderers )
        {
            if ( mr.IsValid() && !_originalColors.ContainsKey( mr ) )
            {
                _originalColors[mr] = mr.Tint;
                mr.Tint = TarTint;
            }
        }
    }

    public void OnTriggerExit( Collider other )
    {
        if ( !other.GameObject.IsValid() ) return;

        var rootObj = other.GameObject.Root;
        _insideObjects.Remove( rootObj );

        
        var renderers = rootObj.Components.GetAll<ModelRenderer>();
        foreach ( var mr in renderers )
        {
            if ( mr.IsValid() && _originalColors.TryGetValue( mr, out var origColor ) )
            {
                mr.Tint = origColor;
                _originalColors.Remove( mr );
            }
        }
    }

    protected override void OnFixedUpdate()
    {
        
        _insideObjects.RemoveWhere( obj => !obj.IsValid() );

        foreach ( var targetObj in _insideObjects )
        {
            
            var rb = targetObj.Components.Get<Rigidbody>();
            if ( rb.IsValid() && rb.PhysicsBody.IsValid() )
                {
                    rb.PhysicsBody.Velocity *= 0.5f; // Замедление в смоле
                }

            
            var cc = targetObj.Components.Get<CharacterController>();
            if ( cc.IsValid() )
            {
                cc.Velocity *= SpeedMultiplier;
            }
        }
    }
}