Как исправить код, связанный с маной?

Помогите, пожалуйста, найти и исправить ошибки в следующем Unity C#-скрипте Mana. Скрипт должен: хранить текущую и максимальную ману, корректно увеличивать и уменьшать её через методы, вызывать событие при изменении маны (с передачей текущего значения) и вызывать событие смерти при мане <= 0. Ниже — исходный код:
  • 17 июня 2026 г. 10:01
Ответы на вопрос 2
Вы не прислали исходный код, поэтому ниже — проверенный шаблон рабочего скрипта и разбор типичных ошибок + варианты реализации (через C#-события и через UnityEvent для инспектора). Вставьте ваш код, если хотите, чтобы я поправил конкретно его.

1) Верный и простой вариант (C# events — удобно подписываться из кода):

```csharp
using System;
using UnityEngine;

public class Mana : MonoBehaviour
{
    [SerializeField, Min(0f)]
    private float maxMana = 100f;

    [SerializeField, Min(0f)]
    private float currentMana = 100f;

    // публичные события для подписки из кода
    public event Action<float> OnManaChanged;
    public event Action OnDied;

    // защищаем от многократного вызова смерти
    private bool isDead;

    public float CurrentMana => currentMana;
    public float MaxMana => maxMana;

    private void Awake()
    {
        // Корректируем начальные значения
        currentMana = Mathf.Clamp(currentMana, 0f, maxMana);
        isDead = currentMana <= 0f;
    }

    // Установить ману напрямую (вызывать событие при изменении и проверять смерть)
    public void SetMana(float value)
    {
        float newVal = Mathf.Clamp(value, 0f, maxMana);
        if (!Mathf.Approximately(newVal, currentMana))
        {
            currentMana = newVal;
            OnManaChanged?.Invoke(currentMana);
        }

        if (currentMana <= 0f && !isDead)
        {
            isDead = true;
            OnDied?.Invoke();
        }
    }

    // Добавить ману (можно использовать отрицательное значение для уменьшения)
    public void AddMana(float amount)
    {
        if (Mathf.Approximately(amount, 0f)) return;
        SetMana(currentMana + amount);
    }

    // Потратить ману (удобное имя)
    public void SpendMana(float amount)
    {
        if (amount <= 0f) return;
        SetMana(currentMana - amount);
    }

    // Изменить максимум маны; опционально сохранить долю текущей маны
    public void ChangeMaxMana(float newMax, bool keepRatio = true)
    {
        newMax = Mathf.Max(0f, newMax);
        if (Mathf.Approximately(newMax, maxMana)) return;

        if (keepRatio)
        {
            float ratio = (maxMana > 0f) ? currentMana / maxMana : 1f;
            maxMana = newMax;
            SetMana(maxMana * ratio);
        }
        else
        {
            maxMana = newMax;
            SetMana(currentMana); // просто зафиксировать в новых рамках
        }
    }
}
```

2) Вариант с UnityEvent (если нужно назначать слушатели в инспекторе):
```csharp
using UnityEngine;
using UnityEngine.Events;

[Serializable] public class FloatEvent : UnityEvent<float> {}

public class Mana : MonoBehaviour
{
    [SerializeField, Min(0f)] private float maxMana = 100f;
    [SerializeField, Min(0f)] private float currentMana = 100f;

    [SerializeField] private FloatEvent onManaChanged;
    [SerializeField] private UnityEvent onDied;

    private bool isDead;

    public float CurrentMana => currentMana;
    public float MaxMana => maxMana;

    private void Awake()
    {
        currentMana = Mathf.Clamp(currentMana, 0f, maxMana);
        isDead = currentMana <= 0f;
    }

    public void SetMana(float value)
    {
        float newVal = Mathf.Clamp(value, 0f, maxMana);
        if (!Mathf.Approximately(newVal, currentMana))
        {
            currentMana = newVal;
            onManaChanged?.Invoke(currentMana);
        }

        if (currentMana <= 0f && !isDead)
        {
            isDead = true;
            onDied?.Invoke();
        }
    }

    public void AddMana(float amount) => SetMana(currentMana + amount);
    public void SpendMana(float amount) { if (amount > 0f) SetMana(currentMana - amount); }
}
```

3) Типичные ошибки и как их исправить
- Не клэмпить значение mаны (Mathf.Clamp) — может уйти в отрицательное или превысить максимум.
- Вызывать событие до обновления значения или не передавать актуальное значение.
- Не проверять null при вызове события — используйте OnChanged?.Invoke(...) или проверку на null.
- Вызывать событие смерти многократно — заведите флаг isDead, чтобы вызвать OnDied только один раз.
- Неправильно настроенные типы событий (например, UnityEvent без generic не принимает float).
- Использование целого типа (int) когда нужны дробные значения — решите заранее float или int.
- Забыл инициализировать currentMana в Awake/Start и не привести его к диапазону [0, max].

4) Как подписаться (пример)
- Через код (C# events):
  mana.OnManaChanged += value => healthBar.SetValue(value);
  mana.OnDied += () => Die();

- Через инспектор (UnityEvent version): добавить слушателей в поле onManaChanged / onDied.

Если пришлёте ваш исходный скрипт, я укажу конкретные строки с ошибками и предложу правки прямо в вашем коде.
после <code>public float Mana</code> не должно быть `;` — это свойство, не поле: <code>public float Mana {</code> <br/> <br/> плюс: <code>UnityEvent ManaChaged</code> не принимает аргументы, нужен <code>UnityEvent&amp;lt;float&amp;gt;</code> ; параметр <code>spent</code> , не <code>Spent</code> (C# чувствителен к регистру); в <code>AddMana(float _Mana)</code> параметр затеняет поле — переименуй в <code>amount</code> и пиши <code>Mana += amount</code> (через свойство, иначе события не сработают)
Похожие вопросы