- Created AdvancedLoggingExample class demonstrating composite and file loggers - Implemented multi-file logging setup with separate error and full logs - Added game event and performance logging methods - Included key input handling for log operations (flush, clear) - Setup proper resource disposal on application quit
285 lines
10 KiB
Markdown
285 lines
10 KiB
Markdown
# Система логирования для 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/<Username>/AppData/LocalLow/<CompanyName>/<ProductName>/game.log`
|
||
- **macOS**: `~/Library/Application Support/<CompanyName>/<ProductName>/game.log`
|
||
- **Linux**: `~/.config/unity3d/<CompanyName>/<ProductName>/game.log`
|
||
- **Android**: `/storage/emulated/0/Android/data/<PackageName>/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 <filename>: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[])` - удалить несколько логгеров
|
||
|
||
## Лицензия
|
||
Свободное использование в ваших проектах.
|
||
|