# Система логирования для Unity ## Обзор Система состоит из трёх компонентов: 1. **CompositeLogger** - композитный логгер, пересылающий сообщения на несколько логгеров 2. **FileLogger** - логгер для записи в файл 3. **LoggerInitializer** - компонент для автоматической инициализации ## Быстрый старт ### Вариант 1: Использование через LoggerInitializer (рекомендуется) 1. Создайте пустой GameObject на сцене 2. Прикрепите компонент `LoggerInitializer` 3. Настройте параметры в инспекторе: - **Enable File Logging** - включить запись в файл - **Custom Log Path** - путь к файлу (оставьте пустым для автоматического) - **Append To Existing Log** - добавлять к существующему файлу - **Clear Log On Start** - очищать файл при запуске 4. Запустите игру - все логи будут автоматически писаться в файл! ### Вариант 2: Ручная настройка в коде ```csharp using UnityEngine; public class MyGameManager : MonoBehaviour { private CompositeLogger compositeLogger; private FileLogger fileLogger; void Awake() { // Инициализация композитного логгера compositeLogger = new CompositeLogger(); compositeLogger.Initialize(); // Создание файлового логгера fileLogger = new FileLogger(); // Использует путь по умолчанию // или // fileLogger = new FileLogger("D:/MyGame/logs/game.log", append: true); // Добавление файлового логгера в композитный compositeLogger.AddLogger(fileLogger); // Теперь все логи через compositeLogger будут идти и в консоль, и в файл compositeLogger.Log("Игра запущена!"); compositeLogger.LogWarning("Test", "Тестовое предупреждение"); } void OnApplicationQuit() { fileLogger?.Dispose(); } } ``` ## Где находится файл лога? По умолчанию файл сохраняется в `Application.persistentDataPath/game.log`: - **Windows**: `C:/Users//AppData/LocalLow///game.log` - **macOS**: `~/Library/Application Support///game.log` - **Linux**: `~/.config/unity3d///game.log` - **Android**: `/storage/emulated/0/Android/data//files/game.log` Узнать точный путь можно через: ```csharp Debug.Log(Application.persistentDataPath); ``` ## Примеры использования ### Базовое логирование ```csharp // Через композитный логгер compositeLogger.Log("Простое сообщение"); compositeLogger.LogWarning("Tag", "Предупреждение"); compositeLogger.LogError("Tag", "Ошибка"); // Через стандартный Debug (если вы заменили Debug.unityLogger) Debug.Log("Это тоже пойдёт в файл"); ``` ### Логирование с контекстом ```csharp compositeLogger.Log(LogType.Log, "Игрок спавнится", playerGameObject); compositeLogger.LogWarning("AI", "Путь не найден", enemyGameObject); ``` ### Логирование исключений ```csharp try { // Опасный код } catch (Exception ex) { compositeLogger.LogException(ex); } ``` ### Форматированное логирование ```csharp compositeLogger.LogFormat(LogType.Log, "Игрок {0} имеет {1} очков здоровья", playerName, health); ``` ### Добавление нескольких логгеров ```csharp var fileLogger1 = new FileLogger("logs/debug.log"); var fileLogger2 = new FileLogger("logs/errors.log"); fileLogger2.filterLogType = LogType.Error; // Только ошибки compositeLogger.AddLoggers(fileLogger1, fileLogger2); ``` ## Настройка фильтрации ### На уровне FileLogger ```csharp fileLogger.filterLogType = LogType.Warning; // Логировать только Warning, Error, Exception fileLogger.logEnabled = false; // Временно отключить ``` ### Очистка файла лога ```csharp fileLogger.Clear(); // Очистить файл и записать новый заголовок ``` ### Принудительная запись на диск ```csharp fileLogger.Flush(); // Сбросить буфер на диск ``` ## Формат записи в файле ``` ================================================================================ Новая сессия логирования начата: 2025-11-07 14:30:15 Unity версия: 2022.3.5f1 Платформа: WindowsEditor Путь к логу: C:/Users/User/AppData/LocalLow/DefaultCompany/MyGame/game.log ================================================================================ [14:30:15.123] [INFO] Игра запущена! [14:30:16.456] [WARNING] [AI] Путь не найден [14:30:17.789] [ERROR] [Network] Соединение потеряно [14:30:18.012] [EXCEPTION] NullReferenceException: Object reference not set to an instance of an object StackTrace: at MyScript.MyMethod () [0x00000] in :0 ``` ## Важные замечания ### Потокобезопасность FileLogger потокобезопасен - использует `lock` для синхронизации записи. ### Производительность - `AutoFlush = true` гарантирует сохранность данных при крашах, но снижает производительность - Если нужна максимальная производительность, установите `AutoFlush = false` и вызывайте `Flush()` вручную ### Освобождение ресурсов **ВАЖНО:** Всегда вызывайте `Dispose()` при завершении работы: ```csharp void OnApplicationQuit() { fileLogger?.Dispose(); } ``` ### Ротация логов Для больших проектов можно реализовать ротацию: ```csharp string timestamp = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"); string logPath = $"logs/game_{timestamp}.log"; var fileLogger = new FileLogger(logPath, append: false); ``` ## Расширенные сценарии ### Отдельные логи для разных систем ```csharp // Общий лог var mainLogger = new FileLogger("logs/game.log"); // Лог только для сетевой подсистемы var networkLogger = new FileLogger("logs/network.log"); networkLogger.filterLogType = LogType.Log; // Лог только для ошибок var errorLogger = new FileLogger("logs/errors.log"); errorLogger.filterLogType = LogType.Error; compositeLogger.AddLoggers(mainLogger, networkLogger, errorLogger); ``` ### Условное логирование ```csharp #if UNITY_EDITOR // В редакторе не пишем в файл, только в консоль #else compositeLogger.AddLogger(new FileLogger()); #endif ``` ### Логирование с метками времени ```csharp public class TimestampLogger { private CompositeLogger logger; public void LogWithTimestamp(string message) { logger.Log($"[{Time.time:F2}s] {message}"); } } ``` ## Troubleshooting ### Файл не создаётся - Проверьте права доступа к папке - Проверьте путь через `Debug.Log(Application.persistentDataPath)` - Убедитесь, что вызвали `Initialize()` на CompositeLogger ### Логи не пишутся в файл - Убедитесь, что `logEnabled = true` - Проверьте `filterLogType` - возможно фильтр слишком строгий - Проверьте, что логгер добавлен через `AddLogger()` ### Файл заблокирован - Убедитесь, что вызвали `Dispose()` перед закрытием приложения - Закройте все программы, которые могут держать файл открытым ### Производительность низкая - Установите `AutoFlush = false` в конструкторе FileLogger - Вызывайте `Flush()` периодически (например, раз в секунду) - Используйте более строгий `filterLogType` ## API Reference ### FileLogger #### Конструктор ```csharp FileLogger(string filePath = null, bool append = true) ``` #### Свойства - `bool logEnabled` - включено ли логирование - `LogType filterLogType` - минимальный уровень логирования - `ILogHandler logHandler` - обработчик логов (для совместимости) #### Методы - `void Flush()` - принудительно сбросить буфер на диск - `void Clear()` - очистить файл лога - `void Dispose()` - закрыть файл и освободить ресурсы - `bool IsLogTypeAllowed(LogType)` - проверка фильтра ### CompositeLogger #### Методы управления - `void Initialize(ILogger additiveLogger = null)` - инициализация - `void AddLogger(ILogger)` - добавить логгер - `void AddLoggers(params ILogger[])` - добавить несколько логгеров - `void RemoveLogger(ILogger)` - удалить логгер - `void RemoveLoggers(params ILogger[])` - удалить несколько логгеров ## Лицензия Свободное использование в ваших проектах.