Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
- Добавил новую систему настроек, возможности:
- Динамически создает список настроек
- Сохраняет настройки в JSON-файл
- Возможность группировать настройки
- Широкие возможности по кастомизации
- Применение настроек в реальном времени (частично)
- Добавил префабы для новых элементов настроек
- Изменил поведение игры исходя из нового формата настроек
162 lines
5.9 KiB
C#
162 lines
5.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.Audio;
|
|
|
|
namespace RR.Common.Settings
|
|
{
|
|
public enum SettingValueType
|
|
{
|
|
Bool,
|
|
Int,
|
|
Float,
|
|
String,
|
|
Button, // Кнопка - не хранит значение, только вызывает действие
|
|
OptionPicker // Выбор из списка опций (enum-like)
|
|
}
|
|
|
|
// "Куда применять" — расширяется редко (не под каждую настройку)
|
|
public enum ApplyTarget
|
|
{
|
|
None,
|
|
|
|
// Audio
|
|
AudioMixerFloat01ToDb, // float 0..1 -> dB и в AudioMixer parameter
|
|
|
|
// Graphics / Performance
|
|
QualityLevel, // int -> QualitySettings.SetQualityLevel
|
|
VSync, // bool -> QualitySettings.vSyncCount
|
|
TargetFps, // int -> Application.targetFrameRate
|
|
Fullscreen, // bool -> Screen.fullScreen
|
|
FullscreenMode, // int 0..3 -> Screen.fullScreenMode
|
|
ResolutionIndex // int -> индекс в Screen.resolutions
|
|
}
|
|
|
|
[Serializable]
|
|
public struct SettingValue
|
|
{
|
|
public SettingValueType type;
|
|
public bool b;
|
|
public int i;
|
|
public float f;
|
|
public string s;
|
|
|
|
public static SettingValue Bool(bool v) => new() { type = SettingValueType.Bool, b = v };
|
|
public static SettingValue Int(int v) => new() { type = SettingValueType.Int, i = v };
|
|
public static SettingValue Float(float v) => new() { type = SettingValueType.Float, f = v };
|
|
public static SettingValue String(string v) => new() { type = SettingValueType.String, s = v };
|
|
}
|
|
|
|
[Serializable]
|
|
public class SettingEntry
|
|
{
|
|
public string key;
|
|
public string displayName;
|
|
[TextArea] public string description;
|
|
public string group = "General";
|
|
|
|
public SettingValueType valueType;
|
|
|
|
// Defaults
|
|
public bool defaultBool = true;
|
|
public int defaultInt = 0;
|
|
public float defaultFloat = 1f;
|
|
public string defaultString = "";
|
|
|
|
// Ranges (used for Int/Float)
|
|
public int minInt = 0;
|
|
public int maxInt = 10;
|
|
public float minFloat = 0f;
|
|
public float maxFloat = 1f;
|
|
|
|
public ApplyTarget applyTarget = ApplyTarget.None;
|
|
|
|
// AudioMixer params (used only for AudioMixerFloat01ToDb)
|
|
public AudioMixer mixer;
|
|
public string mixerParameter = "MasterVolumeDb";
|
|
public float minDb = -80f;
|
|
public float maxDb = 0f;
|
|
|
|
// Button params (для типа Button)
|
|
[Header("Button Settings")]
|
|
[Tooltip("Текст на кнопке (если не задан displayName)")]
|
|
public string buttonText;
|
|
|
|
[Tooltip("Дополнительные данные для кнопки (URL, имя сцены и т.д.)")]
|
|
public string buttonData;
|
|
|
|
[Tooltip("Цвет кнопки")]
|
|
public Color buttonColor = Color.white;
|
|
|
|
[Tooltip("Текстура/спрайт кнопки")]
|
|
public Sprite buttonSprite;
|
|
|
|
// OptionPicker params (для типа OptionPicker)
|
|
[Header("Option Picker Settings")]
|
|
[Tooltip("Список вариантов выбора")]
|
|
public List<string> options;
|
|
|
|
[Tooltip("Индекс варианта по умолчанию")]
|
|
public int defaultOptionIndex;
|
|
|
|
public SettingValue DefaultValue => valueType switch
|
|
{
|
|
SettingValueType.Bool => SettingValue.Bool(defaultBool),
|
|
SettingValueType.Int => SettingValue.Int(defaultInt),
|
|
SettingValueType.Float => SettingValue.Float(defaultFloat),
|
|
SettingValueType.String => SettingValue.String(defaultString ?? ""),
|
|
SettingValueType.Button => default, // Кнопки не хранят значение
|
|
SettingValueType.OptionPicker => SettingValue.Int(options != null && options.Count > 0
|
|
? Mathf.Clamp(defaultOptionIndex, 0, options.Count - 1)
|
|
: 0),
|
|
_ => default
|
|
};
|
|
|
|
public SettingValue Sanitize(SettingValue v)
|
|
{
|
|
if (v.type != valueType) return DefaultValue;
|
|
|
|
// защита от кривых min/max
|
|
int iMin = Mathf.Min(minInt, maxInt);
|
|
int iMax = Mathf.Max(minInt, maxInt);
|
|
float fMin = Mathf.Min(minFloat, maxFloat);
|
|
float fMax = Mathf.Max(minFloat, maxFloat);
|
|
|
|
return valueType switch
|
|
{
|
|
SettingValueType.Bool => SettingValue.Bool(v.b),
|
|
SettingValueType.Int => SettingValue.Int(Mathf.Clamp(v.i, iMin, iMax)),
|
|
SettingValueType.Float => SettingValue.Float(Mathf.Clamp(v.f, fMin, fMax)),
|
|
SettingValueType.String => SettingValue.String(v.s ?? ""),
|
|
SettingValueType.Button => default,
|
|
SettingValueType.OptionPicker => SettingValue.Int(options != null && options.Count > 0
|
|
? Mathf.Clamp(v.i, 0, options.Count - 1)
|
|
: 0),
|
|
_ => DefaultValue
|
|
};
|
|
}
|
|
}
|
|
|
|
[CreateAssetMenu(menuName = "Settings/Database")]
|
|
public class SettingsDatabase : ScriptableObject
|
|
{
|
|
public List<SettingEntry> entries = new();
|
|
|
|
public SettingEntry Find(string key)
|
|
=> entries.Find(e => string.Equals(e.key, key, StringComparison.Ordinal));
|
|
|
|
private void OnValidate()
|
|
{
|
|
var set = new HashSet<string>();
|
|
foreach (var e in entries)
|
|
{
|
|
if (e == null) continue;
|
|
|
|
if (string.IsNullOrWhiteSpace(e.key))
|
|
Debug.LogWarning($"[SettingsDatabase] Empty key in {name}", this);
|
|
else if (!set.Add(e.key))
|
|
Debug.LogWarning($"[SettingsDatabase] Duplicate key '{e.key}' in {name}", this);
|
|
}
|
|
}
|
|
}
|
|
} |