Event Systems in Unity3D
- Tutorial
Good day!
Today I would like to briefly describe the use of events to get rid of garbage and provide complex and dynamic functionality to the code. It should be noted that this article is focused more on beginners who want to learn more about event systems.
We will analyze this whole thing on the example of a sound management system. This system will allow us to enable / disable music and sounds in the game settings.
Before we create a class manager that manages sound and music settings, we will create a simple serializable class. It will be used as a data model for saving to JSON.
Now you can start writing a class manager. We will install it on the very first stage. This manager will be a global object and will not be deleted when going from scene to scene.
Now that the manager is ready, you can create an empty object on your starting scene and name it, for example "_AUDIO_MANAGER" , and then add our class manager to it. You can do this simply by calling the component's add-on menu on the object and selecting “Game Managers” => “Audio Manager” .
After that, we need to write a component that we will dock to each object with an AudioSource.
In this way we can control the sounds / music in the game. This example does not in any way tell how to do it correctly, but only demonstrates the work of the system of events and listeners in Unity3D.
And finally, I want to talk about what we have used now. In the example below, a delegate was declared from which the listener was created:
You can set the listener to perform under certain conditions and cling to them certain methods that will be executed when these conditions are reached.
And with the help of delegates, on the basis of which we created a listener, you can create callback functions. This can be especially useful for asynchronous methods (for example, when sending asynchronous POST requests).
I hope you will benefit from my little experience in this matter and you can apply this example to your projects. Also I will be happy to answer your questions (if someone does not understand something).
Today I would like to briefly describe the use of events to get rid of garbage and provide complex and dynamic functionality to the code. It should be noted that this article is focused more on beginners who want to learn more about event systems.
We will analyze this whole thing on the example of a sound management system. This system will allow us to enable / disable music and sounds in the game settings.
Before we create a class manager that manages sound and music settings, we will create a simple serializable class. It will be used as a data model for saving to JSON.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//=============================================// AudioSettingsModel// @usage model for audio settings//// Developed by CodeBits Interactive// https://cdbits.net///=============================================
[System.Serializable]
publicclassAudioSettingsModel
{
publicbool music = true; // Флаг, отвечающий за музыкуpublicbool sounds = true; // Флаг, отвечающий за звуки
}
Now you can start writing a class manager. We will install it on the very first stage. This manager will be a global object and will not be deleted when going from scene to scene.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
//=============================================// Audio Manager// @usage works with audio settings//// Developed by CodeBits Interactive// https://cdbits.net///=============================================
[AddComponentMenu("Game Managers/Audio Manager")]
publicclassAudioManager : MonoBehaviour{
// Публичные параметрыpublicstatic AudioManager instance = null; // Инстанс менеджераpublicstatic AudioSettingsModel settings = null; // Модель аудио настроекprivatestaticstring _settings_path = ""; // Путь к файлу настроек аудио// Инициализация менеджераvoidAwake(){
// Устанавливаем путь для сохранения настроек
_settings_path = Application.persistentDataPath + "/audioSettings.gdf";
// Проверяем, задан ли инстанс нашего менеджераif (instance == null){ // Инстанс не задан
instance = this; // Установить в инстанс текущий объект
}
// Устанавливаем параметр, который указывает на то,// что данный объект не должен удаляться при выгрузке// уровня
DontDestroyOnLoad(gameObject);
// Инициализируем настройки нашего менеджера
InitializeSettings();
}
// Инициализация менеджераprivatevoidInitializeSettings(){
// Если модель настроек не заданаif (settings == null) settings = new AudioSettingsModel(); // Создаем новую модельif (File.Exists(_settings_path)){ // Если существует файл с настройками
loadSettings(); // Загружаем файл настроек звука
}
}
// Загрузить аудио настройкиpublicvoidloadSettings(){
string _data = File.ReadAllText(_settings_path); // Считываем весь текст из файла
settings = JsonUtility.FromJson<AudioSettingsModel>(_data); // Десериализуем его в текущую модель
}
// Сохранить аудио настройкиpublicvoidsaveSettings(){
string _json_data = JsonUtility.ToJson(settings); // Сериализуем текущие настройки из модели
File.WriteAllText(_settings_path, _json_data); // Сохраняем в наш файл
}
// Создаем делегаты для нашего события, которое в дальнейшем// будет использоваться для отслеживания изменений настроек аудиоpublicdelegatevoidAudioSettingsChanged(); // Добавить новый делегатpublicevent AudioSettingsChanged OnAudioSettingsChanged; // Создать на его основе событие// Включить/выключить звукиpublicvoidtoggleSounds(bool enabled){
settings.sounds = enabled; // Изменить настройки звуков в текущей модели
saveSettings(_settings_path, settings); // Сохранить настройкиif (OnAudioSettingsChanged != null) OnAudioSettingsChanged(); // Вызвать наше событие
}
// Включить/выключить музыкуpublicvoidtoggleMusic(bool enabled){
settings.music = enabled; // Изменить настройки музыки в текущей модели
saveSettings(_settings_path, settings); // Сохранить настройкиif (OnAudioSettingsChanged != null) OnAudioSettingsChanged(); // Вызвать наше событие
}
}
Now that the manager is ready, you can create an empty object on your starting scene and name it, for example "_AUDIO_MANAGER" , and then add our class manager to it. You can do this simply by calling the component's add-on menu on the object and selecting “Game Managers” => “Audio Manager” .
After that, we need to write a component that we will dock to each object with an AudioSource.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//=============================================// Audio Muter// @usage on/off audio sources on objects//// Developed by CodeBits Interactive// https://cdbits.net///=============================================
[AddComponentMenu("Audio/Audio Muter Component")]
publicclassAudioMuter : MonoBehaviour {
// Публичные параметры компонентаpublicbool is_music = false; // Данный флаг дает понять нашему классу, является ли AudioSource звуком или музыкой.// Приватные параметрыprivate AudioSource _as; // AudioSourceprivatefloat _base_volume = 1F; // Базовая громкость AudioSource// Инициализация объектаvoidStart(){
// Получаем компонент AudioSource и его изначальную громкость
_as = this.gameObject.GetComponent<AudioSource>(); // Получить компонент
_base_volume = _as.volume; // Получить базовую громкость// Здесь мы добавляем слушатель, который будет выполнять метод _audioSettingsChanged,// когда настройки музыки/звуков были изменены
AudioManager.instance.OnAudioSettingsChanged += _audioSettingsChanged; // Установить// Ну и на старте мы должны проверить текущее состояние звуков/музыки
_audioSettingsChanged();
}
// При уничтожении объектаvoidOnDestroy(){
AudioManager.instance.OnAudioSettingsChanged -= _audioSettingsChanged; // Уничтожаем слушатель
}
// Данный метод служит для включения/отключения громкости AudioSourceprivatevoid _audioSettingsChanged(){
if (is_music)
_as.volume = (AudioManager.settings.music) ? _base_volume : 0F;
if (!is_music)
_as.volume = (AudioManager.settings.sounds) ? _base_volume : 0F;
}
}
In this way we can control the sounds / music in the game. This example does not in any way tell how to do it correctly, but only demonstrates the work of the system of events and listeners in Unity3D.
And finally, I want to talk about what we have used now. In the example below, a delegate was declared from which the listener was created:
publicdelegatevoidAudioSettingsChanged();
publicevent AudioSettingsChanged OnAudioSettingsChanged;
You can set the listener to perform under certain conditions and cling to them certain methods that will be executed when these conditions are reached.
And with the help of delegates, on the basis of which we created a listener, you can create callback functions. This can be especially useful for asynchronous methods (for example, when sending asynchronous POST requests).
I hope you will benefit from my little experience in this matter and you can apply this example to your projects. Also I will be happy to answer your questions (if someone does not understand something).