8.0 KiB
8.0 KiB
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
- Architecture at a Glance
- Quick Start (Code-First)
- Authoring in the Editor
- Available Settings Types
- Case Studies
- Troubleshooting / FAQ
- Paths & Namespaces
- Change Log
What This Solves
- Consistent, centralized configuration across gameplay systems.
- Safe, designer-editable
ScriptableObjectassets with validation (OnValidate). - Simple, Addressables-based runtime loading and caching via
SettingsProvider. - Editor-time overrides and scene gizmo feedback via
SettingsAccesshelpers.
Architecture at a Glance
- Base:
BaseSettings(ScriptableObject) — common parent for all settings. Implements optionalOnValidate(). - Access (runtime):
SettingsProvider(singletonMonoBehaviour) — loads assets synchronously via Addressables at keysSettings/<TypeName>and caches them. - Access (editor/dev):
SettingsAccess(static) — editor-friendly shim for reading selected values even when not in Play Mode, falling back toGameManagerat runtime. - Contracts:
SettingsInterfaces(IPlayerFollowerSettings,IInteractionSettings,IDivingMinigameSettings) used by systems to remain decoupled from concrete assets. - Editor tooling:
AppleHills/Settings Editor— finds/creates assets underAssets/Settingsand provides a tabbed UI.
Quick Start (Code-First)
Get Settings at Runtime
using AppleHills.Core.Settings;
var playerFollower = SettingsProvider.Instance.GetSettings<PlayerFollowerSettings>();
float speed = playerFollower.MoveSpeed;
Or fetch interaction settings once and reuse:
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:
// 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
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
BaseSettingsand provides tabbed editing for:PlayerFollowerSettingsInteractionSettingsDivingMinigameSettings
- If an asset is missing, the tool auto-creates it under
Assets/Settings/:Assets/Settings/PlayerFollowerSettings.assetAssets/Settings/InteractionSettings.assetAssets/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/PlayerFollowerSettingsSettings/InteractionSettingsSettings/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.
- Player:
InteractionSettings(IInteractionSettings)- Interactions:
PlayerStopDistance,PlayerStopDistanceDirectInteraction,FollowerPickupDelay. - Input/Layering:
InteractableLayerMask. - Prefabs:
BasePickupPrefab,LevelSwitchMenuPrefab,DefaultPuzzleIndicatorPrefab. - Puzzle/UI:
DefaultPuzzlePromptRange. - Items:
CombinationRules,SlotItemConfigsplus helpersGetCombinationRule(...),GetSlotItemConfig(...).
- Interactions:
DivingMinigameSettings(IDivingMinigameSettings)- Movement, spawning, scoring, surfacing, normalized movement, tile generation, obstacles, camera viewfinder settings, photo input mode (
PhotoInputModes).
- Movement, spawning, scoring, surfacing, normalized movement, tile generation, obstacles, camera viewfinder settings, photo input mode (
Case Studies
Tune Interaction Distances
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
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
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.
- Ensure assets are Addressable with keys
- Editor changes don’t reflect in scene gizmos:
- Click “Save All” in
AppleHills/Settings Editor; the editor provider refresh call updates views.
- Click “Save All” in
- Which API to use:
SettingsProvidervsSettingsAccess?- Use
SettingsProviderin runtime code. UseSettingsAccessin editor tools/gizmos or shared code that runs both in Edit and Play Modes.
- Use
Paths & Namespaces
- Scripts:
Assets/Scripts/Core/Settings/BaseSettings.csSettingsInterfaces.csSettingsProvider.csPlayerFollowerSettings.csInteractionSettings.csDivingMinigameSettings.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
- Runtime:
Change Log
- v1.1: New page with TOC, code-first usage, authoring workflow, Addressables keys, case studies, troubleshooting, and paths.