187 lines
8.0 KiB
Markdown
187 lines
8.0 KiB
Markdown
# Apple Hills Settings System
|
||
|
||
Centralized, designer-friendly configuration using `ScriptableObject` assets, with runtime access via `SettingsProvider` (Addressables-backed) and editor/live-preview access via `SettingsAccess`. This page follows the style of other updated docs (TOC, inline code, code-first usage, case studies).
|
||
|
||
## Table of Contents
|
||
- [What This Solves](#what-this-solves)
|
||
- [Architecture at a Glance](#architecture-at-a-glance)
|
||
- [Quick Start (Code-First)](#quick-start-code-first)
|
||
- [Get Settings at Runtime](#get-settings-at-runtime)
|
||
- [Use Editor-Time Values via `SettingsAccess`](#use-editor-time-values-via-settingsaccess)
|
||
- [Access Example Fields](#access-example-fields)
|
||
- [Authoring in the Editor](#authoring-in-the-editor)
|
||
- [Creating/Editing Settings Assets](#creatingediting-settings-assets)
|
||
- [Addressables Keys & Loading](#addressables-keys--loading)
|
||
- [Available Settings Types](#available-settings-types)
|
||
- [Case Studies](#case-studies)
|
||
- [Tune Interaction Distances](#tune-interaction-distances)
|
||
- [Follower Handling & Movement](#follower-handling--movement)
|
||
- [Diving Minigame Tuning](#diving-minigame-tuning)
|
||
- [Troubleshooting / FAQ](#troubleshooting--faq)
|
||
- [Paths & Namespaces](#paths--namespaces)
|
||
- [Change Log](#change-log)
|
||
|
||
## What This Solves
|
||
- Consistent, centralized configuration across gameplay systems.
|
||
- Safe, designer-editable `ScriptableObject` assets with validation (`OnValidate`).
|
||
- Simple, Addressables-based runtime loading and caching via `SettingsProvider`.
|
||
- Editor-time overrides and scene gizmo feedback via `SettingsAccess` helpers.
|
||
|
||
## Architecture at a Glance
|
||
- Base: `BaseSettings` (`ScriptableObject`) — common parent for all settings. Implements optional `OnValidate()`.
|
||
- Access (runtime): `SettingsProvider` (singleton `MonoBehaviour`) — loads assets synchronously via Addressables at keys `Settings/<TypeName>` and caches them.
|
||
- Access (editor/dev): `SettingsAccess` (static) — editor-friendly shim for reading selected values even when not in Play Mode, falling back to `GameManager` at runtime.
|
||
- Contracts: `SettingsInterfaces` (`IPlayerFollowerSettings`, `IInteractionSettings`, `IDivingMinigameSettings`) used by systems to remain decoupled from concrete assets.
|
||
- Editor tooling: `AppleHills/Settings Editor` — finds/creates assets under `Assets/Settings` and provides a tabbed UI.
|
||
|
||
## Quick Start (Code-First)
|
||
|
||
### Get Settings at Runtime
|
||
```csharp
|
||
using AppleHills.Core.Settings;
|
||
|
||
var playerFollower = SettingsProvider.Instance.GetSettings<PlayerFollowerSettings>();
|
||
float speed = playerFollower.MoveSpeed;
|
||
```
|
||
Or fetch interaction settings once and reuse:
|
||
```csharp
|
||
using AppleHills.Core.Settings;
|
||
|
||
private IInteractionSettings _interaction;
|
||
|
||
void Awake()
|
||
{
|
||
_interaction = SettingsProvider.Instance.GetSettings<InteractionSettings>();
|
||
}
|
||
|
||
void UseIt()
|
||
{
|
||
float stopDist = _interaction.PlayerStopDistance;
|
||
}
|
||
```
|
||
|
||
### Use Editor-Time Values via `SettingsAccess`
|
||
For scene tools, gizmos, or editors that should reflect current settings outside Play Mode:
|
||
```csharp
|
||
// Returns editor-sourced values in Edit Mode; GameManager-backed in Play Mode
|
||
float stopDist = AppleHills.SettingsAccess.GetPlayerStopDistance();
|
||
float directStop = AppleHills.SettingsAccess.GetPlayerStopDistanceDirectInteraction();
|
||
float puzzleRange = AppleHills.SettingsAccess.GetPuzzlePromptRange();
|
||
```
|
||
|
||
### Access Example Fields
|
||
```csharp
|
||
using AppleHills.Core.Settings;
|
||
|
||
var pf = SettingsProvider.Instance.GetSettings<PlayerFollowerSettings>();
|
||
// Player
|
||
float moveSpeed = pf.MoveSpeed;
|
||
float accel = pf.MaxAcceleration;
|
||
bool useRb = pf.UseRigidbody;
|
||
// Follower
|
||
float followDist = pf.FollowDistance;
|
||
float near = pf.ThresholdNear;
|
||
|
||
var inter = SettingsProvider.Instance.GetSettings<InteractionSettings>();
|
||
LayerMask interactMask = inter.InteractableLayerMask;
|
||
GameObject pickupPrefab = inter.BasePickupPrefab;
|
||
float promptRange = inter.DefaultPuzzlePromptRange;
|
||
```
|
||
|
||
## Authoring in the Editor
|
||
|
||
### Creating/Editing Settings Assets
|
||
- Open via menu: `AppleHills/Settings Editor`.
|
||
- The window discovers all assets of type `BaseSettings` and provides tabbed editing for:
|
||
- `PlayerFollowerSettings`
|
||
- `InteractionSettings`
|
||
- `DivingMinigameSettings`
|
||
- If an asset is missing, the tool auto-creates it under `Assets/Settings/`:
|
||
- `Assets/Settings/PlayerFollowerSettings.asset`
|
||
- `Assets/Settings/InteractionSettings.asset`
|
||
- `Assets/Settings/DivingMinigameSettings.asset`
|
||
- Click “Save All” to persist and refresh editor providers/gizmos.
|
||
|
||
### Addressables Keys & Loading
|
||
At runtime, `SettingsProvider` synchronously loads settings via Addressables with keys:
|
||
- `Settings/PlayerFollowerSettings`
|
||
- `Settings/InteractionSettings`
|
||
- `Settings/DivingMinigameSettings`
|
||
|
||
Ensure these assets are marked as Addressables with the exact keys above. The provider caches objects, so subsequent `GetSettings<T>()` calls are fast.
|
||
|
||
## Available Settings Types
|
||
- `PlayerFollowerSettings` (`IPlayerFollowerSettings`)
|
||
- Player: `MoveSpeed`, `MaxAcceleration`, `StopDistance`, `UseRigidbody`, `DefaultHoldMovementMode`.
|
||
- Follower: `FollowDistance`, `ManualMoveSmooth`, `ThresholdFar`, `ThresholdNear`, `StopThreshold`.
|
||
- Backend: `FollowUpdateInterval`, `FollowerSpeedMultiplier`, `HeldIconDisplayHeight`.
|
||
- `InteractionSettings` (`IInteractionSettings`)
|
||
- Interactions: `PlayerStopDistance`, `PlayerStopDistanceDirectInteraction`, `FollowerPickupDelay`.
|
||
- Input/Layering: `InteractableLayerMask`.
|
||
- Prefabs: `BasePickupPrefab`, `LevelSwitchMenuPrefab`, `DefaultPuzzleIndicatorPrefab`.
|
||
- Puzzle/UI: `DefaultPuzzlePromptRange`.
|
||
- Items: `CombinationRules`, `SlotItemConfigs` plus helpers `GetCombinationRule(...)`, `GetSlotItemConfig(...)`.
|
||
- `DivingMinigameSettings` (`IDivingMinigameSettings`)
|
||
- Movement, spawning, scoring, surfacing, normalized movement, tile generation, obstacles, camera viewfinder settings, photo input mode (`PhotoInputModes`).
|
||
|
||
## Case Studies
|
||
|
||
### Tune Interaction Distances
|
||
```csharp
|
||
using AppleHills.Core.Settings;
|
||
|
||
public class InteractDistanceExample
|
||
{
|
||
private readonly IInteractionSettings _s = SettingsProvider.Instance.GetSettings<InteractionSettings>();
|
||
public bool IsInRange(float dist) => dist <= _s.PlayerStopDistance;
|
||
}
|
||
```
|
||
|
||
### Follower Handling & Movement
|
||
```csharp
|
||
using AppleHills.Core.Settings;
|
||
|
||
public class FollowerMover
|
||
{
|
||
private readonly IPlayerFollowerSettings _pf = SettingsProvider.Instance.GetSettings<PlayerFollowerSettings>();
|
||
public float TargetSpeed(float error) => Mathf.Clamp(error * _pf.FollowerSpeedMultiplier, 0f, _pf.MoveSpeed);
|
||
}
|
||
```
|
||
|
||
### Diving Minigame Tuning
|
||
```csharp
|
||
using AppleHills.Core.Settings;
|
||
|
||
public class SpawnController
|
||
{
|
||
private readonly IDivingMinigameSettings _m = SettingsProvider.Instance.GetSettings<DivingMinigameSettings>();
|
||
public float NextCooldown(float baseCooldown) => Mathf.Clamp(baseCooldown + Random.Range(-_m.ObstacleSpawnIntervalVariation, _m.ObstacleSpawnIntervalVariation), 0.1f, 99);
|
||
}
|
||
```
|
||
|
||
## Troubleshooting / FAQ
|
||
- Settings return null at runtime:
|
||
- Ensure assets are Addressable with keys `Settings/<TypeName>` and Addressables are initialized before first access.
|
||
- Editor changes don’t reflect in scene gizmos:
|
||
- Click “Save All” in `AppleHills/Settings Editor`; the editor provider refresh call updates views.
|
||
- Which API to use: `SettingsProvider` vs `SettingsAccess`?
|
||
- Use `SettingsProvider` in runtime code. Use `SettingsAccess` in editor tools/gizmos or shared code that runs both in Edit and Play Modes.
|
||
|
||
## Paths & Namespaces
|
||
- Scripts: `Assets/Scripts/Core/Settings/`
|
||
- `BaseSettings.cs`
|
||
- `SettingsInterfaces.cs`
|
||
- `SettingsProvider.cs`
|
||
- `PlayerFollowerSettings.cs`
|
||
- `InteractionSettings.cs`
|
||
- `DivingMinigameSettings.cs`
|
||
- Editor tooling: `Assets/Editor/SettingsEditorWindow.cs`
|
||
- Editor-time facade: `Assets/Scripts/Core/SettingsAccess.cs`
|
||
- Namespaces:
|
||
- Runtime: `AppleHills.Core.Settings`
|
||
- Editor window: `AppleHills.Core.Settings.Editor`
|
||
- Facade: `AppleHills`
|
||
|
||
## Change Log
|
||
- v1.1: New page with TOC, code-first usage, authoring workflow, Addressables keys, case studies, troubleshooting, and paths.
|