Какие методы MonoBehaviour вызываются при окончании жизненного цикла?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Методы MonoBehaviour, вызываемые при окончании жизненного цикла объекта в Unity
При уничтожении или завершении жизненного цикла игрового объекта в Unity вызывается последовательность методов, определенных в классе MonoBehaviour. Эти методы позволяют корректно освобождать ресурсы, выполнять завершающие действия и предотвращать ошибки. Основной метод уничтожения – Destroy(), но существуют также специализированные методы MonoBehaviour для реакции на это событие.
Основные методы завершения жизненного цикла
1. OnDestroy()
Это единственный метод MonoBehaviour, который вызывается автоматически при уничтожении объекта, непосредственно перед его фактическим удалением из памяти игры. Его вызов гарантируется при:
- Вызове метода
Destroy(gameObject)илиDestroy(this). - Удалении объекта, содержащего компонент (например, при уничтожении родительского GameObject).
- Завершении сцены, если объект не является постоянным (
persistent).
Пример использования OnDestroy():
public class ResourceManager : MonoBehaviour
{
private List<Texture2D> loadedTextures;
private void Start()
{
loadedTextures = new List<Texture2D>();
// Загрузка ресурсов...
}
private void OnDestroy()
{
// Критически важно освобождать созданные ресурсы
foreach (Texture2D texture in loadedTextures)
{
if (texture != null)
{
Destroy(texture); // Уничтожение созданных объектов Unity
}
}
loadedTextures.Clear();
// Отмена всех подписок на события
EventSystem.Instance.OnGameEvent -= HandleGameEvent;
Debug.Log($"ResourceManager {gameObject.name} уничтожен.");
}
}
Ключевые моменты для OnDestroy():
- Не вызывается при деактивации объекта (
gameObject.SetActive(false)). - Не гарантируется вызов при аварийном завершении приложения.
- Идеальное место для освобождения объектов Unity (текстуры, аудиоклипы), созданных через
Instantiate()илиnew, но не для обычных managed объектов C# (их сборщик мусора обработает автоматически).
2. OnApplicationQuit()
Этот метод вызывается на всех активных объектах перед завершением приложения. Он выполняется до OnDestroy() и полезен для сохранения данных, отправки финальной статистики на сервер или закрытия сетевых соединений.
public class GameSession : MonoBehaviour
{
private void OnApplicationQuit()
{
SavePlayerProgress();
Analytics.SendSessionEndEvent();
NetworkManager.CloseAllConnections(); // Закрытие сетевых ресурсов
}
}
Важные сопутствующие методы и принципы
Корректное освобождение ресурсов
При завершении жизненного цикла важно:
- Отписываться от событий (
-=). Не сделанная отписка может вызывать исключения или попытки обращения к уничтоженным объектам. - Останавливать Coroutines. Если корутина содержит ссылку на уничтоженный объект, это приведет к ошибкам.
private void OnDestroy()
{
StopAllCoroutines(); // Безопасная остановка всех корутин
}
Различия между Destroy() и OnDestroy()
Destroy(Object obj)– это статический метод классаUnityEngine.Object, который запланирует уничтожение объекта. Сам объект будет удален не сразу, обычно в конце текущего кадра.OnDestroy()– это виртуальный метод MonoBehaviour, который вызывается в процессе уничтожения объекта, как реакция на него.
Последовательность вызовов при завершении приложения
Для объектов, присутствующих в сцене при закрытии игры:
OnApplicationQuit()вызывается на всех активных MonoBehaviour.- Затем для каждого уничтожаемого объекта вызывается
OnDestroy(). - Объекты удаляются из памяти.
Дополнительный контекст: деактивация vs уничтожение
Важно понимать, что методы OnDisable() и OnEnable() относятся к деактивации/активации объекта (SetActive), а не к его жизненному циклу. Они не вызываются при уничтожении, если объект уже активен. Однако, если объект деактивирован перед уничтожением, последовательность может быть: OnDisable() -> OnDestroy().
Резюме
Для корректного завершения жизненного цикла компонента Unity разработчик должен:
- Использовать
OnDestroy()для освобождения всех созданных объектов Unity, отписки от событий и остановки корутин. - Использовать
OnApplicationQuit()для финальных операций при закрытии приложения. - Помнить, что эти методы не вызываются для объектов, уничтоженных при загрузке новой сцены (если они не являются частью постоянной системы), если только они не были явно уничтожены через
Destroy(). - Следить за циклами ссылок, где уничтоженный объект может оставаться в списках других объектов, что приводит к ошибкам
MissingReferenceException.