CCCPaste

Непонятный код, но может поможет1

using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(Collider))]
public class SteeringEnemyAI : MonoBehaviour
{
[Header("Target")]
[Tooltip("Трансформ игрока")]
public Transform player;

[Header("Steering Settings")]
public float maxSpeed = 3f;
public float maxForce = 15f;
public float arrivalRadius = 1f;

[Header("Boids Settings")]
[Tooltip("Минимальное расстояние до соседей")]
public float separationRadius = 1.5f;
public float separationStrength = 7f;
[Range(0f, 1f)] public float cohesionWeight = 0.5f;
[Range(0f, 1f)] public float alignmentWeight = 0.5f;

[Header("Obstacle Avoidance")]
public float avoidDistance = 2f;
public float avoidStrength = 10f;
public LayerMask obstacleMask;

[Header("Rotation")]
public float angularSpeed = 10f;

// Все враги в сцене
private static List<SteeringEnemyAI> allEnemies = new List<SteeringEnemyAI>();

private Rigidbody rb;

// Текущий и целевой множители скорости (Frost-эффект)
[HideInInspector] public float frostMultiplier = 1f;
private float targetMultiplier = 1f;
private float smoothVelocity;

// Слой до заморозки и слой во время Frost
private int originalLayer;
private int frostedLayer;

private void Awake()
{
rb = GetComponent<Rigidbody>();
allEnemies.Add(this);

// Запомним, на каком слое был враг изначально,
// и найдём индекс слоя "EnemyFrosted"
originalLayer = gameObject.layer;
frostedLayer = LayerMask.NameToLayer("EnemyFrosted");
if (frostedLayer < 0)
Debug.LogWarning("Слой EnemyFrosted не найден! Создайте его в настройках Unity.");
}

private void OnDestroy()
{
allEnemies.Remove(this);
}

private void FixedUpdate()
{
if (player == null) return;

// Плавно приближаем frostMultiplier к targetMultiplier
frostMultiplier = Mathf.SmoothDamp(
frostMultiplier,
targetMultiplier,
ref smoothVelocity,
0.3f
);

// Если полностью заморожены — не добавляем никаких сил
if (frostMultiplier <= 1e-4f)
return;

// ----- Steering AI как раньше, за вычетом ручного сброса скорости -----

// 1) Движение к игроку
Vector3 toTarget = player.position - transform.position;
float dist = toTarget.magnitude;
Vector3 desired = toTarget.normalized * maxSpeed * frostMultiplier;
if (dist < arrivalRadius)
desired *= dist / arrivalRadius;

// 2) Boids-силы: Separation, Cohesion, Alignment
Vector3 sepForce = Vector3.zero, cohForce = Vector3.zero, aliForce = Vector3.zero;
int count = 0;
float sepRad2 = separationRadius * separationRadius;

foreach (var other in allEnemies)
{
if (other == this) continue;
Vector3 diff = transform.position - other.transform.position;
float d2 = diff.sqrMagnitude;
if (d2 < sepRad2 && d2 > 0.001f)
{
sepForce += diff.normalized / d2;
count++;
}
}

if (count > 0)
{
sepForce = sepForce.normalized * separationStrength * frostMultiplier;

Vector3 center = Vector3.zero;
foreach (var other in allEnemies)
{
if (other == this) continue;
if ((other.transform.position - transform.position).sqrMagnitude < sepRad2)
center += other.transform.position;
}
center /= count;
cohForce = (center - transform.position).normalized
* separationStrength * cohesionWeight * frostMultiplier;

Vector3 avgVel = Vector3.zero;
foreach (var other in allEnemies)
{
if (other == this) continue;
if ((other.transform.position - transform.position).sqrMagnitude < sepRad2)
avgVel += other.rb.velocity;
}
avgVel /= count;
aliForce = (avgVel.normalized * maxSpeed * frostMultiplier - rb.velocity)
* alignmentWeight * frostMultiplier;
}

// 3) Obstacle Avoidance
Vector3 avoidForce = Vector3.zero;
Vector3 forward = rb.velocity.sqrMagnitude > 0.01f
? rb.velocity.normalized
: transform.forward;
if (Physics.Raycast(transform.position, forward, out RaycastHit hit,
avoidDistance, obstacleMask))
{
avoidForce = Vector3.Cross(hit.normal, Vector3.up).normalized
* avoidStrength * frostMultiplier;
}

// 4) Собираем итоговую силу и применяем
Vector3 steer = desired + sepForce + cohForce + aliForce + avoidForce - rb.velocity;
steer = Vector3.ClampMagnitude(steer, maxForce * frostMultiplier);
rb.AddForce(steer, ForceMode.Acceleration);

// 5) Ограничиваем максимальную скорость
Vector3 horiz = new Vector3(rb.velocity.x, 0f, rb.velocity.z);
if (horiz.magnitude > maxSpeed * frostMultiplier)
{
horiz = horiz.normalized * maxSpeed * frostMultiplier;
rb.velocity = new Vector3(horiz.x, rb.velocity.y, horiz.z);
}

// 6) Лёгкий перенос – при заморозке силой Frost враг медленнее гасят внешние толчки
rb.drag = Mathf.Lerp(0f, 5f, 1f - frostMultiplier);
}

/// <summary>
/// Устанавливает целевой множитель скорости (0…1) и переключает слой,
/// чтобы замороженный враг больше не сталкивался с другими врагами,
/// но мог сталкиваться с игроком.
/// </summary>
public void SetMultiplier(float m)
{
targetMultiplier = Mathf.Clamp01(m);
smoothVelocity = 0f;
frostMultiplier = targetMultiplier;

// Один раз обнуляем скорость при полной заморозке:
if (frostMultiplier <= 1e-4f)
{
Vector3 v = rb.velocity;
rb.velocity = new Vector3(0f, v.y, 0f);
}

// Переключаем игровой слой объекта и всех его потомков
int layerTo = frostMultiplier < 1f - 1e-4f
? frostedLayer
: originalLayer;
SetLayerRecursively(transform, layerTo);
}

// Рекурсивно задаём слой объекту и всем потомкам
private void SetLayerRecursively(Transform t, int layer)
{
t.gameObject.layer = layer;
foreach (Transform child in t)
SetLayerRecursively(child, layer);
}
}