Refactor the settings to remove the old class

This commit is contained in:
Michal Pikulski
2025-09-24 08:05:37 +02:00
committed by AlexanderT
parent 404f6f4e5c
commit f07ce88331
19 changed files with 239 additions and 443 deletions

View File

@@ -0,0 +1,97 @@
using UnityEditor;
using AppleHills.Core.Settings;
using UnityEngine;
namespace AppleHills.Editor
{
/// <summary>
/// Provides access to settings in editor (non-play) mode
/// </summary>
[InitializeOnLoad]
public static class EditorSettingsProvider
{
private static PlayerFollowerSettings _playerFollowerSettings;
private static InteractionSettings _interactionSettings;
private static MinigameSettings _minigameSettings;
// Static constructor will be called when Unity loads/reloads scripts
static EditorSettingsProvider()
{
LoadAllSettings();
// Set up the delegates in SettingsAccess
AppleHills.SettingsAccess.SetupEditorProviders(
GetPlayerStopDistance,
GetPlayerStopDistanceDirectInteraction
);
// Subscribe to asset changes to auto-refresh when settings are modified
EditorApplication.delayCall += () =>
{
EditorApplication.projectChanged += OnProjectChanged;
};
}
private static void OnProjectChanged()
{
// Check if any settings assets have changed
if (HasSettingsChanged())
{
LoadAllSettings();
RefreshSceneViews();
}
}
private static bool HasSettingsChanged()
{
// Simplified check - you might want to make this more efficient
// by checking timestamps or specific files
return true;
}
public static void LoadAllSettings()
{
_playerFollowerSettings = AssetDatabase.LoadAssetAtPath<PlayerFollowerSettings>("Assets/Settings/PlayerFollowerSettings.asset");
_interactionSettings = AssetDatabase.LoadAssetAtPath<InteractionSettings>("Assets/Settings/InteractionSettings.asset");
_minigameSettings = AssetDatabase.LoadAssetAtPath<MinigameSettings>("Assets/Settings/MinigameSettings.asset");
// Re-register the delegates in case they were lost
AppleHills.SettingsAccess.SetupEditorProviders(
GetPlayerStopDistance,
GetPlayerStopDistanceDirectInteraction
);
Debug.Log("Editor settings loaded for Scene View use");
}
public static void RefreshSceneViews()
{
// Force scene views to repaint to refresh gizmos
SceneView.RepaintAll();
}
// Implementation of delegate methods
private static float GetPlayerStopDistance()
{
return _interactionSettings?.PlayerStopDistance ?? 6.0f;
}
private static float GetPlayerStopDistanceDirectInteraction()
{
return _interactionSettings?.PlayerStopDistanceDirectInteraction ?? 2.0f;
}
// Other utility methods
public static T GetSettings<T>() where T : BaseSettings
{
if (typeof(T) == typeof(PlayerFollowerSettings))
return _playerFollowerSettings as T;
else if (typeof(T) == typeof(InteractionSettings))
return _interactionSettings as T;
else if (typeof(T) == typeof(MinigameSettings))
return _minigameSettings as T;
return null;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1e8da573a8db4ea892fe476592276e0f
timeCreated: 1758634265

View File

@@ -1,4 +1,4 @@
 using UnityEngine;
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.Linq;
@@ -135,7 +135,12 @@ namespace AppleHills.Core.Settings.Editor
EditorUtility.SetDirty(serializedObj.targetObject);
}
AssetDatabase.SaveAssets();
Debug.Log("All settings saved!");
// Refresh editor settings after save
AppleHills.Editor.EditorSettingsProvider.LoadAllSettings();
AppleHills.Editor.EditorSettingsProvider.RefreshSceneViews();
Debug.Log("All settings saved and editor views refreshed!");
}
EditorGUILayout.EndHorizontal();

View File

@@ -1,302 +0,0 @@
using UnityEngine;
using UnityEditor;
using UnityEditor.AddressableAssets;
using UnityEditor.AddressableAssets.Settings;
using System.IO;
using AppleHills.Core.Settings;
namespace AppleHills.Editor
{
public class SettingsMigrationWindow : EditorWindow
{
private GameSettings legacySettings;
private bool addressablesInstalled;
private AddressableAssetSettings addressableSettings;
private AddressableAssetGroup settingsGroup;
private GUIStyle headerStyle;
private GUIStyle successStyle;
private Vector2 scrollPosition;
private bool migrationCompleted = false;
[MenuItem("Tools/Migrate Legacy Settings")]
public static void ShowWindow()
{
var window = GetWindow<SettingsMigrationWindow>("Settings Migration");
window.minSize = new Vector2(450, 400);
}
private void OnEnable()
{
// Check if Addressables package is installed
addressablesInstalled = AddressableAssetSettingsDefaultObject.SettingsExists;
if (addressablesInstalled)
{
addressableSettings = AddressableAssetSettingsDefaultObject.Settings;
}
}
private void OnGUI()
{
if (headerStyle == null)
{
headerStyle = new GUIStyle(EditorStyles.boldLabel);
headerStyle.fontSize = 14;
headerStyle.margin = new RectOffset(0, 0, 10, 10);
successStyle = new GUIStyle(EditorStyles.label);
successStyle.normal.textColor = Color.green;
successStyle.fontSize = 12;
}
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
EditorGUILayout.LabelField("Migrate Legacy Settings", headerStyle);
EditorGUILayout.Space(10);
EditorGUILayout.HelpBox(
"This tool will migrate your legacy GameSettings to the new modular settings system. " +
"It will create new settings assets and mark them as Addressables for synchronous loading at runtime.",
MessageType.Info);
EditorGUILayout.Space(10);
// Prerequisites section
EditorGUILayout.LabelField("Prerequisites", EditorStyles.boldLabel);
// Check Addressables
GUI.enabled = false;
EditorGUILayout.Toggle("Addressables Package Installed", addressablesInstalled);
GUI.enabled = true;
if (!addressablesInstalled)
{
EditorGUILayout.HelpBox(
"The Addressables package is not installed. Please install it via Window > Package Manager.",
MessageType.Error);
}
EditorGUILayout.Space(5);
// Legacy settings field
legacySettings = EditorGUILayout.ObjectField("Legacy GameSettings", legacySettings, typeof(GameSettings), false) as GameSettings;
if (legacySettings == null)
{
EditorGUILayout.HelpBox(
"Please assign your legacy GameSettings asset to migrate from.",
MessageType.Warning);
}
EditorGUILayout.Space(15);
// Migration button
GUI.enabled = legacySettings != null && addressablesInstalled;
if (GUILayout.Button("Migrate Settings", GUILayout.Height(30)))
{
MigrateSettings();
}
GUI.enabled = true;
// Success message
if (migrationCompleted)
{
EditorGUILayout.Space(10);
EditorGUILayout.LabelField("Migration completed successfully!", successStyle);
EditorGUILayout.HelpBox(
"The legacy settings have been migrated to the new system. " +
"You can now access these settings through the AppleHills > Settings Editor menu. " +
"Settings are marked as Addressables and will load synchronously at runtime.",
MessageType.Info);
}
EditorGUILayout.EndScrollView();
}
private void MigrateSettings()
{
// Create Settings folder if it doesn't exist
if (!AssetDatabase.IsValidFolder("Assets/Settings"))
{
AssetDatabase.CreateFolder("Assets", "Settings");
}
// Setup Addressables group for settings
SetupAddressablesGroup();
// Create and populate the new settings assets
CreatePlayerFollowerSettings();
CreateInteractionSettings();
CreateMinigameSettings();
// Save all assets
AssetDatabase.SaveAssets();
migrationCompleted = true;
}
private void SetupAddressablesGroup()
{
// Find or create a settings group
settingsGroup = addressableSettings.FindGroup("Settings");
if (settingsGroup == null)
{
settingsGroup = addressableSettings.CreateGroup("Settings", false, false, true, null);
}
}
private void AddAssetToAddressables(string assetPath, string address)
{
// Create entry in addressables
var guid = AssetDatabase.AssetPathToGUID(assetPath);
var entry = addressableSettings.CreateOrMoveEntry(guid, settingsGroup);
// Set the address - use without .asset extension for cleaner addresses
entry.address = address;
Debug.Log($"Added {assetPath} to Addressables with address {address}");
}
private void CreatePlayerFollowerSettings()
{
// Create the settings asset
var settings = ScriptableObject.CreateInstance<PlayerFollowerSettings>();
// Copy values from legacy settings
if (legacySettings != null)
{
// Player settings
var playerSettings = typeof(GameSettings).GetField("moveSpeed");
if (playerSettings != null) settings.GetType().GetField("moveSpeed", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(settings, legacySettings.moveSpeed);
var stopDistanceField = typeof(GameSettings).GetField("stopDistance");
if (stopDistanceField != null) settings.GetType().GetField("stopDistance", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(settings, legacySettings.stopDistance);
var useRigidbodyField = typeof(GameSettings).GetField("useRigidbody");
if (useRigidbodyField != null) settings.GetType().GetField("useRigidbody", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(settings, legacySettings.useRigidbody);
var defaultHoldMovementModeField = typeof(GameSettings).GetField("defaultHoldMovementMode");
if (defaultHoldMovementModeField != null) settings.GetType().GetField("defaultHoldMovementMode", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(settings, legacySettings.defaultHoldMovementMode);
// Follower settings
var followDistanceField = typeof(GameSettings).GetField("followDistance");
if (followDistanceField != null) settings.GetType().GetField("followDistance", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(settings, legacySettings.followDistance);
var manualMoveSmoothField = typeof(GameSettings).GetField("manualMoveSmooth");
if (manualMoveSmoothField != null) settings.GetType().GetField("manualMoveSmooth", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(settings, legacySettings.manualMoveSmooth);
var thresholdFarField = typeof(GameSettings).GetField("thresholdFar");
if (thresholdFarField != null) settings.GetType().GetField("thresholdFar", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(settings, legacySettings.thresholdFar);
var thresholdNearField = typeof(GameSettings).GetField("thresholdNear");
if (thresholdNearField != null) settings.GetType().GetField("thresholdNear", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(settings, legacySettings.thresholdNear);
var stopThresholdField = typeof(GameSettings).GetField("stopThreshold");
if (stopThresholdField != null) settings.GetType().GetField("stopThreshold", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(settings, legacySettings.stopThreshold);
// Backend settings
var followUpdateIntervalField = typeof(GameSettings).GetField("followUpdateInterval");
if (followUpdateIntervalField != null) settings.GetType().GetField("followUpdateInterval", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(settings, legacySettings.followUpdateInterval);
var followerSpeedMultiplierField = typeof(GameSettings).GetField("followerSpeedMultiplier");
if (followerSpeedMultiplierField != null) settings.GetType().GetField("followerSpeedMultiplier", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(settings, legacySettings.followerSpeedMultiplier);
var heldIconDisplayHeightField = typeof(GameSettings).GetField("heldIconDisplayHeight");
if (heldIconDisplayHeightField != null) settings.GetType().GetField("heldIconDisplayHeight", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(settings, legacySettings.heldIconDisplayHeight);
}
// Save the asset
string assetPath = "Assets/Settings/PlayerFollowerSettings.asset";
AssetDatabase.CreateAsset(settings, assetPath);
// Add to addressables
AddAssetToAddressables(assetPath, "Settings/PlayerFollowerSettings");
Debug.Log("Created PlayerFollowerSettings asset");
}
private void CreateInteractionSettings()
{
// Create the settings asset
var settings = ScriptableObject.CreateInstance<InteractionSettings>();
// Copy values from legacy settings
if (legacySettings != null)
{
// Interaction settings
var playerStopDistanceField = typeof(GameSettings).GetField("playerStopDistance");
if (playerStopDistanceField != null) settings.GetType().GetField("playerStopDistance", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(settings, legacySettings.playerStopDistance);
var playerStopDistanceDirectInteractionField = typeof(GameSettings).GetField("playerStopDistanceDirectInteraction");
if (playerStopDistanceDirectInteractionField != null) settings.GetType().GetField("playerStopDistanceDirectInteraction", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(settings, legacySettings.playerStopDistanceDirectInteraction);
var followerPickupDelayField = typeof(GameSettings).GetField("followerPickupDelay");
if (followerPickupDelayField != null) settings.GetType().GetField("followerPickupDelay", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(settings, legacySettings.followerPickupDelay);
var interactableLayerMaskField = typeof(GameSettings).GetField("interactableLayerMask");
if (interactableLayerMaskField != null) settings.GetType().GetField("interactableLayerMask", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(settings, legacySettings.interactableLayerMask);
// Prefabs
var basePickupPrefabField = typeof(GameSettings).GetField("basePickupPrefab");
if (basePickupPrefabField != null) settings.GetType().GetField("basePickupPrefab", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(settings, legacySettings.basePickupPrefab);
var levelSwitchMenuPrefabField = typeof(GameSettings).GetField("levelSwitchMenuPrefab");
if (levelSwitchMenuPrefabField != null) settings.GetType().GetField("levelSwitchMenuPrefab", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(settings, legacySettings.levelSwitchMenuPrefab);
// Item configuration
var combinationRulesField = typeof(GameSettings).GetField("combinationRules");
if (combinationRulesField != null) settings.GetType().GetField("combinationRules", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(settings, legacySettings.combinationRules);
var slotItemConfigsField = typeof(GameSettings).GetField("slotItemConfigs");
if (slotItemConfigsField != null) settings.GetType().GetField("slotItemConfigs", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(settings, legacySettings.slotItemConfigs);
}
// Save the asset
string assetPath = "Assets/Settings/InteractionSettings.asset";
AssetDatabase.CreateAsset(settings, assetPath);
// Add to addressables
AddAssetToAddressables(assetPath, "Settings/InteractionSettings");
Debug.Log("Created InteractionSettings asset");
}
private void CreateMinigameSettings()
{
// Create the settings asset
var settings = ScriptableObject.CreateInstance<MinigameSettings>();
// Copy values from legacy settings
if (legacySettings != null)
{
// Endless descender settings
var endlessDescenderLerpSpeedField = typeof(GameSettings).GetField("endlessDescenderLerpSpeed");
if (endlessDescenderLerpSpeedField != null) settings.GetType().GetField("endlessDescenderLerpSpeed", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(settings, legacySettings.endlessDescenderLerpSpeed);
var endlessDescenderMaxOffsetField = typeof(GameSettings).GetField("endlessDescenderMaxOffset");
if (endlessDescenderMaxOffsetField != null) settings.GetType().GetField("endlessDescenderMaxOffset", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(settings, legacySettings.endlessDescenderMaxOffset);
var endlessDescenderClampXMinField = typeof(GameSettings).GetField("endlessDescenderClampXMin");
if (endlessDescenderClampXMinField != null) settings.GetType().GetField("endlessDescenderClampXMin", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(settings, legacySettings.endlessDescenderClampXMin);
var endlessDescenderClampXMaxField = typeof(GameSettings).GetField("endlessDescenderClampXMax");
if (endlessDescenderClampXMaxField != null) settings.GetType().GetField("endlessDescenderClampXMax", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(settings, legacySettings.endlessDescenderClampXMax);
var endlessDescenderSpeedExponentField = typeof(GameSettings).GetField("endlessDescenderSpeedExponent");
if (endlessDescenderSpeedExponentField != null) settings.GetType().GetField("endlessDescenderSpeedExponent", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(settings, legacySettings.endlessDescenderSpeedExponent);
}
// Save the asset
string assetPath = "Assets/Settings/MinigameSettings.asset";
AssetDatabase.CreateAsset(settings, assetPath);
// Add to addressables
AddAssetToAddressables(assetPath, "Settings/MinigameSettings");
Debug.Log("Created MinigameSettings asset");
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: b16caebbe9934df3a34f0b75879e65f2
timeCreated: 1758630926

View File

@@ -31,28 +31,14 @@ public class GameManager : MonoBehaviour
}
}
[Header("Legacy Game Settings (Deprecated)")]
[Tooltip("This is only used for migration to the new settings system")]
public GameSettings legacyGameSettings;
[Header("Settings Status")]
[SerializeField] private bool _settingsLoaded = false;
public bool SettingsLoaded => _settingsLoaded;
// Use this for fallback values when settings aren't loaded yet
[Header("Fallback Settings")]
[SerializeField] private GameSettings fallbackSettings;
void Awake()
{
_instance = this;
// If no fallback settings assigned, try to load them
if (fallbackSettings == null)
{
fallbackSettings = Resources.Load<GameSettings>("DefaultSettings");
}
// Create settings provider if it doesn't exist
SettingsProvider.Instance.gameObject.name = "Settings Provider";
@@ -112,12 +98,6 @@ public class GameManager : MonoBehaviour
{
Debug.LogWarning("Some settings failed to load - check that all settings assets exist and are marked as Addressables");
}
// Migrate settings if needed
if (legacyGameSettings != null && !playerSettings && !interactionSettings && !minigameSettings)
{
Debug.LogWarning("Legacy settings detected but failed to load new settings. Consider running the migration tool.");
}
}
void OnApplicationQuit()
@@ -138,8 +118,8 @@ public class GameManager : MonoBehaviour
public float MoveSpeed => GetSettings<IPlayerFollowerSettings>()?.MoveSpeed ?? 5f;
public float StopDistance => GetSettings<IPlayerFollowerSettings>()?.StopDistance ?? 0.1f;
public bool UseRigidbody => GetSettings<IPlayerFollowerSettings>()?.UseRigidbody ?? true;
public GameSettings.HoldMovementMode DefaultHoldMovementMode =>
GetSettings<IPlayerFollowerSettings>()?.DefaultHoldMovementMode ?? GameSettings.HoldMovementMode.Pathfinding;
public HoldMovementMode DefaultHoldMovementMode =>
GetSettings<IPlayerFollowerSettings>()?.DefaultHoldMovementMode ?? HoldMovementMode.Pathfinding;
// Follower settings
public float FollowDistance => GetSettings<IPlayerFollowerSettings>()?.FollowDistance ?? 1.5f;
@@ -163,7 +143,7 @@ public class GameManager : MonoBehaviour
/// <summary>
/// Returns the combination rule for two items, if any.
/// </summary>
public GameSettings.CombinationRule GetCombinationRule(PickupItemData item1, PickupItemData item2)
public CombinationRule GetCombinationRule(PickupItemData item1, PickupItemData item2)
{
var settings = GetSettings<IInteractionSettings>();
if (settings == null || settings.CombinationRules == null) return null;
@@ -182,7 +162,7 @@ public class GameManager : MonoBehaviour
/// <summary>
/// Returns the slot item config for a given slot item.
/// </summary>
public GameSettings.SlotItemConfig GetSlotItemConfig(PickupItemData slotItem)
public SlotItemConfig GetSlotItemConfig(PickupItemData slotItem)
{
var settings = GetSettings<IInteractionSettings>();
if (settings == null || settings.SlotItemConfigs == null || slotItem == null) return null;

View File

@@ -1,73 +0,0 @@
using UnityEngine;
/// <summary>
/// ScriptableObject for storing and configuring all game settings, including player, follower, and item configuration.
/// </summary>
[CreateAssetMenu(fileName = "GameSettings", menuName = "AppleHills/GameSettings", order = 1)]
public class GameSettings : ScriptableObject
{
[Header("Interactions")]
public float playerStopDistance = 6.0f;
public float playerStopDistanceDirectInteraction = 2.0f;
public float followerPickupDelay = 0.2f;
[Header("Follower Settings")]
public float followDistance = 1.5f;
public float manualMoveSmooth = 8f;
public float thresholdFar = 2.5f;
public float thresholdNear = 0.5f;
public float stopThreshold = 0.1f;
[Header("Player Settings")]
public float moveSpeed = 5f;
public float stopDistance = 0.1f;
public bool useRigidbody = true;
public enum HoldMovementMode { Pathfinding, Direct }
public HoldMovementMode defaultHoldMovementMode = HoldMovementMode.Pathfinding;
[Header("Backend Settings")]
[Tooltip("Technical parameters, not for design tuning")]
public float followUpdateInterval = 0.1f;
public float followerSpeedMultiplier = 1.2f;
public float heldIconDisplayHeight = 2.0f;
[Header("Default Prefabs")]
public GameObject basePickupPrefab;
[Header("Endless Descender Settings")]
[Tooltip("How quickly the character follows the finger horizontally (higher = more responsive)")]
public float endlessDescenderLerpSpeed = 12f;
[Tooltip("Maximum horizontal offset allowed between character and finger position")]
public float endlessDescenderMaxOffset = 3f;
[Tooltip("Minimum allowed X position for endless descender movement")]
public float endlessDescenderClampXMin = -3.5f;
[Tooltip("Maximum allowed X position for endless descender movement")]
public float endlessDescenderClampXMax = 3.5f;
[Tooltip("Exponent for speed drop-off curve (higher = sharper drop near target)")]
public float endlessDescenderSpeedExponent = 2.5f;
[Header("InputManager Settings")]
[Tooltip("Layer(s) to use for interactable objects.")]
public LayerMask interactableLayerMask = -1; // Default to Everything
[Header("UI Prefabs")]
public GameObject levelSwitchMenuPrefab;
[System.Serializable]
public class CombinationRule {
public PickupItemData itemA;
public PickupItemData itemB;
public GameObject resultPrefab; // The prefab to spawn as the result
}
[System.Serializable]
public class SlotItemConfig {
public PickupItemData slotItem; // The slot object (SO reference)
public System.Collections.Generic.List<PickupItemData> allowedItems;
public System.Collections.Generic.List<PickupItemData> forbiddenItems;
}
[Header("Item Configuration")]
public System.Collections.Generic.List<CombinationRule> combinationRules;
public System.Collections.Generic.List<SlotItemConfig> slotItemConfigs;
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: e4ec438b455a4044957501c2c66a6f4b
timeCreated: 1756933137

View File

@@ -23,8 +23,8 @@ namespace AppleHills.Core.Settings
[SerializeField] private GameObject levelSwitchMenuPrefab;
[Header("Item Configuration")]
[SerializeField] private List<GameSettings.CombinationRule> combinationRules = new List<GameSettings.CombinationRule>();
[SerializeField] private List<GameSettings.SlotItemConfig> slotItemConfigs = new List<GameSettings.SlotItemConfig>();
[SerializeField] private List<CombinationRule> combinationRules = new List<CombinationRule>();
[SerializeField] private List<SlotItemConfig> slotItemConfigs = new List<SlotItemConfig>();
// IInteractionSettings implementation
public float PlayerStopDistance => playerStopDistance;
@@ -33,8 +33,8 @@ namespace AppleHills.Core.Settings
public LayerMask InteractableLayerMask => interactableLayerMask;
public GameObject BasePickupPrefab => basePickupPrefab;
public GameObject LevelSwitchMenuPrefab => levelSwitchMenuPrefab;
public List<GameSettings.CombinationRule> CombinationRules => combinationRules;
public List<GameSettings.SlotItemConfig> SlotItemConfigs => slotItemConfigs;
public List<CombinationRule> CombinationRules => combinationRules;
public List<SlotItemConfig> SlotItemConfigs => slotItemConfigs;
public override void OnValidate()
{

View File

@@ -0,0 +1,27 @@
using System.Collections.Generic;
using UnityEngine;
namespace AppleHills.Core.Settings
{
/// <summary>
/// Defines a rule for combining two items
/// </summary>
[System.Serializable]
public class CombinationRule
{
public PickupItemData itemA;
public PickupItemData itemB;
public GameObject resultPrefab; // The prefab to spawn as the result
}
/// <summary>
/// Configuration for items that can be placed in slots
/// </summary>
[System.Serializable]
public class SlotItemConfig
{
public PickupItemData slotItem; // The slot object (SO reference)
public List<PickupItemData> allowedItems;
public List<PickupItemData> forbiddenItems; // Items that cannot be placed in this slot
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9f9547445fd84c7db30533b7ee9d81dd
timeCreated: 1758699048

View File

@@ -0,0 +1,13 @@
using UnityEngine;
namespace AppleHills.Core.Settings
{
/// <summary>
/// Enum defining different movement modes for player movement
/// </summary>
public enum HoldMovementMode
{
Pathfinding,
Direct
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b6b1454235ab476dae09e99238d6c7ce
timeCreated: 1758699033

View File

@@ -12,7 +12,7 @@ namespace AppleHills.Core.Settings
[SerializeField] private float moveSpeed = 5f;
[SerializeField] private float stopDistance = 0.1f;
[SerializeField] private bool useRigidbody = true;
[SerializeField] private GameSettings.HoldMovementMode defaultHoldMovementMode = GameSettings.HoldMovementMode.Pathfinding;
[SerializeField] private HoldMovementMode defaultHoldMovementMode = HoldMovementMode.Pathfinding;
[Header("Follower Settings")]
[SerializeField] private float followDistance = 1.5f;
@@ -31,7 +31,7 @@ namespace AppleHills.Core.Settings
public float MoveSpeed => moveSpeed;
public float StopDistance => stopDistance;
public bool UseRigidbody => useRigidbody;
public GameSettings.HoldMovementMode DefaultHoldMovementMode => defaultHoldMovementMode;
public HoldMovementMode DefaultHoldMovementMode => defaultHoldMovementMode;
public float FollowDistance => followDistance;
public float ManualMoveSmooth => manualMoveSmooth;
public float ThresholdFar => thresholdFar;

View File

@@ -1,4 +1,5 @@
using UnityEngine;
using System.Collections.Generic;
namespace AppleHills.Core.Settings
{
@@ -11,7 +12,7 @@ namespace AppleHills.Core.Settings
float MoveSpeed { get; }
float StopDistance { get; }
bool UseRigidbody { get; }
GameSettings.HoldMovementMode DefaultHoldMovementMode { get; }
HoldMovementMode DefaultHoldMovementMode { get; }
// Follower settings
float FollowDistance { get; }
@@ -35,8 +36,8 @@ namespace AppleHills.Core.Settings
LayerMask InteractableLayerMask { get; }
GameObject BasePickupPrefab { get; }
GameObject LevelSwitchMenuPrefab { get; }
System.Collections.Generic.List<GameSettings.CombinationRule> CombinationRules { get; }
System.Collections.Generic.List<GameSettings.SlotItemConfig> SlotItemConfigs { get; }
List<CombinationRule> CombinationRules { get; }
List<SlotItemConfig> SlotItemConfigs { get; }
}
/// <summary>

View File

@@ -0,0 +1,57 @@
using UnityEngine;
namespace AppleHills
{
/// <summary>
/// Unified access to settings in both editor and play mode
/// </summary>
public static class SettingsAccess
{
// Delegate type for editor-only settings providers
public delegate float GetSettingsValueDelegate();
// Static delegates that will be set by editor code
private static GetSettingsValueDelegate getPlayerStopDistanceProvider;
private static GetSettingsValueDelegate getPlayerStopDistanceDirectInteractionProvider;
// Editor-only method to set up providers - will be called from editor code
public static void SetupEditorProviders(
GetSettingsValueDelegate playerStopDistanceProvider,
GetSettingsValueDelegate playerStopDistanceDirectInteractionProvider)
{
#if UNITY_EDITOR
if (!Application.isPlaying)
{
getPlayerStopDistanceProvider = playerStopDistanceProvider;
getPlayerStopDistanceDirectInteractionProvider = playerStopDistanceDirectInteractionProvider;
}
#endif
}
public static float GetPlayerStopDistance()
{
#if UNITY_EDITOR
if (!Application.isPlaying && getPlayerStopDistanceProvider != null)
{
return getPlayerStopDistanceProvider();
}
#endif
return GameManager.Instance.PlayerStopDistance;
}
public static float GetPlayerStopDistanceDirectInteraction()
{
#if UNITY_EDITOR
if (!Application.isPlaying && getPlayerStopDistanceDirectInteractionProvider != null)
{
return getPlayerStopDistanceDirectInteractionProvider();
}
#endif
return GameManager.Instance.PlayerStopDistanceDirectInteraction;
}
// Add more methods as needed for other settings
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a23d841c0e2047ff8dbe84820227bdea
timeCreated: 1758634274

View File

@@ -1,5 +1,6 @@
using UnityEngine;
using Pathfinding;
using AppleHills.Core.Settings;
namespace Input
{
@@ -94,7 +95,7 @@ namespace Input
Debug.Log($"[PlayerTouchController] OnHoldStart at {worldPosition}");
lastHoldPosition = worldPosition;
isHolding = true;
if (GameManager.Instance.DefaultHoldMovementMode == GameSettings.HoldMovementMode.Pathfinding &&
if (GameManager.Instance.DefaultHoldMovementMode == HoldMovementMode.Pathfinding &&
aiPath != null)
{
aiPath.enabled = true;
@@ -110,12 +111,12 @@ namespace Input
/// <summary>
/// Handles hold move input. Updates the target position for direct or pathfinding movement.
/// </summary>
/// /// </summary>
public void OnHoldMove(Vector2 worldPosition)
{
if (!isHolding) return;
lastHoldPosition = worldPosition;
if (GameManager.Instance.DefaultHoldMovementMode == GameSettings.HoldMovementMode.Direct)
if (GameManager.Instance.DefaultHoldMovementMode == HoldMovementMode.Direct)
{
if (aiPath != null && aiPath.enabled) aiPath.enabled = false;
MoveDirectlyTo(worldPosition);
@@ -132,7 +133,7 @@ namespace Input
isHolding = false;
directMoveVelocity = Vector3.zero;
if (aiPath != null && GameManager.Instance.DefaultHoldMovementMode ==
GameSettings.HoldMovementMode.Pathfinding)
HoldMovementMode.Pathfinding)
{
if (pathfindingDragCoroutine != null)
{
@@ -141,7 +142,7 @@ namespace Input
}
}
if (aiPath != null && GameManager.Instance.DefaultHoldMovementMode == GameSettings.HoldMovementMode.Direct)
if (aiPath != null && GameManager.Instance.DefaultHoldMovementMode == HoldMovementMode.Direct)
{
aiPath.enabled = false;
}
@@ -237,7 +238,7 @@ namespace Input
{
float normalizedSpeed = 0f;
Vector3 velocity = Vector3.zero;
if (isHolding && GameManager.Instance.DefaultHoldMovementMode == GameSettings.HoldMovementMode.Direct)
if (isHolding && GameManager.Instance.DefaultHoldMovementMode == HoldMovementMode.Direct)
{
normalizedSpeed = directMoveVelocity.magnitude / aiPath.maxSpeed;
velocity = directMoveVelocity;
@@ -260,7 +261,7 @@ namespace Input
bool isCurrentlyMoving = false;
// Check direct movement
if (isHolding && GameManager.Instance.DefaultHoldMovementMode == GameSettings.HoldMovementMode.Direct)
if (isHolding && GameManager.Instance.DefaultHoldMovementMode == HoldMovementMode.Direct)
{
isCurrentlyMoving = directMoveVelocity.sqrMagnitude > 0.001f;
}
@@ -339,7 +340,7 @@ namespace Input
interruptMoveTo = true;
isHolding = false;
directMoveVelocity = Vector3.zero;
if (GameManager.Instance.DefaultHoldMovementMode == GameSettings.HoldMovementMode.Direct && aiPath != null)
if (GameManager.Instance.DefaultHoldMovementMode == HoldMovementMode.Direct && aiPath != null)
aiPath.enabled = false;
OnMoveToCancelled?.Invoke();
}

View File

@@ -194,25 +194,9 @@ namespace Interactions
/// </summary>
void OnDrawGizmos()
{
float playerStopDistance;
if (Application.isPlaying)
{
playerStopDistance = characterToInteract == CharacterToInteract.Trafalgar
? GameManager.Instance.PlayerStopDistanceDirectInteraction
: GameManager.Instance.PlayerStopDistance;
}
else
{
// Load settings directly from asset path in editor
var settings =
UnityEditor.AssetDatabase.LoadAssetAtPath<GameSettings>(
"Assets/Data/Settings/DefaultSettings.asset");
playerStopDistance = settings != null
? (characterToInteract == CharacterToInteract.Trafalgar
? settings.playerStopDistanceDirectInteraction
: settings.playerStopDistance)
: 1.0f;
}
float playerStopDistance = characterToInteract == CharacterToInteract.Trafalgar
? AppleHills.SettingsAccess.GetPlayerStopDistanceDirectInteraction()
: AppleHills.SettingsAccess.GetPlayerStopDistance();
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere(transform.position, playerStopDistance);