Compare commits

...

7 Commits

Author SHA1 Message Date
7fc3ca12f3 Final touchups to the dialogue component 2025-09-26 16:16:33 +02:00
abeb5060f9 DialogueComponent doodles 2025-09-26 15:47:26 +02:00
f380b6fa54 Small updates to dispatchers in items and puzzles 2025-09-26 14:06:03 +02:00
b781a1656d Introduced dialogue graph magic, created assest and importers. Added events for broadcasting puzzle steps 2025-09-26 13:32:14 +02:00
47d942d176 Switched Unity version to 6.2, updated some packages + installed GraphToolkit 2025-09-26 08:48:33 +02:00
e878a32263 Introduce input modes and Pause Menu (#8)
- Add input mode switching to the Input Manager
- Automatically set input mode on scene load - UI for MainMenu and GameAndUI for other scenes
- Add PauseMenu prefab, auto-loaded via the boostrap system
- Automatically control PauseMenu visibility based on current scene

Co-authored-by: AlexanderT <alexander@foolhardyhorizons.com>
Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com>
Reviewed-on: #8
2025-09-25 10:06:51 +00:00
63cb3f1a8c Revamp the settings system (#7)
- A Settings Provider system to utilize addressables for loading settings at runtime
- An editor UI for easy modifications of the settings objects
- A split out developer settings functionality to keep gameplay and nitty-gritty details separately
- Most settings migrated out of game objects and into the new system
- An additional Editor utility for fetching the settings at editor runtime, for gizmos, visualization etc

Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com>
Co-authored-by: AlexanderT <alexander@foolhardyhorizons.com>
Reviewed-on: #7
2025-09-24 13:33:43 +00:00
146 changed files with 9087 additions and 1404 deletions

View File

@@ -0,0 +1,19 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: dea69d41f90c6ea4fa55c27c1d60c145, type: 3}
m_Name: AddressableAssetGroupSortSettings
m_EditorClassIdentifier:
sortOrder:
- eb8a37153d819c44194f7ce97570a3d3
- 2b3d7cefec0915e42be04aebf0400a56
- 6f3207429a65b3e4b83935ac19791077
- c62e6f02418e19949bca4cccdd5fa02e

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 32c1a9c8651793e41848a173d66d98fd
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -15,7 +15,7 @@ MonoBehaviour:
m_DefaultGroup: 6f3207429a65b3e4b83935ac19791077
m_currentHash:
serializedVersion: 2
Hash: c0cf00979528ae95d3583c572e4eb343
Hash: 00000000000000000000000000000000
m_OptimizeCatalogSize: 0
m_BuildRemoteCatalog: 0
m_CatalogRequestsTimeout: 0
@@ -61,6 +61,7 @@ MonoBehaviour:
m_GroupAssets:
- {fileID: 11400000, guid: efe7e1728e73e9546ac5dfee2eff524f, type: 2}
- {fileID: 11400000, guid: 6e4927e7e19eef34b93dc2baa9e9e8e2, type: 2}
- {fileID: 11400000, guid: e25c7672a65b5974bb354fcfb2a8400c, type: 2}
- {fileID: 11400000, guid: 7fcc03e584505ed4381983b6ebb1179d, type: 2}
m_BuildSettings:
m_LogResourceManagerExceptions: 1

View File

@@ -0,0 +1,41 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bbb281ee3bf0b054c82ac2347e9e782c, type: 3}
m_Name: Settings
m_EditorClassIdentifier:
m_GroupName: Settings
m_GUID: c62e6f02418e19949bca4cccdd5fa02e
m_SerializeEntries:
- m_GUID: 328ce914b893df646be3ad3c62755453
m_Address: Settings/Developer/DivingDeveloperSettings
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 35bfcff00faa72c4eb272a9e8288f965
m_Address: Settings/PlayerFollowerSettings
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 8f5195fb013895049a19488fd4d8f2a1
m_Address: Settings/InteractionSettings
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: a9569848f604a6540827d4d4bb0a35c2
m_Address: Settings/DivingMinigameSettings
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
m_ReadOnly: 0
m_Settings: {fileID: 11400000, guid: 11da9bb90d9dd5848b4f7629415a6937, type: 2}
m_SchemaSet:
m_Schemas: []

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e25c7672a65b5974bb354fcfb2a8400c
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@@ -0,0 +1,195 @@
fileFormatVersion: 2
guid: 0a391f68acfee1041a26723b1dafb73b
TextureImporter:
internalIDToNameTable:
- first:
213: 1108211999407853544
second: MenuIcon_PLACEHOLDER_0
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: iOS
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: WindowsStoreApps
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: MenuIcon_PLACEHOLDER_0
rect:
serializedVersion: 2
x: 9
y: 8
width: 239
height: 240
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 8efc78021f8216f00800000000000000
internalID: 1108211999407853544
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
MenuIcon_PLACEHOLDER_0: 1108211999407853544
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -18,3 +18,5 @@ MonoBehaviour:
- {fileID: 458265635552197097, guid: a77d1e8b2fa8aa945a6f39b312536e0d, type: 3}
- {fileID: 552225285624929822, guid: e39992796d5459442be9967c77e27066, type: 3}
- {fileID: 7644433920135100480, guid: 12d242e44fe80ab44af852254b7cab0f, type: 3}
- {fileID: 1794231825201849485, guid: 6fb0d7fc6faad154b8c3e3cb7abb7c15, type: 3}
- {fileID: 6399527186463168339, guid: ac41583865245bc4bb3de6c15929b9fc, type: 3}

View File

@@ -12,6 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 951b5c8af5114086a865d4bb7eae4548, type: 3}
m_Name: Chocolate
m_EditorClassIdentifier:
_itemId: chocolate_4f2011c6
itemName: Chocolate
description: sweet nectar of gods that lures the beasts from bushes
mapSprite: {fileID: -509776585262497855, guid: c648336c825f7d7479582bbe4d95d0bc, type: 3}

View File

@@ -12,6 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 951b5c8af5114086a865d4bb7eae4548, type: 3}
m_Name: LureSpotB
m_EditorClassIdentifier:
_itemId: lurespotb_92c24cf9
itemName: LureSpotB
description: Place where we atract the chocobird
mapSprite: {fileID: 2640071299338251634, guid: 7c4c9881382767047aac78ca51b82923, type: 3}

View File

@@ -12,6 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 951b5c8af5114086a865d4bb7eae4548, type: 3}
m_Name: Ass
m_EditorClassIdentifier:
_itemId: ass_41f5d715
itemName: TestAss
description: Well... how do you like 'em?
mapSprite: {fileID: -5471482676633547895, guid: 77ab3d770c92d5344b36eee3293a0f94, type: 3}

View File

@@ -12,6 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 951b5c8af5114086a865d4bb7eae4548, type: 3}
m_Name: Ass1
m_EditorClassIdentifier:
itemName: TestAss
_itemId: ass1_5469eaae
itemName: TestAss1
description: Well... how do you like 'em?
mapSprite: {fileID: -5471482676633547895, guid: 77ab3d770c92d5344b36eee3293a0f94, type: 3}

View File

@@ -12,6 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 951b5c8af5114086a865d4bb7eae4548, type: 3}
m_Name: Ass2
m_EditorClassIdentifier:
itemName: TestAss
_itemId: ass2_c4e69d34
itemName: TestAss2
description: Well... how do you like 'em?
mapSprite: {fileID: 4013237533433454447, guid: 77ab3d770c92d5344b36eee3293a0f94, type: 3}

View File

@@ -12,6 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 951b5c8af5114086a865d4bb7eae4548, type: 3}
m_Name: Ass3
m_EditorClassIdentifier:
itemName: TestAss
_itemId: ass3_cb8f9cfb
itemName: TestAss3
description: Well... how do you like 'em?
mapSprite: {fileID: -8109988653212156562, guid: 77ab3d770c92d5344b36eee3293a0f94, type: 3}

View File

@@ -12,6 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 951b5c8af5114086a865d4bb7eae4548, type: 3}
m_Name: Axe
m_EditorClassIdentifier:
_itemId: axe_bf031e9e
itemName: Axe
description: Well... how do you like 'em?
mapSprite: {fileID: 6674386295937086461, guid: 3bd1c178a78fcd144965cd1731dc309b, type: 3}

View File

@@ -12,6 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 951b5c8af5114086a865d4bb7eae4548, type: 3}
m_Name: Bonfire
m_EditorClassIdentifier:
_itemId: bonfire_818563eb
itemName: Bonfire
description: Well... how do you like 'em?
mapSprite: {fileID: 6277786745957211492, guid: 016288f704d38e747a8eac9795051717, type: 3}

View File

@@ -12,6 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 951b5c8af5114086a865d4bb7eae4548, type: 3}
m_Name: Head
m_EditorClassIdentifier:
_itemId: head_c827d69b
itemName: Axe
description: Well... how do you like 'em?
mapSprite: {fileID: -1693247529382600072, guid: 77ab3d770c92d5344b36eee3293a0f94, type: 3}

View File

@@ -12,6 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 951b5c8af5114086a865d4bb7eae4548, type: 3}
m_Name: Meat
m_EditorClassIdentifier:
_itemId: meat_6500cc13
itemName: Meat
description: Well... how do you like 'em?
mapSprite: {fileID: 6282751622250221668, guid: 204325ac88be74d4d882a078c64cf5e1, type: 3}

View File

@@ -0,0 +1,18 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 951b5c8af5114086a865d4bb7eae4548, type: 3}
m_Name: PickupItemData
m_EditorClassIdentifier: AppleHillsScripts::PickupItemData
_itemId: pickupitemdata_10de237f
itemName:
description:
mapSprite: {fileID: 0}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b1cd8267212dd2349ad7e2b91ec5be11
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -12,6 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 951b5c8af5114086a865d4bb7eae4548, type: 3}
m_Name: FootballBall
m_EditorClassIdentifier:
_itemId: footballball_b37968c2
itemName: FootballBall
description: Ball that is used to attract the football bird.
mapSprite: {fileID: -6720685004267932717, guid: 88acd207b6a9e114ca3d3e59ac3aa550, type: 3}

View File

@@ -12,6 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 951b5c8af5114086a865d4bb7eae4548, type: 3}
m_Name: LureSpotA
m_EditorClassIdentifier:
_itemId: lurespota_19a6cf7c
itemName: LureSpotA
description: Place where we atract the footballbird
mapSprite: {fileID: -8438005379329254897, guid: fe735eb4f8856904caec179520dcb92f, type: 3}

View File

@@ -12,6 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 951b5c8af5114086a865d4bb7eae4548, type: 3}
m_Name: LureSpotC
m_EditorClassIdentifier:
_itemId: lurespotc_559f54b7
itemName: LureSpotC
description: Place where we atract the hammerbird
mapSprite: {fileID: 3009302558630513478, guid: 3aefb78ee1b7f6e4685d0fff00e24e3d, type: 3}

View File

@@ -12,6 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 951b5c8af5114086a865d4bb7eae4548, type: 3}
m_Name: Nails
m_EditorClassIdentifier:
_itemId: nails_2ecaef33
itemName: Nails
description: Nails used to lure the hammer bird out.
mapSprite: {fileID: 21300000, guid: 34b9ddb77aae2df4ab489b7bb8f16cff, type: 3}

View File

@@ -12,6 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 951b5c8af5114086a865d4bb7eae4548, type: 3}
m_Name: Bunfflers
m_EditorClassIdentifier:
_itemId: bunfflers_07f2a135
itemName: Bunfflers
description: Ear Mufflers made to put on the soundbird so it doesn't fly away.
mapSprite: {fileID: -8848419083337551572, guid: b285cfb6530624a44a95ec99a59d7215, type: 3}

View File

@@ -12,6 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 951b5c8af5114086a865d4bb7eae4548, type: 3}
m_Name: BurgerBuns
m_EditorClassIdentifier:
_itemId: burgerbuns_4ccd8772
itemName: BurgerBuns
description: A pack of Burguer Buns, they need to be combined with the headband
to get "Bunfflers"

View File

@@ -12,6 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 951b5c8af5114086a865d4bb7eae4548, type: 3}
m_Name: Headband
m_EditorClassIdentifier:
_itemId: headband_9a56f411
itemName: Headband
description: Item dropped by Uncle Kunt!
mapSprite: {fileID: 743298078511449570, guid: 6f463983177b1404ca39fa222f03a3b2, type: 3}

View File

@@ -12,6 +12,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 951b5c8af5114086a865d4bb7eae4548, type: 3}
m_Name: SoundBird
m_EditorClassIdentifier:
_itemId: soundbird_16b17ba9
itemName: SoundBird
description: Objective Bird, escapes if player makes sound when close to it, stays
quiet if earmufflers are applied.

8
Assets/Dialogue.meta Normal file
View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: dcec43b1a5d809b4187eb91cabd6b657
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,695 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &1
MonoBehaviour:
m_ObjectHideFlags: 61
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 790b4d75d92f4b0984310a268dbd952f, type: 3}
m_Name: TestDialogue
m_EditorClassIdentifier: Unity.GraphToolkit.Editor::Unity.GraphToolkit.Editor.Implementation.GraphObjectImp
m_GraphModel:
rid: 1219994508087787734
references:
version: 2
RefIds:
- rid: -2
type: {class: , ns: , asm: }
- rid: 1219994508087787734
type: {class: GraphModelImp, ns: Unity.GraphToolkit.Editor.Implementation, asm: Unity.GraphToolkit.Editor}
data:
m_Guid:
m_Value0: 12720528336768607292
m_Value1: 4541789886294233460
m_HashGuid:
serializedVersion: 2
Hash: 3c246244206588b074910791d6ad073f
m_Name:
m_GraphNodeModels:
- rid: 1219994508087787747
- rid: 1219994508087787749
- rid: 1219994508087787751
- rid: 1219994508087787764
- rid: 1219994508087787770
- rid: 1219994508087787776
m_GraphWireModels:
- rid: 1219994508087787755
- rid: 1219994508087787773
- rid: 1219994508087787779
- rid: 1219994508087787780
- rid: 1219994508087787813
m_GraphStickyNoteModels: []
m_GraphPlacematModels: []
m_GraphVariableModels:
- rid: 1219994508087787760
m_GraphPortalModels: []
m_SectionModels:
- rid: 1219994508087787735
m_LocalSubgraphs: []
m_LastKnownBounds:
serializedVersion: 2
x: 123
y: -65
width: 1698
height: 244
m_GraphElementMetaData:
- m_Guid:
m_Value0: 13346176596883742728
m_Value1: 18083586785705260694
m_HashGuid:
serializedVersion: 2
Hash: 0820e35ee72437b996f6e8e25ecef5fa
m_Category: 0
m_Index: 0
- m_Guid:
m_Value0: 356371523793864382
m_Value1: 4751895819492649258
m_HashGuid:
serializedVersion: 2
Hash: be46cc430316f2042ae9853a1220f241
m_Category: 0
m_Index: 1
- m_Guid:
m_Value0: 8593691416048532199
m_Value1: 6890539440515769320
m_HashGuid:
serializedVersion: 2
Hash: e77ae5c2cfec4277e8e3c20e1d1da05f
m_Category: 0
m_Index: 2
- m_Guid:
m_Value0: 7709580528075638554
m_Value1: 12466507236153719696
m_HashGuid:
serializedVersion: 2
Hash: 1a8737a7a4eefd6a907bc7e847ee01ad
m_Category: 2
m_Index: 0
- m_Guid:
m_Value0: 13887651235662800591
m_Value1: 935957084791214113
m_HashGuid:
serializedVersion: 2
Hash: cf26320a38d9bac02190fd7b0230fd0c
m_Category: 1
m_Index: 0
- m_Guid:
m_Value0: 4225538081375705477
m_Value1: 10816025756629798206
m_HashGuid:
serializedVersion: 2
Hash: 85d948457f20a43a3e0d65b11e3e1a96
m_Category: 0
m_Index: 3
- m_Guid:
m_Value0: 1990642935411556156
m_Value1: 16710028644464764280
m_HashGuid:
serializedVersion: 2
Hash: 3cbfd8ef332fa01b78a5ecc384f2e5e7
m_Category: 0
m_Index: 4
- m_Guid:
m_Value0: 5477022009621441144
m_Value1: 13992127810305260154
m_HashGuid:
serializedVersion: 2
Hash: 786a7bce7f4a024c7afa1b291c062ec2
m_Category: 2
m_Index: 1
- m_Guid:
m_Value0: 10537482371379217669
m_Value1: 805153394380735108
m_HashGuid:
serializedVersion: 2
Hash: 05c5ff0463a83c928482c30dbf7a2c0b
m_Category: 0
m_Index: 5
- m_Guid:
m_Value0: 10238952115911916765
m_Value1: 16796494752743159762
m_HashGuid:
serializedVersion: 2
Hash: ddfc297db310188ed2f7f768fc2219e9
m_Category: 2
m_Index: 2
- m_Guid:
m_Value0: 10375816761084646535
m_Value1: 15824079162718769611
m_HashGuid:
serializedVersion: 2
Hash: 8794feea5e4efe8fcb5183af286c9adb
m_Category: 2
m_Index: 3
- m_Guid:
m_Value0: 10491986159911335451
m_Value1: 18287880145942505208
m_HashGuid:
serializedVersion: 2
Hash: 1b76d4d1d2059b91f866d271199acbfd
m_Category: 2
m_Index: 4
m_EntryPoint:
rid: 1219994508087787747
m_Graph:
rid: 1219994508087787736
- rid: 1219994508087787735
type: {class: SectionModel, ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
data:
m_Guid:
m_Value0: 12939578175715148634
m_Value1: 2855330721591447007
m_HashGuid:
serializedVersion: 2
Hash: 5a03e642cb9d92b3dfcdb7c0292ca027
m_Version: 2
m_Items:
- rid: 1219994508087787760
m_Title:
- rid: 1219994508087787736
type: {class: DialogueGraph, ns: Editor.Dialogue, asm: AppleHillsEditor}
data:
- rid: 1219994508087787747
type: {class: UserNodeModelImp, ns: Unity.GraphToolkit.Editor.Implementation, asm: Unity.GraphToolkit.Editor}
data:
m_Guid:
m_Value0: 13346176596883742728
m_Value1: 18083586785705260694
m_HashGuid:
serializedVersion: 2
Hash: 0820e35ee72437b996f6e8e25ecef5fa
m_Version: 2
m_Position: {x: 316.4595, y: -65.01193}
m_Title:
m_Tooltip:
m_NodePreviewModel:
rid: -2
m_State: 0
m_InputConstantsById:
m_KeyList:
- SpeakerName
m_ValueList:
- rid: 1219994508087787766
m_InputPortInfos:
expandedPortsById:
m_KeyList: []
m_ValueList:
m_OutputPortInfos:
expandedPortsById:
m_KeyList: []
m_ValueList:
m_Collapsed: 0
m_CurrentModeIndex: 0
m_ElementColor:
m_Color: {r: 0, g: 0, b: 0, a: 0}
m_HasUserColor: 0
m_Node:
rid: 1219994508087787748
- rid: 1219994508087787748
type: {class: StartNode, ns: Editor.Dialogue, asm: AppleHillsEditor}
data:
- rid: 1219994508087787749
type: {class: UserNodeModelImp, ns: Unity.GraphToolkit.Editor.Implementation, asm: Unity.GraphToolkit.Editor}
data:
m_Guid:
m_Value0: 356371523793864382
m_Value1: 4751895819492649258
m_HashGuid:
serializedVersion: 2
Hash: be46cc430316f2042ae9853a1220f241
m_Version: 2
m_Position: {x: 1707.9503, y: -59.602116}
m_Title:
m_Tooltip:
m_NodePreviewModel:
rid: -2
m_State: 0
m_InputConstantsById:
m_KeyList: []
m_ValueList: []
m_InputPortInfos:
expandedPortsById:
m_KeyList: []
m_ValueList:
m_OutputPortInfos:
expandedPortsById:
m_KeyList: []
m_ValueList:
m_Collapsed: 0
m_CurrentModeIndex: 0
m_ElementColor:
m_Color: {r: 0, g: 0, b: 0, a: 0}
m_HasUserColor: 0
m_Node:
rid: 1219994508087787750
- rid: 1219994508087787750
type: {class: EndNode, ns: Editor.Dialogue, asm: AppleHillsEditor}
data:
- rid: 1219994508087787751
type: {class: UserNodeModelImp, ns: Unity.GraphToolkit.Editor.Implementation, asm: Unity.GraphToolkit.Editor}
data:
m_Guid:
m_Value0: 8593691416048532199
m_Value1: 6890539440515769320
m_HashGuid:
serializedVersion: 2
Hash: e77ae5c2cfec4277e8e3c20e1d1da05f
m_Version: 2
m_Position: {x: 530.97986, y: -60.683594}
m_Title:
m_Tooltip:
m_NodePreviewModel:
rid: -2
m_State: 0
m_InputConstantsById:
m_KeyList:
- __option_DialogueLineType
- __option_NoLines
- DefaultDialogueLine
- LoopThroughDefaultLines
m_ValueList:
- rid: 1219994508087787857
- rid: 1219994508087787858
- rid: 1219994508087787897
- rid: 1219994508087787904
m_InputPortInfos:
expandedPortsById:
m_KeyList: []
m_ValueList:
m_OutputPortInfos:
expandedPortsById:
m_KeyList: []
m_ValueList:
m_Collapsed: 0
m_CurrentModeIndex: 0
m_ElementColor:
m_Color: {r: 0, g: 0, b: 0, a: 0}
m_HasUserColor: 0
m_Node:
rid: 1219994508087787752
- rid: 1219994508087787752
type: {class: DialogueNode, ns: Editor.Dialogue, asm: AppleHillsEditor}
data:
- rid: 1219994508087787755
type: {class: WireModel, ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
data:
m_Guid:
m_Value0: 7709580528075638554
m_Value1: 12466507236153719696
m_HashGuid:
serializedVersion: 2
Hash: 1a8737a7a4eefd6a907bc7e847ee01ad
m_Version: 2
m_FromPortReference:
m_NodeModelGuid:
m_Value0: 13346176596883742728
m_Value1: 18083586785705260694
m_NodeModelHashGuid:
serializedVersion: 2
Hash: 0820e35ee72437b996f6e8e25ecef5fa
m_UniqueId: out
m_PortDirection: 2
m_PortOrientation: 0
m_Title: out
m_ToPortReference:
m_NodeModelGuid:
m_Value0: 8593691416048532199
m_Value1: 6890539440515769320
m_NodeModelHashGuid:
serializedVersion: 2
Hash: e77ae5c2cfec4277e8e3c20e1d1da05f
m_UniqueId: in
m_PortDirection: 1
m_PortOrientation: 0
m_Title: in
- rid: 1219994508087787760
type: {class: VariableDeclarationModel, ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
data:
m_Guid:
m_Value0: 13887651235662800591
m_Value1: 935957084791214113
m_HashGuid:
serializedVersion: 2
Hash: cf26320a38d9bac02190fd7b0230fd0c
m_Version: 2
m_Name: Anna-Lyse
m_UniqueId:
m_DataType:
m_Identification: System.String, System.Private.CoreLib, Version=4.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089
m_IsExposed: 0
m_Scope: 0
m_ShowOnInspectorOnly: 0
m_Tooltip:
m_InitializationValue:
rid: 1219994508087787761
m_Modifiers: 0
m_VariableFlags: 0
- rid: 1219994508087787761
type: {class: 'Constant`1[[System.String, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
data:
m_Value: Anna-Lyse
- rid: 1219994508087787764
type: {class: VariableNodeModelImp, ns: Unity.GraphToolkit.Editor.Implementation, asm: Unity.GraphToolkit.Editor}
data:
m_Guid:
m_Value0: 4225538081375705477
m_Value1: 10816025756629798206
m_HashGuid:
serializedVersion: 2
Hash: 85d948457f20a43a3e0d65b11e3e1a96
m_Version: 2
m_Position: {x: 123.485, y: -64.61}
m_Title: Anna-Lyse
m_Tooltip:
m_NodePreviewModel:
rid: -2
m_State: 0
m_InputConstantsById:
m_KeyList: []
m_ValueList: []
m_InputPortInfos:
expandedPortsById:
m_KeyList: []
m_ValueList:
m_OutputPortInfos:
expandedPortsById:
m_KeyList: []
m_ValueList:
m_Collapsed: 0
m_CurrentModeIndex: 0
m_ElementColor:
m_Color: {r: 0, g: 0, b: 0, a: 0}
m_HasUserColor: 0
m_DeclarationModel:
rid: 1219994508087787760
m_DeclarationModelHashGuid:
serializedVersion: 2
Hash: cf26320a38d9bac02190fd7b0230fd0c
- rid: 1219994508087787766
type: {class: 'Constant`1[[System.String, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
data:
m_Value:
- rid: 1219994508087787770
type: {class: UserNodeModelImp, ns: Unity.GraphToolkit.Editor.Implementation, asm: Unity.GraphToolkit.Editor}
data:
m_Guid:
m_Value0: 1990642935411556156
m_Value1: 16710028644464764280
m_HashGuid:
serializedVersion: 2
Hash: 3cbfd8ef332fa01b78a5ecc384f2e5e7
m_Version: 2
m_Position: {x: 914.5827, y: -58.93837}
m_Title: DialogueNode
m_Tooltip:
m_NodePreviewModel:
rid: -2
m_State: 0
m_InputConstantsById:
m_KeyList:
- __option_DialogueLineType
- __option_NoLines
- DefaultDialogueLine1
- DefaultDialogueLine2
- DefaultDialogueLine3
- LoopThroughDefaultLines
m_ValueList:
- rid: 1219994508087787860
- rid: 1219994508087787861
- rid: 1219994508087787900
- rid: 1219994508087787901
- rid: 1219994508087787902
- rid: 1219994508087787905
m_InputPortInfos:
expandedPortsById:
m_KeyList: []
m_ValueList:
m_OutputPortInfos:
expandedPortsById:
m_KeyList: []
m_ValueList:
m_Collapsed: 0
m_CurrentModeIndex: 0
m_ElementColor:
m_Color: {r: 0, g: 0, b: 0, a: 0}
m_HasUserColor: 0
m_Node:
rid: 1219994508087787772
- rid: 1219994508087787772
type: {class: DialogueNode, ns: Editor.Dialogue, asm: AppleHillsEditor}
data:
- rid: 1219994508087787773
type: {class: WireModel, ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
data:
m_Guid:
m_Value0: 5477022009621441144
m_Value1: 13992127810305260154
m_HashGuid:
serializedVersion: 2
Hash: 786a7bce7f4a024c7afa1b291c062ec2
m_Version: 2
m_FromPortReference:
m_NodeModelGuid:
m_Value0: 8593691416048532199
m_Value1: 6890539440515769320
m_NodeModelHashGuid:
serializedVersion: 2
Hash: e77ae5c2cfec4277e8e3c20e1d1da05f
m_UniqueId: out
m_PortDirection: 2
m_PortOrientation: 0
m_Title: out
m_ToPortReference:
m_NodeModelGuid:
m_Value0: 1990642935411556156
m_Value1: 16710028644464764280
m_NodeModelHashGuid:
serializedVersion: 2
Hash: 3cbfd8ef332fa01b78a5ecc384f2e5e7
m_UniqueId: in
m_PortDirection: 1
m_PortOrientation: 0
m_Title: in
- rid: 1219994508087787776
type: {class: UserNodeModelImp, ns: Unity.GraphToolkit.Editor.Implementation, asm: Unity.GraphToolkit.Editor}
data:
m_Guid:
m_Value0: 10537482371379217669
m_Value1: 805153394380735108
m_HashGuid:
serializedVersion: 2
Hash: 05c5ff0463a83c928482c30dbf7a2c0b
m_Version: 2
m_Position: {x: 1294.008, y: -60.75061}
m_Title: DialogueNode
m_Tooltip:
m_NodePreviewModel:
rid: -2
m_State: 0
m_InputConstantsById:
m_KeyList:
- __option_DialogueLineType
- __option_NoLines
- DefaultDialogueLine
- LoopThroughDefaultLines
m_ValueList:
- rid: 1219994508087787863
- rid: 1219994508087787864
- rid: 1219994508087787898
- rid: 1219994508087787906
m_InputPortInfos:
expandedPortsById:
m_KeyList: []
m_ValueList:
m_OutputPortInfos:
expandedPortsById:
m_KeyList: []
m_ValueList:
m_Collapsed: 0
m_CurrentModeIndex: 0
m_ElementColor:
m_Color: {r: 0, g: 0, b: 0, a: 0}
m_HasUserColor: 0
m_Node:
rid: 1219994508087787778
- rid: 1219994508087787778
type: {class: DialogueNode, ns: Editor.Dialogue, asm: AppleHillsEditor}
data:
- rid: 1219994508087787779
type: {class: WireModel, ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
data:
m_Guid:
m_Value0: 10238952115911916765
m_Value1: 16796494752743159762
m_HashGuid:
serializedVersion: 2
Hash: ddfc297db310188ed2f7f768fc2219e9
m_Version: 2
m_FromPortReference:
m_NodeModelGuid:
m_Value0: 1990642935411556156
m_Value1: 16710028644464764280
m_NodeModelHashGuid:
serializedVersion: 2
Hash: 3cbfd8ef332fa01b78a5ecc384f2e5e7
m_UniqueId: out
m_PortDirection: 2
m_PortOrientation: 0
m_Title: out
m_ToPortReference:
m_NodeModelGuid:
m_Value0: 10537482371379217669
m_Value1: 805153394380735108
m_NodeModelHashGuid:
serializedVersion: 2
Hash: 05c5ff0463a83c928482c30dbf7a2c0b
m_UniqueId: in
m_PortDirection: 1
m_PortOrientation: 0
m_Title: in
- rid: 1219994508087787780
type: {class: WireModel, ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
data:
m_Guid:
m_Value0: 10375816761084646535
m_Value1: 15824079162718769611
m_HashGuid:
serializedVersion: 2
Hash: 8794feea5e4efe8fcb5183af286c9adb
m_Version: 2
m_FromPortReference:
m_NodeModelGuid:
m_Value0: 10537482371379217669
m_Value1: 805153394380735108
m_NodeModelHashGuid:
serializedVersion: 2
Hash: 05c5ff0463a83c928482c30dbf7a2c0b
m_UniqueId: out
m_PortDirection: 2
m_PortOrientation: 0
m_Title: out
m_ToPortReference:
m_NodeModelGuid:
m_Value0: 356371523793864382
m_Value1: 4751895819492649258
m_NodeModelHashGuid:
serializedVersion: 2
Hash: be46cc430316f2042ae9853a1220f241
m_UniqueId: in
m_PortDirection: 1
m_PortOrientation: 0
m_Title: in
- rid: 1219994508087787813
type: {class: WireModel, ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
data:
m_Guid:
m_Value0: 10491986159911335451
m_Value1: 18287880145942505208
m_HashGuid:
serializedVersion: 2
Hash: 1b76d4d1d2059b91f866d271199acbfd
m_Version: 2
m_FromPortReference:
m_NodeModelGuid:
m_Value0: 4225538081375705477
m_Value1: 10816025756629798206
m_NodeModelHashGuid:
serializedVersion: 2
Hash: 85d948457f20a43a3e0d65b11e3e1a96
m_UniqueId: MainPortName
m_PortDirection: 2
m_PortOrientation: 0
m_Title: MainPortName
m_ToPortReference:
m_NodeModelGuid:
m_Value0: 13346176596883742728
m_Value1: 18083586785705260694
m_NodeModelHashGuid:
serializedVersion: 2
Hash: 0820e35ee72437b996f6e8e25ecef5fa
m_UniqueId: SpeakerName
m_PortDirection: 1
m_PortOrientation: 0
m_Title: SpeakerName
- rid: 1219994508087787857
type: {class: EnumConstant, ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
data:
m_Value:
m_EnumType:
m_Identification: Editor.Dialogue.DialogueType, AppleHillsEditor, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null
m_Value: 0
m_EnumType:
m_Identification: Editor.Dialogue.DialogueType, AppleHillsEditor, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null
- rid: 1219994508087787858
type: {class: 'Constant`1[[System.Int32, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
data:
m_Value: 1
- rid: 1219994508087787860
type: {class: EnumConstant, ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
data:
m_Value:
m_EnumType:
m_Identification: Editor.Dialogue.DialogueType, AppleHillsEditor, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null
m_Value: 1
m_EnumType:
m_Identification: Editor.Dialogue.DialogueType, AppleHillsEditor, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null
- rid: 1219994508087787861
type: {class: 'Constant`1[[System.Int32, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
data:
m_Value: 3
- rid: 1219994508087787863
type: {class: EnumConstant, ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
data:
m_Value:
m_EnumType:
m_Identification: Editor.Dialogue.DialogueType, AppleHillsEditor, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null
m_Value: 0
m_EnumType:
m_Identification: Editor.Dialogue.DialogueType, AppleHillsEditor, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null
- rid: 1219994508087787864
type: {class: 'Constant`1[[System.Int32, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
data:
m_Value: 1
- rid: 1219994508087787897
type: {class: 'Constant`1[[System.String, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
data:
m_Value: This is a test line
- rid: 1219994508087787898
type: {class: 'Constant`1[[System.String, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
data:
m_Value: Another regular line
- rid: 1219994508087787900
type: {class: 'Constant`1[[System.String, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
data:
m_Value: One multiline
- rid: 1219994508087787901
type: {class: 'Constant`1[[System.String, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
data:
m_Value: Two multiline
- rid: 1219994508087787902
type: {class: 'Constant`1[[System.String, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
data:
m_Value: Three multiline
- rid: 1219994508087787904
type: {class: 'Constant`1[[System.Boolean, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
data:
m_Value: 0
- rid: 1219994508087787905
type: {class: 'Constant`1[[System.Boolean, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
data:
m_Value: 0
- rid: 1219994508087787906
type: {class: 'Constant`1[[System.Boolean, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
data:
m_Value: 0

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9050f99a225035b40b415df272d2b341
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -4,7 +4,9 @@
"references": [
"GUID:d91d3f46515a6954caa674697afbf416",
"GUID:69448af7b92c7f342b298e06a37122aa",
"GUID:9e24947de15b9834991c9d8411ea37cf"
"GUID:9e24947de15b9834991c9d8411ea37cf",
"GUID:70ef9a24f4cfc4aec911c1414e3f90ad",
"GUID:d1e08c06f8f9473888c892637c83c913"
],
"includePlatforms": [
"Editor"

View File

@@ -0,0 +1,207 @@
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.Linq;
using System.IO;
namespace AppleHills.Core.Settings.Editor
{
public class DeveloperSettingsEditorWindow : EditorWindow
{
private Vector2 scrollPosition;
private List<BaseDeveloperSettings> allDeveloperSettings = new List<BaseDeveloperSettings>();
private string[] tabNames = new string[] { "Diving", "Other Systems" }; // Add more tabs as needed
private int selectedTab = 0;
private Dictionary<string, SerializedObject> serializedSettingsObjects = new Dictionary<string, SerializedObject>();
private GUIStyle headerStyle;
[MenuItem("AppleHills/Developer Settings Editor")]
public static void ShowWindow()
{
GetWindow<DeveloperSettingsEditorWindow>("Developer Settings");
}
private void OnEnable()
{
LoadAllSettings();
}
private void LoadAllSettings()
{
allDeveloperSettings.Clear();
serializedSettingsObjects.Clear();
// Find all developer settings assets
string[] guids = AssetDatabase.FindAssets("t:BaseDeveloperSettings");
foreach (string guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
BaseDeveloperSettings settings = AssetDatabase.LoadAssetAtPath<BaseDeveloperSettings>(path);
if (settings != null)
{
allDeveloperSettings.Add(settings);
serializedSettingsObjects[settings.GetType().Name] = new SerializedObject(settings);
}
}
// If any settings are missing, create them
CreateSettingsIfMissing<DivingDeveloperSettings>("DivingDeveloperSettings");
// Add more developer settings types here as needed
// CreateSettingsIfMissing<OtherDeveloperSettings>("OtherDeveloperSettings");
}
private void CreateSettingsIfMissing<T>(string fileName) where T : BaseDeveloperSettings
{
if (!allDeveloperSettings.Any(s => s is T))
{
// Check if the asset already exists
string[] guids = AssetDatabase.FindAssets($"t:{typeof(T).Name}");
if (guids.Length == 0)
{
// Create the settings folder if it doesn't exist
string settingsFolder = "Assets/Settings/Developer";
if (!AssetDatabase.IsValidFolder("Assets/Settings"))
{
AssetDatabase.CreateFolder("Assets", "Settings");
}
if (!AssetDatabase.IsValidFolder(settingsFolder))
{
AssetDatabase.CreateFolder("Assets/Settings", "Developer");
}
// Create new settings asset
T settings = CreateInstance<T>();
string path = $"{settingsFolder}/{fileName}.asset";
AssetDatabase.CreateAsset(settings, path);
AssetDatabase.SaveAssets();
allDeveloperSettings.Add(settings);
serializedSettingsObjects[typeof(T).Name] = new SerializedObject(settings);
Debug.Log($"Created missing developer settings asset: {path}");
}
else
{
// Load existing asset
string path = AssetDatabase.GUIDToAssetPath(guids[0]);
T settings = AssetDatabase.LoadAssetAtPath<T>(path);
allDeveloperSettings.Add(settings);
serializedSettingsObjects[typeof(T).Name] = new SerializedObject(settings);
}
}
}
private void OnGUI()
{
if (headerStyle == null)
{
headerStyle = new GUIStyle(EditorStyles.boldLabel);
headerStyle.fontSize = 14;
headerStyle.margin = new RectOffset(0, 0, 10, 10);
}
EditorGUILayout.Space(10);
EditorGUILayout.LabelField("Apple Hills Developer Settings", headerStyle);
EditorGUILayout.HelpBox("This editor is for technical settings intended for developers. For gameplay settings, use the Game Settings editor.", MessageType.Info);
EditorGUILayout.Space(10);
selectedTab = GUILayout.Toolbar(selectedTab, tabNames);
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
switch (selectedTab)
{
case 0: // Diving
DrawSettingsEditor<DivingDeveloperSettings>();
break;
case 1: // Other Systems
EditorGUILayout.HelpBox("Other developer settings will appear here as they are added.", MessageType.Info);
break;
// Add additional cases as more developer settings types are added
}
EditorGUILayout.EndScrollView();
EditorGUILayout.Space(10);
EditorGUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button("Refresh", GUILayout.Width(100)))
{
LoadAllSettings();
}
if (GUILayout.Button("Save All", GUILayout.Width(100)))
{
foreach (var serializedObj in serializedSettingsObjects.Values)
{
serializedObj.ApplyModifiedProperties();
EditorUtility.SetDirty(serializedObj.targetObject);
}
AssetDatabase.SaveAssets();
Debug.Log("All developer settings saved!");
}
EditorGUILayout.EndHorizontal();
}
private void DrawSettingsEditor<T>() where T : BaseDeveloperSettings
{
BaseDeveloperSettings settings = allDeveloperSettings.Find(s => s is T);
if (settings == null)
{
EditorGUILayout.HelpBox($"No {typeof(T).Name} found. Click Refresh to create one.", MessageType.Warning);
return;
}
SerializedObject serializedObj = serializedSettingsObjects[typeof(T).Name];
serializedObj.Update();
EditorGUILayout.Space(10);
// Draw all properties
SerializedProperty property = serializedObj.GetIterator();
bool enterChildren = true;
while (property.NextVisible(enterChildren))
{
enterChildren = false;
// Skip the script field
if (property.name == "m_Script") continue;
// Group headers
if (property.isArray && property.propertyType == SerializedPropertyType.Generic)
{
EditorGUILayout.LabelField(property.displayName, EditorStyles.boldLabel);
}
EditorGUILayout.PropertyField(property, true);
}
// Apply changes
if (serializedObj.ApplyModifiedProperties())
{
EditorUtility.SetDirty(settings);
// Trigger OnValidate on the asset
if (settings != null)
{
settings.OnValidate();
}
}
}
// Helper method to highlight important fields
private void DrawHighlightedProperty(SerializedProperty property, string tooltip = null)
{
GUI.backgroundColor = new Color(0.8f, 0.9f, 1f); // Light blue for developer settings
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
GUI.backgroundColor = Color.white;
EditorGUILayout.PropertyField(property, new GUIContent(property.displayName, tooltip));
EditorGUILayout.EndVertical();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 8ab6d9fee0924431b8e22edb500b35df
timeCreated: 1758710778

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5ced9daeaad4427f9feb953a53b6d3df
timeCreated: 1758869763

View File

@@ -0,0 +1,20 @@
using System;
using UnityEngine;
using UnityEditor;
using Unity.GraphToolkit.Editor;
namespace Editor.Dialogue
{
[Serializable]
[Graph(AssetExtension)]
public class DialogueGraph : Graph
{
public const string AssetExtension = "dialoguegraph";
[MenuItem("Assets/Create/Dialogue Graph", false)]
private static void CreateAssetFile()
{
GraphDatabase.PromptInProjectBrowserToCreateNewAsset<DialogueGraph>();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: eff5cdbb7a22496e93560cffa5754029
timeCreated: 1758869773

View File

@@ -0,0 +1,246 @@
using UnityEngine;
using UnityEditor.AssetImporters;
using Unity.GraphToolkit.Editor;
using System;
using System.Collections.Generic;
using System.Linq;
using Dialogue;
using PuzzleS;
namespace Editor.Dialogue
{
[ScriptedImporter(1, DialogueGraph.AssetExtension)]
public class DialogueGraphImporter : ScriptedImporter
{
public override void OnImportAsset(AssetImportContext ctx)
{
DialogueGraph editorGraph = GraphDatabase.LoadGraphForImporter<DialogueGraph>(ctx.assetPath);
RuntimeDialogueGraph runtimeGraph = ScriptableObject.CreateInstance<RuntimeDialogueGraph>();
var nodeIDMap = new Dictionary<INode, string>();
// Generate stable GUIDs for each node
foreach (var node in editorGraph.GetNodes())
{
nodeIDMap[node] = Guid.NewGuid().ToString();
}
// Process start node to get entry point and speaker name
var startNode = editorGraph.GetNodes().OfType<StartNode>().FirstOrDefault();
if (startNode != null)
{
var entryPoint = startNode.GetOutputPorts().FirstOrDefault()?.firstConnectedPort;
if (entryPoint != null)
{
runtimeGraph.entryNodeID = nodeIDMap[entryPoint.GetNode()];
}
runtimeGraph.speakerName = GetPortValue<string>(startNode.GetInputPortByName("SpeakerName"));
}
// Process each node in the graph
foreach (var iNode in editorGraph.GetNodes())
{
if (iNode is StartNode || iNode is IVariableNode)
continue;
var runtimeNode = new RuntimeDialogueNode{ nodeID = nodeIDMap[iNode] };
// Process node based on its type
if (iNode is DialogueNode dialogueNode)
{
if (iNode is WaitOnPuzzleStep puzzleNode)
{
ProcessPuzzleNode(puzzleNode, runtimeNode);
}
else if (iNode is WaitOnPickup pickupNode)
{
ProcessPickupNode(pickupNode, runtimeNode);
}
else if (iNode is WaitOnSlot slotNode)
{
ProcessSlotNode(slotNode, runtimeNode);
}
// Process base dialogue node properties (for all node types)
ProcessDialogueNodeBase(dialogueNode, runtimeNode);
}
else if (iNode is EndNode)
{
runtimeNode.nodeType = RuntimeDialogueNodeType.End;
// End nodes don't have next nodes, so we don't need to look for "out" ports
}
// Get next node connection (skip for EndNodes as they don't have out ports)
if (!(iNode is EndNode))
{
// Check if the node has output ports before trying to get one by name
var outputPorts = iNode.GetOutputPorts();
if (outputPorts != null && outputPorts.Any())
{
var outPort = outputPorts.FirstOrDefault(p => p.name == "out");
if (outPort != null && outPort.firstConnectedPort != null)
{
runtimeNode.nextNodeID = nodeIDMap[outPort.firstConnectedPort.GetNode()];
}
}
}
// Add node to runtime graph
runtimeGraph.allNodes.Add(runtimeNode);
}
ctx.AddObjectToAsset("RuntimeData", runtimeGraph);
ctx.SetMainObject(runtimeGraph);
Debug.Log($"Imported DialogueGraph with {runtimeGraph.allNodes.Count} nodes.");
}
private void ProcessDialogueNodeBase(DialogueNode node, RuntimeDialogueNode runtimeNode)
{
// Set default node type
runtimeNode.nodeType = RuntimeDialogueNodeType.Dialogue;
// Get line type and count options
var lineTypeOption = node.GetNodeOptionByName("DialogueLineType");
lineTypeOption.TryGetValue<DialogueType>(out var lineType);
var lineCountOption = node.GetNodeOptionByName("NoLines");
lineCountOption.TryGetValue<int>(out var lineCount);
// Process dialogue lines based on line type
if (lineType == DialogueType.SayMultipleLines)
{
for (var i = 0; i < lineCount; i++)
{
var lineValue = GetPortValue<string>(node.GetInputPortByName($"DefaultDialogueLine{i + 1}"));
if (!string.IsNullOrEmpty(lineValue))
{
runtimeNode.dialogueLines.Add(lineValue);
}
}
}
else
{
var lineValue = GetPortValue<string>(node.GetInputPortByName("DefaultDialogueLine"));
if (!string.IsNullOrEmpty(lineValue))
{
runtimeNode.dialogueLines.Add(lineValue);
}
}
// Get loop through lines option
var loopThroughLines = GetPortValue<bool>(node.GetInputPortByName("LoopThroughDefaultLines"));
runtimeNode.loopThroughLines = loopThroughLines;
}
private void ProcessPuzzleNode(WaitOnPuzzleStep node, RuntimeDialogueNode runtimeNode)
{
runtimeNode.nodeType = RuntimeDialogueNodeType.WaitOnPuzzleStep;
var puzzleStep = GetPortValue<PuzzleStepSO>(node.GetInputPortByName("RequiredPuzzleStep"));
if (puzzleStep != null)
{
runtimeNode.puzzleStepID = puzzleStep.stepId;
}
}
private void ProcessPickupNode(WaitOnPickup node, RuntimeDialogueNode runtimeNode)
{
runtimeNode.nodeType = RuntimeDialogueNodeType.WaitOnPickup;
var pickup = GetPortValue<PickupItemData>(node.GetInputPortByName("RequiredPickup"));
if (pickup != null)
{
runtimeNode.pickupItemID = pickup.itemId;
}
}
private void ProcessSlotNode(WaitOnSlot node, RuntimeDialogueNode runtimeNode)
{
runtimeNode.nodeType = RuntimeDialogueNodeType.WaitOnSlot;
var slot = GetPortValue<PickupItemData>(node.GetInputPortByName("RequiredSlot"));
if (slot != null)
{
runtimeNode.slotItemID = slot.itemId;
}
// Process incorrect item lines
var incorrectItemLineTypeOption = node.GetNodeOptionByName("IncorrectItemDialogueLineType");
incorrectItemLineTypeOption.TryGetValue<DialogueType>(out var incorrectItemLineType);
var incorrectItemLineCountOption = node.GetNodeOptionByName("IncorrectItemNoLines");
incorrectItemLineCountOption.TryGetValue<int>(out var incorrectItemLineCount);
if (incorrectItemLineType == DialogueType.SayMultipleLines)
{
for (var i = 0; i < incorrectItemLineCount; i++)
{
var lineValue = GetPortValue<string>(node.GetInputPortByName($"IncorrectItemDialogueLine{i + 1}"));
if (!string.IsNullOrEmpty(lineValue))
{
runtimeNode.incorrectItemLines.Add(lineValue);
}
}
}
else
{
var lineValue = GetPortValue<string>(node.GetInputPortByName("IncorrectItemDialogueLine"));
if (!string.IsNullOrEmpty(lineValue))
{
runtimeNode.incorrectItemLines.Add(lineValue);
}
}
runtimeNode.loopThroughIncorrectLines =
GetPortValue<bool>(node.GetInputPortByName("LoopThroughIncorrectItemLines"));
// Process forbidden item lines
var forbiddenItemLineTypeOption = node.GetNodeOptionByName("ForbiddenItemDialogueLineType");
forbiddenItemLineTypeOption.TryGetValue<DialogueType>(out var forbiddenItemLineType);
var forbiddenItemLineCountOption = node.GetNodeOptionByName("ForbiddenItemNoLines");
forbiddenItemLineCountOption.TryGetValue<int>(out var forbiddenItemLineCount);
if (forbiddenItemLineType == DialogueType.SayMultipleLines)
{
for (var i = 0; i < forbiddenItemLineCount; i++)
{
var lineValue = GetPortValue<string>(node.GetInputPortByName($"ForbiddenItemDialogueLine{i + 1}"));
if (!string.IsNullOrEmpty(lineValue))
{
runtimeNode.forbiddenItemLines.Add(lineValue);
}
}
}
else
{
var lineValue = GetPortValue<string>(node.GetInputPortByName("ForbiddenItemDialogueLine"));
if (!string.IsNullOrEmpty(lineValue))
{
runtimeNode.forbiddenItemLines.Add(lineValue);
}
}
runtimeNode.loopThroughForbiddenLines =
GetPortValue<bool>(node.GetInputPortByName("LoopThroughForbiddenItemLines"));
}
private T GetPortValue<T>(IPort port)
{
if (port == null) return default(T);
if (port.isConnected)
{
if (port.firstConnectedPort.GetNode() is IVariableNode variableNode)
{
variableNode.variable.TryGetDefaultValue(out T value);
return value;
}
}
port.TryGetValue(out T fallbackValue);
return fallbackValue;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a2334d3ee5254a2bbcb316035c681b27
timeCreated: 1758871584

View File

@@ -0,0 +1,196 @@
using UnityEngine;
using Unity.GraphToolkit.Editor;
using System;
namespace Editor.Dialogue
{
[Serializable]
public class StartNode : Node
{
protected override void OnDefinePorts(IPortDefinitionContext context)
{
context.AddOutputPort("out").Build();
context.AddInputPort<string>("SpeakerName").Build();
}
}
[Serializable]
public class EndNode : Node
{
protected override void OnDefinePorts(IPortDefinitionContext context)
{
context.AddInputPort("in").Build();
}
}
[Serializable]
public enum DialogueType
{
SayOneLine,
SayMultipleLines
}
[Serializable]
public class DialogueNode : Node
{
const string LineTypeOptionName = "DialogueLineType";
const string NoLinesOptionName = "NoLines";
const string LoopThroughDefaultLinesOptionName = "LoopThroughDefaultLines";
const string DefaultDialogueLineOptionName = "DefaultDialogueLine";
protected override void OnDefineOptions(IOptionDefinitionContext context)
{
context.AddOption<DialogueType>(LineTypeOptionName)
.WithDisplayName("Default Line Type")
.WithDefaultValue(DialogueType.SayOneLine)
.Delayed();
context.AddOption<int>(NoLinesOptionName)
.WithDisplayName("Number of Default Lines")
.WithDefaultValue(1)
.Delayed();
}
protected override void OnDefinePorts(IPortDefinitionContext context)
{
context.AddInputPort("in").Build();
context.AddOutputPort("out").Build();
var lineTypeOption = GetNodeOptionByName(LineTypeOptionName);
lineTypeOption.TryGetValue<DialogueType>(out var lineType);
var lineCountOption = GetNodeOptionByName(NoLinesOptionName);
lineCountOption.TryGetValue<int>(out var lineCount);
if (lineType == DialogueType.SayMultipleLines)
{
for (var i = 0; i < lineCount; i++)
{
context.AddInputPort<string>($"{DefaultDialogueLineOptionName}{i + 1}").WithDisplayName($"Default Dialogue Line {i + 1}").Build();
}
}
else
{
context.AddInputPort<string>($"{DefaultDialogueLineOptionName}").WithDisplayName("Default Dialogue Line").Build();
}
context.AddInputPort<bool>($"{LoopThroughDefaultLinesOptionName}").WithDisplayName("Loop Through Default Lines?").Build();
}
}
[Serializable]
public class WaitOnPuzzleStep : DialogueNode
{
const string RequiredPuzzleStep = "RequiredPuzzleStep";
protected override void OnDefinePorts(IPortDefinitionContext context)
{
context.AddInputPort<PuzzleStepSO>(RequiredPuzzleStep).WithDisplayName("Required Puzzle Step").Build();
base.OnDefinePorts(context);
}
}
[Serializable]
public class WaitOnPickup : DialogueNode
{
const string RequiredPickupsOptionName = "RequiredPickup";
protected override void OnDefinePorts(IPortDefinitionContext context)
{
context.AddInputPort<PickupItemData>(RequiredPickupsOptionName).WithDisplayName("Required Pickup").Build();
base.OnDefinePorts(context);
}
}
[Serializable]
public class WaitOnSlot : DialogueNode
{
const string RequiredSlotOptionName = "RequiredSlot";
// Incorrect item - i.e. not the correct one but also not forbidden
const string IncorrectItemLineTypeOptionName = "IncorrectItemDialogueLineType";
const string IncorrectItemNoLinesOptionName = "IncorrectItemNoLines";
const string LoopThroughIncorrectItemLinesOptionName = "LoopThroughIncorrectItemLines";
const string IncorrectIteDialogueLineOptionName = "IncorrectItemDialogueLine";
// Explicitely forbidden item
const string ForbiddenItemLineTypeOptionName = "ForbiddenItemDialogueLineType";
const string ForbiddenItemNoLinesOptionName = "ForbiddenItemNoLines";
const string LoopThroughForbiddenItemLinesOptionName = "LoopThroughForbiddenItemLines";
const string ForbiddenIteDialogueLineOptionName = "ForbiddenItemDialogueLine";
protected override void OnDefineOptions(IOptionDefinitionContext context)
{
base.OnDefineOptions(context);
// Incorrect
context.AddOption<DialogueType>(IncorrectItemLineTypeOptionName)
.WithDisplayName("Incorrect Item Line Type")
.WithDefaultValue(DialogueType.SayOneLine)
.Delayed();
context.AddOption<int>(IncorrectItemNoLinesOptionName)
.WithDisplayName("Number of Incorrect Item Lines")
.WithDefaultValue(1)
.Delayed();
// Forbidden
context.AddOption<DialogueType>(ForbiddenItemLineTypeOptionName)
.WithDisplayName("Forbidden Item Line Type")
.WithDefaultValue(DialogueType.SayOneLine)
.Delayed();
context.AddOption<int>(ForbiddenItemNoLinesOptionName)
.WithDisplayName("Forbidden of Incorrect Item Lines")
.WithDefaultValue(1)
.Delayed();
}
protected override void OnDefinePorts(IPortDefinitionContext context)
{
context.AddInputPort<PickupItemData>(RequiredSlotOptionName).WithDisplayName("Required Slot").Build();
base.OnDefinePorts(context);
// Incorrect
var incorrectItemLineTypeOption = GetNodeOptionByName(IncorrectItemLineTypeOptionName);
incorrectItemLineTypeOption.TryGetValue<DialogueType>(out var incorrectItemLineType);
var incorrectItemLineCountOption = GetNodeOptionByName(IncorrectItemNoLinesOptionName);
incorrectItemLineCountOption.TryGetValue<int>(out var incorrectItemLineCount);
if (incorrectItemLineType == DialogueType.SayMultipleLines)
{
for (var i = 0; i < incorrectItemLineCount; i++)
{
context.AddInputPort<string>($"{IncorrectIteDialogueLineOptionName}{i + 1}").WithDisplayName($"Incorrect Item Dialogue Line {i + 1}").Build();
}
}
else
{
context.AddInputPort<string>($"{IncorrectIteDialogueLineOptionName}").WithDisplayName("Incorrect Item Dialogue Line").Build();
}
context.AddInputPort<bool>($"{LoopThroughIncorrectItemLinesOptionName}").WithDisplayName("Loop Through Incorrect Item Lines?").Build();
// Forbidden
var forbiddenItemLineTypeOption = GetNodeOptionByName(ForbiddenItemLineTypeOptionName);
forbiddenItemLineTypeOption.TryGetValue<DialogueType>(out var forbiddenItemLineType);
var forbiddenItemLineCountOption = GetNodeOptionByName(ForbiddenItemNoLinesOptionName);
forbiddenItemLineCountOption.TryGetValue<int>(out var forbiddenItemLineCount);
if (forbiddenItemLineType == DialogueType.SayMultipleLines)
{
for (var i = 0; i < forbiddenItemLineCount; i++)
{
context.AddInputPort<string>($"{ForbiddenIteDialogueLineOptionName}{i + 1}").WithDisplayName($"Forbidden Item Dialogue Line {i + 1}").Build();
}
}
else
{
context.AddInputPort<string>($"{ForbiddenIteDialogueLineOptionName}").WithDisplayName("Forbidden Item Dialogue Line").Build();
}
context.AddInputPort<bool>($"{LoopThroughForbiddenItemLinesOptionName}").WithDisplayName("Loop Through Forbidden Item Lines?").Build();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a8b3213c46b447a9adc5627a273f2b2d
timeCreated: 1758870466

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 DivingMinigameSettings _divingMinigameSettings;
// 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");
_divingMinigameSettings = AssetDatabase.LoadAssetAtPath<DivingMinigameSettings>("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(DivingMinigameSettings))
return _divingMinigameSettings as T;
return null;
}
}
}

View File

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

View File

@@ -18,7 +18,7 @@ namespace Editor
private enum ItemType { None, Pickup, ItemSlot }
private ItemType _itemType = ItemType.None;
[MenuItem("Tools/Item Prefab Editor")]
[MenuItem("AppleHills/Item Prefab Editor")]
public static void ShowWindow()
{
var window = GetWindow<ItemPrefabEditorWindow>("Item Prefab Editor");

View File

@@ -0,0 +1,54 @@
using UnityEngine;
using UnityEditor;
namespace AppleHills.Core.Settings.Editor
{
/// <summary>
/// Custom property drawer for layer fields to display a dropdown with layer names
/// </summary>
[CustomPropertyDrawer(typeof(LayerAttribute))]
public class LayerPropertyDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);
// Draw a nice layer selection dropdown like the one in Unity inspector
if (property.propertyType == SerializedPropertyType.Integer)
{
property.intValue = EditorGUI.LayerField(position, label, property.intValue);
}
else
{
EditorGUI.LabelField(position, label.text, "Use [Layer] with int fields only");
}
EditorGUI.EndProperty();
}
}
/// <summary>
/// Custom property drawer for LayerMask fields to display a mask dropdown with layer names
/// </summary>
[CustomPropertyDrawer(typeof(LayerMaskAttribute))]
public class LayerMaskPropertyDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);
// Draw a nice layer mask selection like the one in Unity inspector
if (property.propertyType == SerializedPropertyType.LayerMask)
{
property.intValue = EditorGUI.MaskField(position, label,
property.intValue, UnityEditorInternal.InternalEditorUtility.layers);
}
else
{
EditorGUI.LabelField(position, label.text, "Use [LayerMask] with LayerMask fields only");
}
EditorGUI.EndProperty();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6c6b274ce7b14e91bf5a294a23ba0609
timeCreated: 1758711663

View File

@@ -23,7 +23,7 @@ namespace Editor
private bool _createNext = false;
[MenuItem("Tools/Prefab Creator")]
[MenuItem("AppleHills/Item Prefab Creator")]
public static void ShowWindow()
{
var window = GetWindow<PrefabCreatorWindow>("Prefab Creator");

View File

@@ -9,7 +9,7 @@ public class PuzzleChainEditorWindow : EditorWindow
private Vector2 scrollPos;
private const int INDENT_SIZE = 24;
[MenuItem("Tools/Puzzle Chain Editor")]
[MenuItem("AppleHills/Puzzle Chain Editor")]
public static void ShowWindow()
{
var window = GetWindow<PuzzleChainEditorWindow>("Puzzle Chain Editor");

View File

@@ -15,7 +15,7 @@ public class SceneObjectLocatorWindow : EditorWindow
private List<PickupInfo> pickupInfos = new List<PickupInfo>();
private Vector2 scrollPos;
[MenuItem("Tools/Scene Object Locator")]
[MenuItem("AppleHills/Scene Object Locator")]
public static void ShowWindow()
{
var window = GetWindow<SceneObjectLocatorWindow>("Scene Object Locator");

View File

@@ -0,0 +1,195 @@
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.Linq;
using System.IO;
namespace AppleHills.Core.Settings.Editor
{
public class SettingsEditorWindow : EditorWindow
{
private Vector2 scrollPosition;
private List<BaseSettings> allSettings = new List<BaseSettings>();
private string[] tabNames = new string[] { "Player & Follower", "Interaction & Items", "Diving Minigame" };
private int selectedTab = 0;
private Dictionary<string, SerializedObject> serializedSettingsObjects = new Dictionary<string, SerializedObject>();
private GUIStyle headerStyle;
[MenuItem("AppleHills/Settings Editor")]
public static void ShowWindow()
{
GetWindow<SettingsEditorWindow>("Game Settings");
}
private void OnEnable()
{
LoadAllSettings();
}
private void LoadAllSettings()
{
allSettings.Clear();
serializedSettingsObjects.Clear();
// Find all settings assets
string[] guids = AssetDatabase.FindAssets("t:BaseSettings");
foreach (string guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
BaseSettings settings = AssetDatabase.LoadAssetAtPath<BaseSettings>(path);
if (settings != null)
{
allSettings.Add(settings);
serializedSettingsObjects[settings.GetType().Name] = new SerializedObject(settings);
}
}
// If any settings are missing, create them
CreateSettingsIfMissing<PlayerFollowerSettings>("PlayerFollowerSettings");
CreateSettingsIfMissing<InteractionSettings>("InteractionSettings");
CreateSettingsIfMissing<DivingMinigameSettings>("DivingMinigameSettings");
}
private void CreateSettingsIfMissing<T>(string fileName) where T : BaseSettings
{
if (!allSettings.Any(s => s is T))
{
// Check if the asset already exists
string[] guids = AssetDatabase.FindAssets($"t:{typeof(T).Name}");
if (guids.Length == 0)
{
// Create the settings folder if it doesn't exist
if (!AssetDatabase.IsValidFolder("Assets/Settings"))
{
AssetDatabase.CreateFolder("Assets", "Settings");
}
// Create new settings asset
T settings = CreateInstance<T>();
string path = $"Assets/Settings/{fileName}.asset";
AssetDatabase.CreateAsset(settings, path);
AssetDatabase.SaveAssets();
allSettings.Add(settings);
serializedSettingsObjects[typeof(T).Name] = new SerializedObject(settings);
Debug.Log($"Created missing settings asset: {path}");
}
else
{
// Load existing asset
string path = AssetDatabase.GUIDToAssetPath(guids[0]);
T settings = AssetDatabase.LoadAssetAtPath<T>(path);
allSettings.Add(settings);
serializedSettingsObjects[typeof(T).Name] = new SerializedObject(settings);
}
}
}
private void OnGUI()
{
if (headerStyle == null)
{
headerStyle = new GUIStyle(EditorStyles.boldLabel);
headerStyle.fontSize = 14;
headerStyle.margin = new RectOffset(0, 0, 10, 10);
}
EditorGUILayout.Space(10);
EditorGUILayout.LabelField("Apple Hills Game Settings", headerStyle);
EditorGUILayout.HelpBox("Use this window to modify game settings. Changes are saved automatically.", MessageType.Info);
EditorGUILayout.Space(10);
selectedTab = GUILayout.Toolbar(selectedTab, tabNames);
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
switch (selectedTab)
{
case 0: // Player & Follower
DrawSettingsEditor<PlayerFollowerSettings>();
break;
case 1: // Interaction & Items
DrawSettingsEditor<InteractionSettings>();
break;
case 2: // Minigames
DrawSettingsEditor<DivingMinigameSettings>();
break;
}
EditorGUILayout.EndScrollView();
EditorGUILayout.Space(10);
EditorGUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button("Refresh", GUILayout.Width(100)))
{
LoadAllSettings();
}
if (GUILayout.Button("Save All", GUILayout.Width(100)))
{
foreach (var serializedObj in serializedSettingsObjects.Values)
{
serializedObj.ApplyModifiedProperties();
EditorUtility.SetDirty(serializedObj.targetObject);
}
AssetDatabase.SaveAssets();
// Refresh editor settings after save
AppleHills.Editor.EditorSettingsProvider.LoadAllSettings();
AppleHills.Editor.EditorSettingsProvider.RefreshSceneViews();
Debug.Log("All settings saved and editor views refreshed!");
}
EditorGUILayout.EndHorizontal();
}
private void DrawSettingsEditor<T>() where T : BaseSettings
{
BaseSettings settings = allSettings.Find(s => s is T);
if (settings == null)
{
EditorGUILayout.HelpBox($"No {typeof(T).Name} found. Click Refresh to create one.", MessageType.Warning);
return;
}
SerializedObject serializedObj = serializedSettingsObjects[typeof(T).Name];
serializedObj.Update();
EditorGUILayout.Space(10);
// Draw all properties
SerializedProperty property = serializedObj.GetIterator();
bool enterChildren = true;
while (property.NextVisible(enterChildren))
{
enterChildren = false;
// Skip the script field
if (property.name == "m_Script") continue;
EditorGUILayout.PropertyField(property, true);
}
// Apply changes
if (serializedObj.ApplyModifiedProperties())
{
EditorUtility.SetDirty(settings);
}
}
// Helper method to highlight important fields
private void DrawHighlightedProperty(SerializedProperty property, string tooltip = null)
{
GUI.backgroundColor = new Color(1f, 1f, 0.8f);
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
GUI.backgroundColor = Color.white;
EditorGUILayout.PropertyField(property, new GUIContent(property.displayName, tooltip));
EditorGUILayout.EndVertical();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bfb9e77c746e41a2903603a39df3d424
timeCreated: 1758619952

File diff suppressed because one or more lines are too long

View File

@@ -3,7 +3,7 @@
"name": "PlayerTouchActions",
"maps": [
{
"name": "DefaultActionMap",
"name": "PlayerTouch",
"id": "53d55b3c-f7c2-4706-a857-c615ecb16ff7",
"actions": [
{
@@ -69,6 +69,522 @@
"isPartOfComposite": false
}
]
},
{
"name": "UI",
"id": "12cf45dc-5cb9-4cc1-b345-1169f531df44",
"actions": [
{
"name": "Navigate",
"type": "PassThrough",
"id": "cef0a4a7-0193-44a6-bad9-f46ca2845c43",
"expectedControlType": "Vector2",
"processors": "",
"interactions": "",
"initialStateCheck": false
},
{
"name": "Submit",
"type": "Button",
"id": "843a4564-118d-44ea-8bd3-edcdc48f98c3",
"expectedControlType": "Button",
"processors": "",
"interactions": "",
"initialStateCheck": false
},
{
"name": "Cancel",
"type": "Button",
"id": "4a050dc0-bc3d-4941-aec6-d8d539f3e4b3",
"expectedControlType": "Button",
"processors": "",
"interactions": "",
"initialStateCheck": false
},
{
"name": "Point",
"type": "PassThrough",
"id": "a03cf960-cfac-495c-9344-de5f5ef44bba",
"expectedControlType": "Vector2",
"processors": "",
"interactions": "",
"initialStateCheck": true
},
{
"name": "Click",
"type": "PassThrough",
"id": "7e486236-0e6f-4f21-ade8-0ab696112f8e",
"expectedControlType": "Button",
"processors": "",
"interactions": "",
"initialStateCheck": true
},
{
"name": "RightClick",
"type": "PassThrough",
"id": "09458b52-8a45-4617-a412-000ed647d359",
"expectedControlType": "Button",
"processors": "",
"interactions": "",
"initialStateCheck": false
},
{
"name": "MiddleClick",
"type": "PassThrough",
"id": "7c721d8a-977d-4ff7-87b2-19dbd4eb5ea6",
"expectedControlType": "Button",
"processors": "",
"interactions": "",
"initialStateCheck": false
},
{
"name": "ScrollWheel",
"type": "PassThrough",
"id": "e6a073b0-0030-42c2-88ef-85d828760630",
"expectedControlType": "Vector2",
"processors": "",
"interactions": "",
"initialStateCheck": false
},
{
"name": "TrackedDevicePosition",
"type": "PassThrough",
"id": "efcff6db-3f65-4107-8658-7e56305f2c8a",
"expectedControlType": "Vector3",
"processors": "",
"interactions": "",
"initialStateCheck": false
},
{
"name": "TrackedDeviceOrientation",
"type": "PassThrough",
"id": "2c7ed826-65c6-4dc4-81c7-536d62bbede1",
"expectedControlType": "Quaternion",
"processors": "",
"interactions": "",
"initialStateCheck": false
}
],
"bindings": [
{
"name": "Gamepad",
"id": "499b8c05-0325-4b99-9be0-9c8aa41ec39d",
"path": "2DVector",
"interactions": "",
"processors": "",
"groups": "",
"action": "Navigate",
"isComposite": true,
"isPartOfComposite": false
},
{
"name": "up",
"id": "e5794321-3fc2-4ca8-a7a9-e35446b102ef",
"path": "<Gamepad>/leftStick/up",
"interactions": "",
"processors": "",
"groups": ";Gamepad",
"action": "Navigate",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "up",
"id": "72f978c8-23be-4e97-8609-0b1426355553",
"path": "<Gamepad>/rightStick/up",
"interactions": "",
"processors": "",
"groups": ";Gamepad",
"action": "Navigate",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "down",
"id": "6009f3e0-d95b-4440-a827-617812265049",
"path": "<Gamepad>/leftStick/down",
"interactions": "",
"processors": "",
"groups": ";Gamepad",
"action": "Navigate",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "down",
"id": "590f0119-784f-45f3-97b6-5ffbfad9941f",
"path": "<Gamepad>/rightStick/down",
"interactions": "",
"processors": "",
"groups": ";Gamepad",
"action": "Navigate",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "left",
"id": "e3588172-d7ee-4395-bc1a-3fc013f42400",
"path": "<Gamepad>/leftStick/left",
"interactions": "",
"processors": "",
"groups": ";Gamepad",
"action": "Navigate",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "left",
"id": "4da29037-9c91-4140-8068-68a7375cdc4e",
"path": "<Gamepad>/rightStick/left",
"interactions": "",
"processors": "",
"groups": ";Gamepad",
"action": "Navigate",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "right",
"id": "4620550c-3f8f-437c-a426-ad3e52b2764c",
"path": "<Gamepad>/leftStick/right",
"interactions": "",
"processors": "",
"groups": ";Gamepad",
"action": "Navigate",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "right",
"id": "c74b9635-b880-45f5-a469-5cb8c2b83909",
"path": "<Gamepad>/rightStick/right",
"interactions": "",
"processors": "",
"groups": ";Gamepad",
"action": "Navigate",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "",
"id": "7a2feef9-0779-498f-a6ae-08484b606d07",
"path": "<Gamepad>/dpad",
"interactions": "",
"processors": "",
"groups": ";Gamepad",
"action": "Navigate",
"isComposite": false,
"isPartOfComposite": false
},
{
"name": "Joystick",
"id": "cd58a9a8-6605-4b26-8fb3-466b928fad60",
"path": "2DVector",
"interactions": "",
"processors": "",
"groups": "",
"action": "Navigate",
"isComposite": true,
"isPartOfComposite": false
},
{
"name": "up",
"id": "be8cdff0-47f9-4546-a919-405e54580ea5",
"path": "<Joystick>/stick/up",
"interactions": "",
"processors": "",
"groups": "Joystick",
"action": "Navigate",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "down",
"id": "04487afd-6a42-471a-ae70-49d7583ad93b",
"path": "<Joystick>/stick/down",
"interactions": "",
"processors": "",
"groups": "Joystick",
"action": "Navigate",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "left",
"id": "d327788e-3a9a-4c14-97c8-b46bff05cf16",
"path": "<Joystick>/stick/left",
"interactions": "",
"processors": "",
"groups": "Joystick",
"action": "Navigate",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "right",
"id": "4c760fb6-00fc-46bc-8a0f-e1be2a3a91cd",
"path": "<Joystick>/stick/right",
"interactions": "",
"processors": "",
"groups": "Joystick",
"action": "Navigate",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "Keyboard",
"id": "21afa4c3-8c86-4939-bafc-c75c37368f04",
"path": "2DVector",
"interactions": "",
"processors": "",
"groups": "",
"action": "Navigate",
"isComposite": true,
"isPartOfComposite": false
},
{
"name": "up",
"id": "1d6ea17c-5d6b-4ae5-9881-cf787fd492ed",
"path": "<Keyboard>/w",
"interactions": "",
"processors": "",
"groups": "Keyboard&Mouse",
"action": "Navigate",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "up",
"id": "6e90418f-6f67-4248-bbb4-90243304f39a",
"path": "<Keyboard>/upArrow",
"interactions": "",
"processors": "",
"groups": "Keyboard&Mouse",
"action": "Navigate",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "down",
"id": "6be3eb21-d6ea-458d-a66f-f82487ec9139",
"path": "<Keyboard>/s",
"interactions": "",
"processors": "",
"groups": "Keyboard&Mouse",
"action": "Navigate",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "down",
"id": "3188c496-3978-454b-be6f-944521aabea4",
"path": "<Keyboard>/downArrow",
"interactions": "",
"processors": "",
"groups": "Keyboard&Mouse",
"action": "Navigate",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "left",
"id": "00de0415-2218-4887-9ad6-e4a6c1dacc5b",
"path": "<Keyboard>/a",
"interactions": "",
"processors": "",
"groups": "Keyboard&Mouse",
"action": "Navigate",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "left",
"id": "f723bc7b-263d-4619-93aa-0afdc40f3bc3",
"path": "<Keyboard>/leftArrow",
"interactions": "",
"processors": "",
"groups": "Keyboard&Mouse",
"action": "Navigate",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "right",
"id": "f3530c12-f67f-437a-979e-2271af5b2d2d",
"path": "<Keyboard>/d",
"interactions": "",
"processors": "",
"groups": "Keyboard&Mouse",
"action": "Navigate",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "right",
"id": "d760d39b-f0b3-4823-a705-c20b641b5720",
"path": "<Keyboard>/rightArrow",
"interactions": "",
"processors": "",
"groups": "Keyboard&Mouse",
"action": "Navigate",
"isComposite": false,
"isPartOfComposite": true
},
{
"name": "",
"id": "2cc2aec1-4255-4cab-bb40-0a894a0d87d3",
"path": "*/{Submit}",
"interactions": "",
"processors": "",
"groups": "Keyboard&Mouse;Gamepad;Touch;Joystick;XR",
"action": "Submit",
"isComposite": false,
"isPartOfComposite": false
},
{
"name": "",
"id": "fbe038e0-74cf-48bc-b013-4d6f9e817833",
"path": "*/{Cancel}",
"interactions": "",
"processors": "",
"groups": "Keyboard&Mouse;Gamepad;Touch;Joystick;XR",
"action": "Cancel",
"isComposite": false,
"isPartOfComposite": false
},
{
"name": "",
"id": "21be382d-dc2e-4360-bdb6-a3cc412a0abe",
"path": "<Mouse>/position",
"interactions": "",
"processors": "",
"groups": "Keyboard&Mouse",
"action": "Point",
"isComposite": false,
"isPartOfComposite": false
},
{
"name": "",
"id": "38f39dfe-e703-4be0-8fcf-6de2167518c1",
"path": "<Pen>/position",
"interactions": "",
"processors": "",
"groups": "Keyboard&Mouse",
"action": "Point",
"isComposite": false,
"isPartOfComposite": false
},
{
"name": "",
"id": "5bbcf2f7-aea0-4067-ae32-aaf383287fb3",
"path": "<Touchscreen>/touch*/position",
"interactions": "",
"processors": "",
"groups": "Touch",
"action": "Point",
"isComposite": false,
"isPartOfComposite": false
},
{
"name": "",
"id": "32dde7e0-9557-4429-a882-7c87540c7e53",
"path": "<Mouse>/leftButton",
"interactions": "",
"processors": "",
"groups": ";Keyboard&Mouse",
"action": "Click",
"isComposite": false,
"isPartOfComposite": false
},
{
"name": "",
"id": "f22741eb-66dd-4e3e-aaca-94d92991235c",
"path": "<Pen>/tip",
"interactions": "",
"processors": "",
"groups": ";Keyboard&Mouse",
"action": "Click",
"isComposite": false,
"isPartOfComposite": false
},
{
"name": "",
"id": "1bec0af0-b75f-43da-a4a7-7de7f952df13",
"path": "<Touchscreen>/touch*/press",
"interactions": "",
"processors": "",
"groups": "Touch",
"action": "Click",
"isComposite": false,
"isPartOfComposite": false
},
{
"name": "",
"id": "d281b478-404c-47ec-95d3-ddcdcc19369a",
"path": "<XRController>/trigger",
"interactions": "",
"processors": "",
"groups": "XR",
"action": "Click",
"isComposite": false,
"isPartOfComposite": false
},
{
"name": "",
"id": "ea2e7ff3-1a42-4202-8c53-abcae2467bb2",
"path": "<Mouse>/scroll",
"interactions": "",
"processors": "",
"groups": ";Keyboard&Mouse",
"action": "ScrollWheel",
"isComposite": false,
"isPartOfComposite": false
},
{
"name": "",
"id": "b0b7ca17-b763-4af6-a02a-0fcfbf043c37",
"path": "<Mouse>/rightButton",
"interactions": "",
"processors": "",
"groups": "Keyboard&Mouse",
"action": "RightClick",
"isComposite": false,
"isPartOfComposite": false
},
{
"name": "",
"id": "c3146994-3749-4211-a80a-5766edd782e3",
"path": "<Mouse>/middleButton",
"interactions": "",
"processors": "",
"groups": "Keyboard&Mouse",
"action": "MiddleClick",
"isComposite": false,
"isPartOfComposite": false
},
{
"name": "",
"id": "35aad27d-6a71-481b-b308-7763de690931",
"path": "<XRController>/devicePosition",
"interactions": "",
"processors": "",
"groups": "XR",
"action": "TrackedDevicePosition",
"isComposite": false,
"isPartOfComposite": false
},
{
"name": "",
"id": "d116b82b-e40f-4ab3-b7b8-eec40f53e88a",
"path": "<XRController>/deviceRotation",
"interactions": "",
"processors": "",
"groups": "XR",
"action": "TrackedDeviceOrientation",
"isComposite": false,
"isPartOfComposite": false
}
]
}
],
"controlSchemes": []

View File

@@ -52,6 +52,8 @@ SpriteRenderer:
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
@@ -73,6 +75,7 @@ SpriteRenderer:
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 1
@@ -147,6 +150,8 @@ SpriteRenderer:
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
@@ -168,6 +173,7 @@ SpriteRenderer:
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0

View File

@@ -52,6 +52,8 @@ SpriteRenderer:
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
@@ -73,6 +75,7 @@ SpriteRenderer:
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 1
@@ -139,6 +142,8 @@ SpriteRenderer:
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
@@ -160,6 +165,7 @@ SpriteRenderer:
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 1
@@ -234,6 +240,8 @@ SpriteRenderer:
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
@@ -255,6 +263,7 @@ SpriteRenderer:
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0

View File

@@ -135,6 +135,8 @@ SpriteRenderer:
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
@@ -156,6 +158,7 @@ SpriteRenderer:
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 1
@@ -232,6 +235,8 @@ SpriteRenderer:
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
@@ -253,6 +258,7 @@ SpriteRenderer:
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0

View File

@@ -56,6 +56,8 @@ SpriteRenderer:
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
@@ -77,6 +79,7 @@ SpriteRenderer:
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
@@ -246,6 +249,8 @@ SpriteRenderer:
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
@@ -267,6 +272,7 @@ SpriteRenderer:
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0

View File

@@ -55,6 +55,8 @@ SpriteRenderer:
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
@@ -76,6 +78,7 @@ SpriteRenderer:
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 1

View File

@@ -72,6 +72,6 @@ MonoBehaviour:
m_ActionEvents: []
m_NeverAutoSwitchControlSchemes: 0
m_DefaultControlScheme:
m_DefaultActionMap: DefaultActionMap
m_DefaultActionMap: 53d55b3c-f7c2-4706-a857-c615ecb16ff7
m_SplitScreenIndex: -1
m_Camera: {fileID: 0}

View File

@@ -0,0 +1,46 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &6399527186463168339
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7768516537241418043}
- component: {fileID: 4607144289768175859}
m_Layer: 0
m_Name: ItemManager
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &7768516537241418043
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6399527186463168339}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: -2.64965, y: 3.24335, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &4607144289768175859
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6399527186463168339}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a78fe78378e6426da43710f6d0ae84ba, type: 3}
m_Name:
m_EditorClassIdentifier: AppleHillsScripts::Core.ItemManager

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: ac41583865245bc4bb3de6c15929b9fc
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -47,7 +47,6 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
prefabIndex: 0
damage: 1
moveSpeed: 2
enableMovement: 1
spawner: {fileID: 0}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 6fb0d7fc6faad154b8c3e3cb7abb7c15
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -309,7 +309,7 @@ PrefabInstance:
objectReference: {fileID: -8109988653212156562, guid: 77ab3d770c92d5344b36eee3293a0f94, type: 3}
- target: {fileID: 6350287859698694726, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3}
propertyPath: m_Name
value: TestAss
value: TestAss3
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
@@ -368,6 +368,8 @@ SpriteRenderer:
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
@@ -389,6 +391,7 @@ SpriteRenderer:
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
@@ -995,7 +998,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 6350287859698694726, guid: b5fc01af35233eb4cbeede05e50a7c34, type: 3}
propertyPath: m_Name
value: TestAss
value: TestAss2
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
@@ -1228,6 +1231,8 @@ SpriteRenderer:
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
@@ -1249,6 +1254,7 @@ SpriteRenderer:
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: -1
@@ -1633,6 +1639,37 @@ SpriteRenderer:
m_CorrespondingSourceObject: {fileID: 7494677664706785084, guid: bf4b9d7045397f946b2125b1ad4a3fbd, type: 3}
m_PrefabInstance: {fileID: 1336824707}
m_PrefabAsset: {fileID: 0}
--- !u!1 &1668240410
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1668240411}
m_Layer: 0
m_Name: Buttons
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1668240411
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1668240410}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 898.1756, y: 720.9647, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1741016587
GameObject:
m_ObjectHideFlags: 0
@@ -1795,7 +1832,6 @@ MonoBehaviour:
m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0}
m_RequiresDepthTexture: 0
m_RequiresColorTexture: 0
m_Version: 2
m_TaaSettings:
m_Quality: 3
m_FrameInfluence: 0.1
@@ -1803,6 +1839,7 @@ MonoBehaviour:
m_MipBias: 0
m_VarianceClampScale: 0.9
m_ContrastAdaptiveSharpening: 0
m_Version: 2
--- !u!1 &1880929593
GameObject:
m_ObjectHideFlags: 0
@@ -1979,6 +2016,10 @@ PrefabInstance:
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7852204877518954380, guid: 8ac0210dbf9d7754e9526d6d5c214f49, type: 3}
propertyPath: maxSpeed
value: 15
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
@@ -2058,3 +2099,4 @@ SceneRoots:
- {fileID: 1234715653}
- {fileID: 1336824707}
- {fileID: 384576747}
- {fileID: 1668240411}

View File

@@ -172,6 +172,8 @@ SpriteRenderer:
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
@@ -193,6 +195,7 @@ SpriteRenderer:
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
@@ -253,6 +256,51 @@ BoxCollider2D:
m_AutoTiling: 0
m_Size: {x: 1, y: 1}
m_EdgeRadius: 0
--- !u!1 &1334266842
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1334266844}
- component: {fileID: 1334266843}
m_Layer: 0
m_Name: DialogueTest
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &1334266843
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1334266842}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 749c3dece1c14b82845c175203a2e7dc, type: 3}
m_Name:
m_EditorClassIdentifier: AppleHillsScripts::Dialogue.DialogueComponent
runtimeGraph: {fileID: 3965311268370046156, guid: 9050f99a225035b40b415df272d2b341, type: 3}
--- !u!4 &1334266844
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1334266842}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: -3.64555, y: 2.05444, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1507068790
GameObject:
m_ObjectHideFlags: 0
@@ -264,6 +312,7 @@ GameObject:
- component: {fileID: 1507068793}
- component: {fileID: 1507068792}
- component: {fileID: 1507068791}
- component: {fileID: 1507068794}
m_Layer: 0
m_Name: Main Camera
m_TagString: MainCamera
@@ -345,6 +394,50 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1507068794
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1507068790}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.UniversalAdditionalCameraData
m_RenderShadows: 1
m_RequiresDepthTextureOption: 2
m_RequiresOpaqueTextureOption: 2
m_CameraType: 0
m_Cameras: []
m_RendererIndex: -1
m_VolumeLayerMask:
serializedVersion: 2
m_Bits: 1
m_VolumeTrigger: {fileID: 0}
m_VolumeFrameworkUpdateModeOption: 2
m_RenderPostProcessing: 0
m_Antialiasing: 0
m_AntialiasingQuality: 2
m_StopNaN: 0
m_Dithering: 0
m_ClearDepth: 1
m_AllowXRRendering: 1
m_AllowHDROutput: 1
m_UseScreenCoordOverride: 0
m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0}
m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0}
m_RequiresDepthTexture: 0
m_RequiresColorTexture: 0
m_TaaSettings:
m_Quality: 3
m_FrameInfluence: 0.1
m_JitterScale: 1
m_MipBias: 0
m_VarianceClampScale: 0.9
m_ContrastAdaptiveSharpening: 0
m_Version: 2
--- !u!1 &1851499346
GameObject:
m_ObjectHideFlags: 0
@@ -429,6 +522,8 @@ SpriteRenderer:
m_RayTracingAccelStructBuildFlagsOverride: 0
m_RayTracingAccelStructBuildFlags: 1
m_SmallMeshCulling: 1
m_ForceMeshLod: -1
m_MeshLodSelectionBias: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
@@ -450,6 +545,7 @@ SpriteRenderer:
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_GlobalIlluminationMeshLod: 0
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
@@ -518,3 +614,4 @@ SceneRoots:
- {fileID: 1851499349}
- {fileID: 2029728268}
- {fileID: 465048834}
- {fileID: 1334266844}

View File

@@ -1,4 +1,6 @@
using UnityEngine;
using AppleHills.Core.Settings;
using System;
/// <summary>
/// Singleton manager for global game state and settings. Provides accessors for various gameplay parameters.
@@ -29,53 +31,172 @@ public class GameManager : MonoBehaviour
}
}
[Header("Game Settings")]
public GameSettings gameSettings;
[Header("Settings Status")]
[SerializeField] private bool _settingsLoaded = false;
[SerializeField] private bool _developerSettingsLoaded = false;
public bool SettingsLoaded => _settingsLoaded;
public bool DeveloperSettingsLoaded => _developerSettingsLoaded;
void Awake()
{
_instance = this;
if (gameSettings == null)
{
gameSettings = Resources.Load<GameSettings>("DefaultSettings");
if (gameSettings == null)
{
Debug.LogError("GameSettings asset not found in Resources!");
}
}
// Create settings provider if it doesn't exist
SettingsProvider.Instance.gameObject.name = "Settings Provider";
// Create developer settings provider if it doesn't exist
DeveloperSettingsProvider.Instance.gameObject.name = "Developer Settings Provider";
// Load all settings synchronously during Awake
InitializeSettings();
InitializeDeveloperSettings();
// DontDestroyOnLoad(gameObject);
}
private void InitializeSettings()
{
Debug.Log("Starting settings initialization...");
// Load settings synchronously
var playerSettings = SettingsProvider.Instance.LoadSettingsSynchronous<PlayerFollowerSettings>();
var interactionSettings = SettingsProvider.Instance.LoadSettingsSynchronous<InteractionSettings>();
var minigameSettings = SettingsProvider.Instance.LoadSettingsSynchronous<DivingMinigameSettings>();
// Register settings with service locator
if (playerSettings != null)
{
ServiceLocator.Register<IPlayerFollowerSettings>(playerSettings);
Debug.Log("PlayerFollowerSettings registered successfully");
}
else
{
Debug.LogError("Failed to load PlayerFollowerSettings");
}
if (interactionSettings != null)
{
ServiceLocator.Register<IInteractionSettings>(interactionSettings);
Debug.Log("InteractionSettings registered successfully");
}
else
{
Debug.LogError("Failed to load InteractionSettings");
}
if (minigameSettings != null)
{
ServiceLocator.Register<IDivingMinigameSettings>(minigameSettings);
Debug.Log("MinigameSettings registered successfully");
}
else
{
Debug.LogError("Failed to load MinigameSettings");
}
// Log success
_settingsLoaded = playerSettings != null && interactionSettings != null && minigameSettings != null;
if (_settingsLoaded)
{
Debug.Log("All settings loaded and registered with ServiceLocator");
}
else
{
Debug.LogWarning("Some settings failed to load - check that all settings assets exist and are marked as Addressables");
}
}
/// <summary>
/// Check for and initialize developer settings.
/// </summary>
private void InitializeDeveloperSettings()
{
Debug.Log("Starting developer settings initialization...");
// Load developer settings
var divingDevSettings = DeveloperSettingsProvider.Instance.GetSettings<DivingDeveloperSettings>();
_developerSettingsLoaded = divingDevSettings != null;
if (_developerSettingsLoaded)
{
Debug.Log("All developer settings loaded successfully");
}
else
{
Debug.LogWarning("Some developer settings failed to load");
}
}
void OnApplicationQuit()
{
_isQuitting = true;
ServiceLocator.Clear();
}
// Accessors for game settings
public float PlayerStopDistance => gameSettings != null ? gameSettings.playerStopDistance : 1.0f;
public float FollowerPickupDelay => gameSettings != null ? gameSettings.followerPickupDelay : 0.2f;
public float FollowDistance => gameSettings != null ? gameSettings.followDistance : 1.5f;
public float ManualMoveSmooth => gameSettings != null ? gameSettings.manualMoveSmooth : 8f;
public float ThresholdFar => gameSettings != null ? gameSettings.thresholdFar : 2.5f;
public float ThresholdNear => gameSettings != null ? gameSettings.thresholdNear : 0.5f;
public float StopThreshold => gameSettings != null ? gameSettings.stopThreshold : 0.5f;
public float MoveSpeed => gameSettings != null ? gameSettings.moveSpeed : 5f;
public float StopDistance => gameSettings != null ? gameSettings.stopDistance : 0.1f;
public bool UseRigidbody => gameSettings != null ? gameSettings.useRigidbody : true;
public float FollowUpdateInterval => gameSettings != null ? gameSettings.followUpdateInterval : 0.1f;
public float FollowerSpeedMultiplier => gameSettings != null ? gameSettings.followerSpeedMultiplier : 1.2f;
public float HeldIconDisplayHeight => gameSettings != null ? gameSettings.heldIconDisplayHeight : 2.0f;
public GameObject BasePickupPrefab => gameSettings != null ? gameSettings.basePickupPrefab : null;
public LayerMask InteractableLayerMask => gameSettings != null ? gameSettings.interactableLayerMask : -1;
public float PlayerStopDistanceDirectInteraction => gameSettings != null ? gameSettings.playerStopDistanceDirectInteraction : 2.0f;
// Helper method to get settings
private T GetSettings<T>() where T : class
{
return ServiceLocator.Get<T>();
}
/// <summary>
/// Returns the entire settings object of specified type.
/// </summary>
/// <typeparam name="T">Type of settings to retrieve</typeparam>
/// <returns>The settings object or null if not found</returns>
public static T GetSettingsObject<T>() where T : class
{
return Instance?.GetSettings<T>();
}
/// <summary>
/// Returns the developer settings object of specified type.
/// </summary>
/// <typeparam name="T">Type of developer settings to retrieve</typeparam>
/// <returns>The developer settings object or null if not found</returns>
public static T GetDeveloperSettings<T>() where T : BaseDeveloperSettings
{
return DeveloperSettingsProvider.Instance?.GetSettings<T>();
}
// PLAYER & FOLLOWER SETTINGS
// Player settings
public float MoveSpeed => GetSettings<IPlayerFollowerSettings>()?.MoveSpeed ?? 5f;
public float StopDistance => GetSettings<IPlayerFollowerSettings>()?.StopDistance ?? 0.1f;
public bool UseRigidbody => GetSettings<IPlayerFollowerSettings>()?.UseRigidbody ?? true;
public HoldMovementMode DefaultHoldMovementMode =>
GetSettings<IPlayerFollowerSettings>()?.DefaultHoldMovementMode ?? HoldMovementMode.Pathfinding;
// Follower settings
public float FollowDistance => GetSettings<IPlayerFollowerSettings>()?.FollowDistance ?? 1.5f;
public float ManualMoveSmooth => GetSettings<IPlayerFollowerSettings>()?.ManualMoveSmooth ?? 8f;
public float ThresholdFar => GetSettings<IPlayerFollowerSettings>()?.ThresholdFar ?? 2.5f;
public float ThresholdNear => GetSettings<IPlayerFollowerSettings>()?.ThresholdNear ?? 0.5f;
public float StopThreshold => GetSettings<IPlayerFollowerSettings>()?.StopThreshold ?? 0.1f;
public float FollowUpdateInterval => GetSettings<IPlayerFollowerSettings>()?.FollowUpdateInterval ?? 0.1f;
public float FollowerSpeedMultiplier => GetSettings<IPlayerFollowerSettings>()?.FollowerSpeedMultiplier ?? 1.2f;
public float HeldIconDisplayHeight => GetSettings<IPlayerFollowerSettings>()?.HeldIconDisplayHeight ?? 2.0f;
// INTERACTION SETTINGS
public float PlayerStopDistance => GetSettings<IInteractionSettings>()?.PlayerStopDistance ?? 6.0f;
public float PlayerStopDistanceDirectInteraction => GetSettings<IInteractionSettings>()?.PlayerStopDistanceDirectInteraction ?? 2.0f;
public float FollowerPickupDelay => GetSettings<IInteractionSettings>()?.FollowerPickupDelay ?? 0.2f;
public LayerMask InteractableLayerMask => GetSettings<IInteractionSettings>()?.InteractableLayerMask ?? -1;
public GameObject BasePickupPrefab => GetSettings<IInteractionSettings>()?.BasePickupPrefab;
public GameObject LevelSwitchMenuPrefab => GetSettings<IInteractionSettings>()?.LevelSwitchMenuPrefab;
/// <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)
{
if (gameSettings == null || gameSettings.combinationRules == null) return null;
foreach (var rule in gameSettings.combinationRules)
var settings = GetSettings<IInteractionSettings>();
if (settings == null || settings.CombinationRules == null) return null;
foreach (var rule in settings.CombinationRules)
{
if ((PickupItemData.AreEquivalent(rule.itemA, item1) && PickupItemData.AreEquivalent(rule.itemB, item2)) ||
(PickupItemData.AreEquivalent(rule.itemA, item2) && PickupItemData.AreEquivalent(rule.itemB, item1)))
@@ -89,22 +210,16 @@ 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)
{
if (gameSettings == null || gameSettings.slotItemConfigs == null || slotItem == null) return null;
foreach (var config in gameSettings.slotItemConfigs)
var settings = GetSettings<IInteractionSettings>();
if (settings == null || settings.SlotItemConfigs == null || slotItem == null) return null;
foreach (var config in settings.SlotItemConfigs)
{
if (PickupItemData.AreEquivalent(slotItem, config.slotItem))
return config;
}
return null;
}
// Add more accessors as needed
public float EndlessDescenderLerpSpeed => gameSettings != null ? gameSettings.endlessDescenderLerpSpeed : 12f;
public float EndlessDescenderMaxOffset => gameSettings != null ? gameSettings.endlessDescenderMaxOffset : 3f;
public float EndlessDescenderClampXMin => gameSettings != null ? gameSettings.endlessDescenderClampXMin : -5f;
public float EndlessDescenderClampXMax => gameSettings != null ? gameSettings.endlessDescenderClampXMax : 5f;
public float EndlessDescenderSpeedExponent => gameSettings != null ? gameSettings.endlessDescenderSpeedExponent : 2.5f;
public GameSettings.HoldMovementMode DefaultHoldMovementMode => gameSettings != null ? gameSettings.defaultHoldMovementMode : GameSettings.HoldMovementMode.Pathfinding;
public GameObject LevelSwitchMenuPrefab => gameSettings != null ? gameSettings.levelSwitchMenuPrefab : 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

@@ -0,0 +1,181 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using Interactions;
namespace Core
{
/// <summary>
/// Central registry for pickups and item slots.
/// Mirrors the singleton pattern used by PuzzleManager.
/// </summary>
public class ItemManager : MonoBehaviour
{
private static ItemManager _instance;
private static bool _isQuitting;
public static ItemManager Instance
{
get
{
if (_instance == null && Application.isPlaying && !_isQuitting)
{
_instance = FindAnyObjectByType<ItemManager>();
if (_instance == null)
{
var go = new GameObject("ItemManager");
_instance = go.AddComponent<ItemManager>();
// DontDestroyOnLoad(go);
}
}
return _instance;
}
}
private readonly HashSet<Pickup> _pickups = new HashSet<Pickup>();
private readonly HashSet<ItemSlot> _itemSlots = new HashSet<ItemSlot>();
// Central events forwarded from registered pickups/slots
// Broadcasts when any registered pickup was picked up (passes the picked item data)
public event Action<PickupItemData> OnItemPickedUp;
// Broadcasts when any registered ItemSlot reports a correct item slotted
// Args: slot's itemData (the slot definition), then the slotted item data
public event Action<PickupItemData, PickupItemData> OnCorrectItemSlotted;
void Awake()
{
_instance = this;
}
void Start()
{
// Subscribe to scene load completed so we can clear registrations when scenes change
// Access Instance directly to ensure the service is initialized and we get the event hookup.
SceneManagerService.Instance.SceneLoadCompleted += OnSceneLoadCompleted;
}
void OnDestroy()
{
// Unsubscribe from SceneManagerService
if (SceneManagerService.Instance != null)
SceneManagerService.Instance.SceneLoadCompleted -= OnSceneLoadCompleted;
// Ensure we clean up any subscriptions from registered items when the manager is destroyed
ClearAllRegistrations();
}
void OnApplicationQuit()
{
_isQuitting = true;
}
private void OnSceneLoadCompleted(string sceneName)
{
// Clear all registrations when a new scene is loaded, so no stale references persist
ClearAllRegistrations();
}
/// <summary>
/// Unsubscribe all pickup/slot event handlers and clear registries and manager events.
/// </summary>
private void ClearAllRegistrations()
{
// Unsubscribe pickup handlers
var pickupsCopy = new List<Pickup>(_pickups);
foreach (var p in pickupsCopy)
{
if (p != null)
p.OnItemPickedUp -= Pickup_OnItemPickedUp;
}
_pickups.Clear();
// Unsubscribe slot handlers
var slotsCopy = new List<ItemSlot>(_itemSlots);
foreach (var s in slotsCopy)
{
if (s != null)
s.OnCorrectItemSlotted -= ItemSlot_OnCorrectItemSlotted;
}
_itemSlots.Clear();
// Clear manager-level event subscribers
OnItemPickedUp = null;
OnCorrectItemSlotted = null;
}
public void RegisterPickup(Pickup pickup)
{
if (pickup == null) return;
// only subscribe if newly added to avoid duplicate subscriptions
if (_pickups.Add(pickup))
{
pickup.OnItemPickedUp += Pickup_OnItemPickedUp;
}
}
public void UnregisterPickup(Pickup pickup)
{
if (pickup == null) return;
if (_pickups.Remove(pickup))
{
pickup.OnItemPickedUp -= Pickup_OnItemPickedUp;
}
}
public void RegisterItemSlot(ItemSlot slot)
{
if (slot == null) return;
if (_itemSlots.Add(slot))
{
slot.OnCorrectItemSlotted += ItemSlot_OnCorrectItemSlotted;
}
}
public void UnregisterItemSlot(ItemSlot slot)
{
if (slot == null) return;
if (_itemSlots.Remove(slot))
{
slot.OnCorrectItemSlotted -= ItemSlot_OnCorrectItemSlotted;
}
}
// Handler that forwards pickup events
private void Pickup_OnItemPickedUp(PickupItemData data)
{
OnItemPickedUp?.Invoke(data);
}
// Handler that forwards correct-slot events
private void ItemSlot_OnCorrectItemSlotted(PickupItemData slotData, PickupItemData slottedItem)
{
OnCorrectItemSlotted?.Invoke(slotData, slottedItem);
}
/// <summary>
/// Returns the current slot state for the given item data by searching registered slots.
/// If the item is currently slotted in a slot, returns that slot's state; otherwise returns ItemSlotState.None.
/// </summary>
public ItemSlotState GetSlotStatusForItem(PickupItemData itemData)
{
if (itemData == null) return ItemSlotState.None;
foreach (var slot in _itemSlots)
{
var slottedObj = slot.GetSlottedObject();
if (slottedObj == null) continue;
var pickup = slottedObj.GetComponent<Pickup>();
if (pickup == null) continue;
if (pickup.itemData == itemData)
{
return slot.CurrentSlottedState;
}
}
return ItemSlotState.None;
}
public IEnumerable<Pickup> Pickups => _pickups;
public IEnumerable<ItemSlot> ItemSlots => _itemSlots;
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a78fe78378e6426da43710f6d0ae84ba
timeCreated: 1758888493

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e380783135324fcd925048783e01d691
timeCreated: 1758619858

View File

@@ -0,0 +1,19 @@
using UnityEngine;
namespace AppleHills.Core.Settings
{
/// <summary>
/// Base abstract class for all developer settings.
/// Developer settings are intended for technical configuration rather than gameplay/design values.
/// </summary>
public abstract class BaseDeveloperSettings : ScriptableObject
{
/// <summary>
/// Called to validate settings values when they are changed in the inspector.
/// </summary>
public virtual void OnValidate()
{
// Base implementation does nothing, override in derived classes
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 50def2e6e95a4830b57f3e1b76a4df51
timeCreated: 1758707161

View File

@@ -0,0 +1,16 @@
using UnityEngine;
namespace AppleHills.Core.Settings
{
/// <summary>
/// Base class for all settings ScriptableObjects.
/// Provides common functionality for all settings types.
/// </summary>
public abstract class BaseSettings : ScriptableObject
{
public virtual void OnValidate()
{
// Override in derived classes to add validation
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: cd33ef6036eb49358acbbd50dfd9bb13
timeCreated: 1758619858

View File

@@ -0,0 +1,116 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using System;
namespace AppleHills.Core.Settings
{
/// <summary>
/// Provides access to developer settings for technical configuration rather than gameplay parameters.
/// Follows the singleton pattern for global access.
/// </summary>
public class DeveloperSettingsProvider : MonoBehaviour
{
private static DeveloperSettingsProvider _instance;
/// <summary>
/// Singleton instance of the provider.
/// </summary>
public static DeveloperSettingsProvider Instance
{
get
{
if (_instance == null && Application.isPlaying)
{
_instance = FindFirstObjectByType<DeveloperSettingsProvider>();
if (_instance == null)
{
GameObject go = new GameObject("DeveloperSettingsProvider");
_instance = go.AddComponent<DeveloperSettingsProvider>();
// Don't destroy between scenes
DontDestroyOnLoad(go);
}
}
return _instance;
}
}
// Dictionary to cache loaded settings
private Dictionary<System.Type, BaseDeveloperSettings> _settingsCache = new Dictionary<System.Type, BaseDeveloperSettings>();
// Path prefix for addressable developer settings
[SerializeField] private string _addressablePath = "Settings/Developer";
private void Awake()
{
if (_instance != null && _instance != this)
{
Destroy(gameObject);
return;
}
_instance = this;
DontDestroyOnLoad(gameObject);
// Initialize settings cache
_settingsCache = new Dictionary<System.Type, BaseDeveloperSettings>();
}
/// <summary>
/// Gets or loads developer settings of the specified type.
/// </summary>
/// <typeparam name="T">Type of developer settings to retrieve</typeparam>
/// <returns>The settings instance or null if not found</returns>
public T GetSettings<T>() where T : BaseDeveloperSettings
{
System.Type type = typeof(T);
// Return from cache if available
if (_settingsCache.TryGetValue(type, out BaseDeveloperSettings cachedSettings))
{
return cachedSettings as T;
}
// Load from Addressables if not cached
string key = $"{_addressablePath}/{type.Name}";
try
{
T settings = Addressables.LoadAssetAsync<T>(key).WaitForCompletion();
if (settings != null)
{
_settingsCache[type] = settings;
return settings;
}
}
catch (Exception e)
{
Debug.LogError($"Failed to load developer settings at '{key}': {e.Message}");
}
Debug.LogWarning($"Developer settings of type {type.Name} not found at addressable path '{key}'");
// Fallback to Resources for backward compatibility
T resourcesSettings = Resources.Load<T>($"{_addressablePath}/{type.Name}");
if (resourcesSettings != null)
{
Debug.Log($"Found developer settings in Resources instead of Addressables at '{_addressablePath}/{type.Name}'");
_settingsCache[type] = resourcesSettings;
return resourcesSettings;
}
return null;
}
/// <summary>
/// Clears the settings cache, forcing settings to be reloaded.
/// </summary>
public void ClearCache()
{
_settingsCache.Clear();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f9945aa4a563434e973ab49176259150
timeCreated: 1758707186

View File

@@ -0,0 +1,246 @@
using UnityEngine;
namespace AppleHills.Core.Settings
{
/// <summary>
/// Enum defining the type of bump response when player collides with obstacles
/// </summary>
public enum BumpMode
{
Impulse = 0,
SmoothToCenter = 1
}
/// <summary>
/// Developer settings for the diving minigame technical configuration.
/// These settings are separate from gameplay/design settings and focus on technical implementation details.
/// </summary>
[CreateAssetMenu(fileName = "DivingDeveloperSettings", menuName = "AppleHills/Developer Settings/Diving", order = 1)]
public class DivingDeveloperSettings : BaseDeveloperSettings
{
[Header("Bubble System")]
[Tooltip("Object pooling enabled for bubbles")]
[SerializeField] private bool bubbleUseObjectPooling = true;
[Tooltip("Initial number of bubbles to pre-allocate in pool")]
[SerializeField] private int bubbleInitialPoolSize = 10;
[Tooltip("Maximum number of bubbles allowed in pool")]
[SerializeField] private int bubbleMaxPoolSize = 30;
[Tooltip("Default spawn interval for bubbles in seconds")]
[SerializeField] private float bubbleSpawnInterval = 0.3f;
[Tooltip("Range of possible bubble movement speeds (min, max)")]
[SerializeField] private Vector2 bubbleSpeedRange = new Vector2(0.5f, 2f);
[Tooltip("Range of possible bubble scale factors (min, max)")]
[SerializeField] private Vector2 bubbleScaleRange = new Vector2(0.3f, 0.7f);
[Tooltip("Range of possible bubble wobble speeds (min, max)")]
[SerializeField] private Vector2 bubbleWobbleSpeedRange = new Vector2(1f, 3f);
[Tooltip("Range of possible bubble wobble amounts (min, max)")]
[SerializeField] private Vector2 bubbleWobbleAmountRange = new Vector2(0.05f, 0.15f);
[Tooltip("Minimum X position for bubble spawning")]
[SerializeField] private float bubbleSpawnXMin = -3.5f;
[Tooltip("Maximum X position for bubble spawning")]
[SerializeField] private float bubbleSpawnXMax = 3.5f;
[Tooltip("Y position for bubble spawning")]
[SerializeField] private float bubbleSpawnY = -5f;
[Tooltip("Minimum scale factor during wobble animation")]
[SerializeField] private float bubbleWobbleMinScale = 0.2f;
[Tooltip("Maximum scale factor during wobble animation")]
[SerializeField] private float bubbleWobbleMaxScale = 1.2f;
[Tooltip("Factor to multiply bubble speed by when surfacing")]
[SerializeField] private float bubbleSurfacingSpeedFactor = 0.5f;
[Header("Obstacle System")]
[Tooltip("Layer for obstacles to be placed on")]
[Layer]
[SerializeField] private int obstacleLayer = 9;
[Tooltip("Whether to use object pooling for obstacles")]
[SerializeField] private bool obstacleUseObjectPooling = true;
[Tooltip("Maximum objects per prefab type in obstacle pool")]
[SerializeField] private int obstacleMaxPerPrefabPoolSize = 3;
[Tooltip("Total maximum size of obstacle pool across all prefab types")]
[SerializeField] private int obstacleTotalMaxPoolSize = 15;
[Header("Trench Tile System")]
[Tooltip("Layer for trench tiles to be placed on")]
[Layer]
[SerializeField] private int trenchTileLayer = 13; // QuarryTrenchTile layer
[Tooltip("Whether to use object pooling for trench tiles")]
[SerializeField] private bool trenchTileUseObjectPooling = true;
[Tooltip("Maximum objects per prefab type in trench tile pool")]
[SerializeField] private int trenchTileMaxPerPrefabPoolSize = 2;
[Tooltip("Total maximum size of trench tile pool across all prefab types")]
[SerializeField] private int trenchTileTotalMaxPoolSize = 10;
[Header("Player Blink Behavior")]
[Tooltip("Color to blink to when taking damage (typically red for damage indication)")]
[SerializeField] private Color playerBlinkDamageColor = Color.red;
[Tooltip("How fast to blink between normal and damage colors (seconds between color changes)")]
[SerializeField] private float playerBlinkRate = 0.15f;
[Tooltip("Alpha value for the damage color (0 = transparent, 1 = opaque)")]
[Range(0f, 1f)]
[SerializeField] private float playerDamageColorAlpha = 0.7f;
[Header("Player Wobble Behavior")]
[Tooltip("Frequency of wobble (higher = faster rocking)")]
[SerializeField] private float playerWobbleFrequency = 1.5f;
[Tooltip("Base wobble amplitude in degrees from horizontal")]
[SerializeField] private float playerBaseWobbleAmplitude = 8f;
[Tooltip("How much speed affects amplitude")]
[SerializeField] private float playerSpeedToAmplitude = 2f;
[Tooltip("Maximum allowed rotation in degrees")]
[SerializeField] private float playerMaxRotationLimit = 45f;
[Tooltip("Frequency of vertical bobbing")]
[SerializeField] private float playerVerticalFrequency = 0.5f;
[Tooltip("How far the object moves up/down")]
[SerializeField] private float playerVerticalAmplitude = 0.5f;
[Tooltip("How quickly velocity changes are smoothed")]
[SerializeField] private float playerVelocitySmoothing = 10f;
[Tooltip("How quickly rotation is smoothed")]
[SerializeField] private float playerRotationSmoothing = 10f;
[Header("Collision Settings")]
[Tooltip("Layer mask for obstacle detection - configure which layers contain obstacles")]
[LayerMask]
[SerializeField] private LayerMask playerObstacleLayerMask = -1;
[Tooltip("Whether to block player input during damage immunity period")]
[SerializeField] private bool blockInputDuringImmunity = true;
[Tooltip("Type of bump response: 0=Impulse, 1=SmoothToCenter")]
[SerializeField] private BumpMode bumpMode = BumpMode.Impulse;
[Tooltip("Animation curve controlling bump movement over time")]
[SerializeField] private AnimationCurve bumpCurve = new AnimationCurve(
new Keyframe(0f, 0f, 0f, 2f),
new Keyframe(1f, 1f, 0f, 0f));
// Bubble properties access
public bool BubbleUseObjectPooling => bubbleUseObjectPooling;
public int BubbleInitialPoolSize => bubbleInitialPoolSize;
public int BubbleMaxPoolSize => bubbleMaxPoolSize;
public float BubbleSpawnInterval => bubbleSpawnInterval;
public Vector2 BubbleSpeedRange => bubbleSpeedRange;
public Vector2 BubbleScaleRange => bubbleScaleRange;
public Vector2 BubbleWobbleSpeedRange => bubbleWobbleSpeedRange;
public Vector2 BubbleWobbleAmountRange => bubbleWobbleAmountRange;
public float BubbleSpawnXMin => bubbleSpawnXMin;
public float BubbleSpawnXMax => bubbleSpawnXMax;
public float BubbleSpawnY => bubbleSpawnY;
public float BubbleWobbleMinScale => bubbleWobbleMinScale;
public float BubbleWobbleMaxScale => bubbleWobbleMaxScale;
public float BubbleSurfacingSpeedFactor => bubbleSurfacingSpeedFactor;
// Obstacle properties access
public int ObstacleLayer => obstacleLayer;
public bool ObstacleUseObjectPooling => obstacleUseObjectPooling;
public int ObstacleMaxPerPrefabPoolSize => obstacleMaxPerPrefabPoolSize;
public int ObstacleTotalMaxPoolSize => obstacleTotalMaxPoolSize;
// Trench Tile System properties
public int TrenchTileLayer => trenchTileLayer;
public bool TrenchTileUseObjectPooling => trenchTileUseObjectPooling;
public int TrenchTileMaxPerPrefabPoolSize => trenchTileMaxPerPrefabPoolSize;
public int TrenchTileTotalMaxPoolSize => trenchTileTotalMaxPoolSize;
// Player Blink Behavior properties
public Color PlayerBlinkDamageColor => playerBlinkDamageColor;
public float PlayerBlinkRate => playerBlinkRate;
public float PlayerDamageColorAlpha => playerDamageColorAlpha;
// Player Wobble Behavior properties
public float PlayerWobbleFrequency => playerWobbleFrequency;
public float PlayerBaseWobbleAmplitude => playerBaseWobbleAmplitude;
public float PlayerSpeedToAmplitude => playerSpeedToAmplitude;
public float PlayerMaxRotationLimit => playerMaxRotationLimit;
public float PlayerVerticalFrequency => playerVerticalFrequency;
public float PlayerVerticalAmplitude => playerVerticalAmplitude;
public float PlayerVelocitySmoothing => playerVelocitySmoothing;
public float PlayerRotationSmoothing => playerRotationSmoothing;
// Collision Settings properties
public LayerMask PlayerObstacleLayerMask => playerObstacleLayerMask;
public bool BlockInputDuringImmunity => blockInputDuringImmunity;
public BumpMode BumpMode => bumpMode;
public AnimationCurve BumpCurve => bumpCurve;
public override void OnValidate()
{
base.OnValidate();
// Validate bubble settings
bubbleInitialPoolSize = Mathf.Max(1, bubbleInitialPoolSize);
bubbleMaxPoolSize = Mathf.Max(bubbleInitialPoolSize, bubbleMaxPoolSize);
bubbleSpawnInterval = Mathf.Max(0.05f, bubbleSpawnInterval);
bubbleSpeedRange = new Vector2(
Mathf.Max(0.1f, bubbleSpeedRange.x),
Mathf.Max(bubbleSpeedRange.x, bubbleSpeedRange.y)
);
bubbleScaleRange = new Vector2(
Mathf.Max(0.1f, bubbleScaleRange.x),
Mathf.Max(bubbleScaleRange.x, bubbleScaleRange.y)
);
bubbleWobbleSpeedRange = new Vector2(
Mathf.Max(0.1f, bubbleWobbleSpeedRange.x),
Mathf.Max(bubbleWobbleSpeedRange.x, bubbleWobbleSpeedRange.y)
);
bubbleWobbleAmountRange = new Vector2(
Mathf.Max(0.01f, bubbleWobbleAmountRange.x),
Mathf.Max(bubbleWobbleAmountRange.x, bubbleWobbleAmountRange.y)
);
bubbleWobbleMinScale = Mathf.Max(0.01f, bubbleWobbleMinScale);
bubbleWobbleMaxScale = Mathf.Max(bubbleWobbleMinScale, bubbleWobbleMaxScale);
bubbleSurfacingSpeedFactor = Mathf.Max(0.01f, bubbleSurfacingSpeedFactor);
// Validate obstacle settings
obstacleMaxPerPrefabPoolSize = Mathf.Max(1, obstacleMaxPerPrefabPoolSize);
obstacleTotalMaxPoolSize = Mathf.Max(obstacleMaxPerPrefabPoolSize, obstacleTotalMaxPoolSize);
// Validate Trench Tile settings
trenchTileMaxPerPrefabPoolSize = Mathf.Max(1, trenchTileMaxPerPrefabPoolSize);
trenchTileTotalMaxPoolSize = Mathf.Max(trenchTileMaxPerPrefabPoolSize, trenchTileTotalMaxPoolSize);
// Validate Player Blink settings
playerBlinkRate = Mathf.Max(0.01f, playerBlinkRate);
playerDamageColorAlpha = Mathf.Clamp01(playerDamageColorAlpha);
// Validate Player Wobble settings
playerWobbleFrequency = Mathf.Max(0.01f, playerWobbleFrequency);
playerBaseWobbleAmplitude = Mathf.Max(0f, playerBaseWobbleAmplitude);
playerMaxRotationLimit = Mathf.Max(0f, playerMaxRotationLimit);
playerVerticalFrequency = Mathf.Max(0.01f, playerVerticalFrequency);
playerVerticalAmplitude = Mathf.Max(0f, playerVerticalAmplitude);
playerVelocitySmoothing = Mathf.Max(0.1f, playerVelocitySmoothing);
playerRotationSmoothing = Mathf.Max(0.1f, playerRotationSmoothing);
// Validate Collision settings
bumpMode = (BumpMode)Mathf.Clamp((int)bumpMode, 0, 1);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 033961b12e7b4289838d554c2264bacd
timeCreated: 1758707215

View File

@@ -0,0 +1,234 @@
using UnityEngine;
namespace AppleHills.Core.Settings
{
/// <summary>
/// Settings related to minigames
/// </summary>
[CreateAssetMenu(fileName = "MinigameSettings", menuName = "AppleHills/Settings/Minigames", order = 3)]
public class DivingMinigameSettings : BaseSettings, IDivingMinigameSettings
{
[Header("Basic Movement")]
[Tooltip("How quickly the character follows the finger horizontally (higher = more responsive)")]
[SerializeField] private float lerpSpeed = 12f;
[Tooltip("Maximum horizontal offset allowed between character and finger position")]
[SerializeField] private float maxOffset = 3f;
[Tooltip("Minimum allowed X position for movement")]
[SerializeField] private float clampXMin = -3.5f;
[Tooltip("Maximum allowed X position for movement")]
[SerializeField] private float clampXMax = 3.5f;
[Tooltip("Exponent for speed drop-off curve (higher = sharper drop near target)")]
[SerializeField] private float speedExponent = 2.5f;
[Header("Player Movement")]
[Tooltip("Maximum distance the player can move from a single tap")]
[SerializeField] private float tapMaxDistance = 0.5f;
[Tooltip("How quickly the tap impulse fades (higher = faster stop)")]
[SerializeField] private float tapDecelerationRate = 5.0f;
[Header("Monster Spawning")]
[Tooltip("Base chance (0-1) of spawning a monster on each tile")]
[SerializeField] private float baseSpawnProbability = 0.2f;
[Tooltip("Maximum chance (0-1) of spawning a monster")]
[SerializeField] private float maxSpawnProbability = 0.5f;
[Tooltip("How fast the probability increases per second")]
[SerializeField] private float probabilityIncreaseRate = 0.01f;
[Tooltip("Force a spawn after this many seconds without spawns")]
[SerializeField] private float guaranteedSpawnTime = 30f;
[Tooltip("Minimum time between monster spawns")]
[SerializeField] private float spawnCooldown = 5f;
[Header("Scoring")]
[Tooltip("Base points for taking a picture")]
[SerializeField] private int basePoints = 100;
[Tooltip("Additional points per depth unit")]
[SerializeField] private int depthMultiplier = 10;
[Header("Surfacing")]
[Tooltip("Duration in seconds for speed transition when surfacing")]
[SerializeField] private float speedTransitionDuration = 2.0f;
[Tooltip("Factor to multiply speed by when surfacing (usually 1.0 for same speed)")]
[SerializeField] private float surfacingSpeedFactor = 3.0f;
[Tooltip("How long to continue spawning tiles after surfacing begins (seconds)")]
[SerializeField] private float surfacingSpawnDelay = 5.0f;
[Header("Tile Generation")]
[Tooltip("Initial number of tiles to create at start")]
[SerializeField] private int initialTileCount = 3;
[Tooltip("Buffer distance for spawning new tiles")]
[SerializeField] private float tileSpawnBuffer = 1f;
[Tooltip("Base movement speed for tiles")]
[SerializeField] private float moveSpeed = 3f;
[Tooltip("Factor to increase speed by each interval")]
[SerializeField] private float speedUpFactor = 0.2f;
[Tooltip("Time interval between speed increases (seconds)")]
[SerializeField] private float speedUpInterval = 10f;
[Tooltip("Maximum movement speed allowed")]
[SerializeField] private float maxMoveSpeed = 12f;
[Tooltip("Interval for velocity calculations (seconds)")]
[SerializeField] private float velocityCalculationInterval = 0.5f;
[Header("Obstacles")]
[Tooltip("Time interval between obstacle spawn attempts (in seconds)")]
[SerializeField] private float obstacleSpawnInterval = 2f;
[Tooltip("Random variation in obstacle spawn timing (+/- seconds)")]
[SerializeField] private float obstacleSpawnIntervalVariation = 0.5f;
[Tooltip("Maximum number of obstacle spawn position attempts before skipping")]
[SerializeField] private int obstacleMaxSpawnAttempts = 10;
[Tooltip("Radius around obstacle spawn point to check for tile collisions")]
[SerializeField] private float obstacleSpawnCollisionRadius = 1f;
[Tooltip("Minimum movement speed for spawned obstacles")]
[SerializeField] private float obstacleMinMoveSpeed = 1f;
[Tooltip("Maximum movement speed for spawned obstacles")]
[SerializeField] private float obstacleMaxMoveSpeed = 4f;
[Header("Collision Handling")]
[Tooltip("Duration in seconds of damage immunity after being hit")]
[SerializeField] private float damageImmunityDuration = 1.0f;
[Tooltip("Force strength for impulse bumps - higher values push further toward center")]
[SerializeField] private float bumpForce = 5.0f;
[Tooltip("Speed for smooth movement to center (units per second)")]
[SerializeField] private float smoothMoveSpeed = 8.0f;
[Tooltip("Whether to block player input during bump movement")]
[SerializeField] private bool blockInputDuringBump = true;
// IDivingMinigameSettings implementation - Basic Movement
public float LerpSpeed => lerpSpeed;
public float MaxOffset => maxOffset;
public float ClampXMin => clampXMin;
public float ClampXMax => clampXMax;
public float SpeedExponent => speedExponent;
// IDivingMinigameSettings implementation - Player Movement
public float TapMaxDistance => tapMaxDistance;
public float TapDecelerationRate => tapDecelerationRate;
// IDivingMinigameSettings implementation - Monster Spawning
public float BaseSpawnProbability => baseSpawnProbability;
public float MaxSpawnProbability => maxSpawnProbability;
public float ProbabilityIncreaseRate => probabilityIncreaseRate;
public float GuaranteedSpawnTime => guaranteedSpawnTime;
public float SpawnCooldown => spawnCooldown;
// IDivingMinigameSettings implementation - Scoring
public int BasePoints => basePoints;
public int DepthMultiplier => depthMultiplier;
// IDivingMinigameSettings implementation - Surfacing
public float SpeedTransitionDuration => speedTransitionDuration;
public float SurfacingSpeedFactor => surfacingSpeedFactor;
public float SurfacingSpawnDelay => surfacingSpawnDelay;
// IDivingMinigameSettings implementation - Tile Generation
public int InitialTileCount => initialTileCount;
public float TileSpawnBuffer => tileSpawnBuffer;
public float MoveSpeed => moveSpeed;
public float SpeedUpFactor => speedUpFactor;
public float SpeedUpInterval => speedUpInterval;
public float MaxMoveSpeed => maxMoveSpeed;
public float VelocityCalculationInterval => velocityCalculationInterval;
// IDivingMinigameSettings implementation - Obstacles
public float ObstacleSpawnInterval => obstacleSpawnInterval;
public float ObstacleSpawnIntervalVariation => obstacleSpawnIntervalVariation;
public int ObstacleMaxSpawnAttempts => obstacleMaxSpawnAttempts;
public float ObstacleSpawnCollisionRadius => obstacleSpawnCollisionRadius;
public float ObstacleMinMoveSpeed => obstacleMinMoveSpeed;
public float ObstacleMaxMoveSpeed => obstacleMaxMoveSpeed;
// IDivingMinigameSettings implementation - Collision Handling
public float DamageImmunityDuration => damageImmunityDuration;
public float BumpForce => bumpForce;
public float SmoothMoveSpeed => smoothMoveSpeed;
public bool BlockInputDuringBump => blockInputDuringBump;
public override void OnValidate()
{
base.OnValidate();
// Validate basic movement values
lerpSpeed = Mathf.Max(0.1f, lerpSpeed);
maxOffset = Mathf.Max(0.1f, maxOffset);
speedExponent = Mathf.Max(0.1f, speedExponent);
// Ensure min is less than max for clamping
if (clampXMin >= clampXMax)
{
clampXMin = clampXMax - 0.1f;
}
// Validate player movement
tapMaxDistance = Mathf.Max(0.01f, tapMaxDistance);
tapDecelerationRate = Mathf.Max(0.1f, tapDecelerationRate);
// Validate probability values
baseSpawnProbability = Mathf.Clamp01(baseSpawnProbability);
maxSpawnProbability = Mathf.Clamp01(maxSpawnProbability);
probabilityIncreaseRate = Mathf.Max(0f, probabilityIncreaseRate);
// Ensure max probability is at least base probability
if (maxSpawnProbability < baseSpawnProbability)
{
maxSpawnProbability = baseSpawnProbability;
}
// Validate time values
guaranteedSpawnTime = Mathf.Max(0.1f, guaranteedSpawnTime);
spawnCooldown = Mathf.Max(0.1f, spawnCooldown);
speedTransitionDuration = Mathf.Max(0.1f, speedTransitionDuration);
surfacingSpawnDelay = Mathf.Max(0f, surfacingSpawnDelay);
// Validate scoring
basePoints = Mathf.Max(0, basePoints);
depthMultiplier = Mathf.Max(0, depthMultiplier);
// Validate tile generation
initialTileCount = Mathf.Max(1, initialTileCount);
tileSpawnBuffer = Mathf.Max(0f, tileSpawnBuffer);
moveSpeed = Mathf.Max(0.1f, moveSpeed);
speedUpFactor = Mathf.Max(0f, speedUpFactor);
speedUpInterval = Mathf.Max(0.1f, speedUpInterval);
maxMoveSpeed = Mathf.Max(moveSpeed, maxMoveSpeed);
velocityCalculationInterval = Mathf.Max(0.01f, velocityCalculationInterval);
// Validate obstacle values
obstacleSpawnInterval = Mathf.Max(0.1f, obstacleSpawnInterval);
obstacleSpawnIntervalVariation = Mathf.Max(0f, obstacleSpawnIntervalVariation);
obstacleMaxSpawnAttempts = Mathf.Max(1, obstacleMaxSpawnAttempts);
obstacleSpawnCollisionRadius = Mathf.Max(0.1f, obstacleSpawnCollisionRadius);
obstacleMinMoveSpeed = Mathf.Max(0.1f, obstacleMinMoveSpeed);
obstacleMaxMoveSpeed = Mathf.Max(obstacleMinMoveSpeed, obstacleMaxMoveSpeed);
// Validate collision settings
damageImmunityDuration = Mathf.Max(0.1f, damageImmunityDuration);
bumpForce = Mathf.Max(0.1f, bumpForce);
smoothMoveSpeed = Mathf.Max(0.1f, smoothMoveSpeed);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0ce4dba7a1c54e73b1b3d7131a1c0570
timeCreated: 1758619927

View File

@@ -0,0 +1,48 @@
using System.Collections.Generic;
using UnityEngine;
namespace AppleHills.Core.Settings
{
/// <summary>
/// Settings related to interactions and items
/// </summary>
[CreateAssetMenu(fileName = "InteractionSettings", menuName = "AppleHills/Settings/Interaction & Items", order = 2)]
public class InteractionSettings : BaseSettings, IInteractionSettings
{
[Header("Interactions")]
[SerializeField] private float playerStopDistance = 6.0f;
[SerializeField] private float playerStopDistanceDirectInteraction = 2.0f;
[SerializeField] private float followerPickupDelay = 0.2f;
[Header("InputManager Settings")]
[Tooltip("Layer(s) to use for interactable objects.")]
[SerializeField] private LayerMask interactableLayerMask = -1; // Default to Everything
[Header("Default Prefabs")]
[SerializeField] private GameObject basePickupPrefab;
[SerializeField] private GameObject levelSwitchMenuPrefab;
[Header("Item Configuration")]
[SerializeField] private List<CombinationRule> combinationRules = new List<CombinationRule>();
[SerializeField] private List<SlotItemConfig> slotItemConfigs = new List<SlotItemConfig>();
// IInteractionSettings implementation
public float PlayerStopDistance => playerStopDistance;
public float PlayerStopDistanceDirectInteraction => playerStopDistanceDirectInteraction;
public float FollowerPickupDelay => followerPickupDelay;
public LayerMask InteractableLayerMask => interactableLayerMask;
public GameObject BasePickupPrefab => basePickupPrefab;
public GameObject LevelSwitchMenuPrefab => levelSwitchMenuPrefab;
public List<CombinationRule> CombinationRules => combinationRules;
public List<SlotItemConfig> SlotItemConfigs => slotItemConfigs;
public override void OnValidate()
{
base.OnValidate();
// Validate values
playerStopDistance = Mathf.Max(0.1f, playerStopDistance);
playerStopDistanceDirectInteraction = Mathf.Max(0.1f, playerStopDistanceDirectInteraction);
followerPickupDelay = Mathf.Max(0f, followerPickupDelay);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ac22b092dc6f4db5b3dad35172b6e4c4
timeCreated: 1758619914

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,20 @@
using UnityEngine;
namespace AppleHills.Core.Settings
{
/// <summary>
/// Attribute to indicate a field should be drawn using the layer selector dropdown
/// </summary>
public class LayerAttribute : PropertyAttribute
{
// No properties needed - this is a marker attribute
}
/// <summary>
/// Attribute to indicate a field should be drawn using the layer mask selector dropdown
/// </summary>
public class LayerMaskAttribute : PropertyAttribute
{
// No properties needed - this is a marker attribute
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 7c64dbd728524f23bda766b57a388207
timeCreated: 1758711688

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

@@ -0,0 +1,53 @@
using UnityEngine;
namespace AppleHills.Core.Settings
{
/// <summary>
/// Settings related to player and follower behavior
/// </summary>
[CreateAssetMenu(fileName = "PlayerFollowerSettings", menuName = "AppleHills/Settings/Player & Follower", order = 1)]
public class PlayerFollowerSettings : BaseSettings, IPlayerFollowerSettings
{
[Header("Player Settings")]
[SerializeField] private float moveSpeed = 5f;
[SerializeField] private float stopDistance = 0.1f;
[SerializeField] private bool useRigidbody = true;
[SerializeField] private HoldMovementMode defaultHoldMovementMode = HoldMovementMode.Pathfinding;
[Header("Follower Settings")]
[SerializeField] private float followDistance = 1.5f;
[SerializeField] private float manualMoveSmooth = 8f;
[SerializeField] private float thresholdFar = 2.5f;
[SerializeField] private float thresholdNear = 0.5f;
[SerializeField] private float stopThreshold = 0.1f;
[Header("Backend Settings")]
[Tooltip("Technical parameters, not for design tuning")]
[SerializeField] private float followUpdateInterval = 0.1f;
[SerializeField] private float followerSpeedMultiplier = 1.2f;
[SerializeField] private float heldIconDisplayHeight = 2.0f;
// IPlayerFollowerSettings implementation
public float MoveSpeed => moveSpeed;
public float StopDistance => stopDistance;
public bool UseRigidbody => useRigidbody;
public HoldMovementMode DefaultHoldMovementMode => defaultHoldMovementMode;
public float FollowDistance => followDistance;
public float ManualMoveSmooth => manualMoveSmooth;
public float ThresholdFar => thresholdFar;
public float ThresholdNear => thresholdNear;
public float StopThreshold => stopThreshold;
public float FollowUpdateInterval => followUpdateInterval;
public float FollowerSpeedMultiplier => followerSpeedMultiplier;
public float HeldIconDisplayHeight => heldIconDisplayHeight;
public override void OnValidate()
{
base.OnValidate();
// Validate values
moveSpeed = Mathf.Max(0.1f, moveSpeed);
followDistance = Mathf.Max(0.1f, followDistance);
followerSpeedMultiplier = Mathf.Max(0.1f, followerSpeedMultiplier);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 32cd6d14d9304d5ba0fd590da1346654
timeCreated: 1758619904

View File

@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace AppleHills.Core.Settings
{
/// <summary>
/// Service Locator implementation for managing settings services.
/// Provides a central registry for all settings services.
/// </summary>
public static class ServiceLocator
{
private static readonly Dictionary<Type, object> _services = new Dictionary<Type, object>();
/// <summary>
/// Register a service with the service locator.
/// </summary>
/// <typeparam name="T">The interface type for the service</typeparam>
/// <param name="service">The service implementation</param>
public static void Register<T>(T service) where T : class
{
_services[typeof(T)] = service;
Debug.Log($"Service registered: {typeof(T).Name}");
}
/// <summary>
/// Get a service from the service locator.
/// </summary>
/// <typeparam name="T">The interface type for the service</typeparam>
/// <returns>The service implementation, or null if not found</returns>
public static T Get<T>() where T : class
{
if (_services.TryGetValue(typeof(T), out object service))
{
return service as T;
}
Debug.LogWarning($"Service of type {typeof(T).Name} not found!");
return null;
}
/// <summary>
/// Clear all registered services.
/// </summary>
public static void Clear()
{
_services.Clear();
Debug.Log("All services cleared");
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 16cc39d2f99b4e7fa65c4a8b39f3e87c
timeCreated: 1758619866

View File

@@ -0,0 +1,98 @@
using UnityEngine;
using System.Collections.Generic;
namespace AppleHills.Core.Settings
{
/// <summary>
/// Interface for player and follower settings
/// </summary>
public interface IPlayerFollowerSettings
{
// Player settings
float MoveSpeed { get; }
float StopDistance { get; }
bool UseRigidbody { get; }
HoldMovementMode DefaultHoldMovementMode { get; }
// Follower settings
float FollowDistance { get; }
float ManualMoveSmooth { get; }
float ThresholdFar { get; }
float ThresholdNear { get; }
float StopThreshold { get; }
float FollowUpdateInterval { get; }
float FollowerSpeedMultiplier { get; }
float HeldIconDisplayHeight { get; }
}
/// <summary>
/// Interface for interaction and item settings
/// </summary>
public interface IInteractionSettings
{
float PlayerStopDistance { get; }
float PlayerStopDistanceDirectInteraction { get; }
float FollowerPickupDelay { get; }
LayerMask InteractableLayerMask { get; }
GameObject BasePickupPrefab { get; }
GameObject LevelSwitchMenuPrefab { get; }
List<CombinationRule> CombinationRules { get; }
List<SlotItemConfig> SlotItemConfigs { get; }
}
/// <summary>
/// Interface for minigame settings
/// </summary>
public interface IDivingMinigameSettings
{
// Basic Movement
float LerpSpeed { get; }
float MaxOffset { get; }
float ClampXMin { get; }
float ClampXMax { get; }
float SpeedExponent { get; }
// Player Movement
float TapMaxDistance { get; }
float TapDecelerationRate { get; }
// Monster Spawning
float BaseSpawnProbability { get; }
float MaxSpawnProbability { get; }
float ProbabilityIncreaseRate { get; }
float GuaranteedSpawnTime { get; }
float SpawnCooldown { get; }
// Scoring
int BasePoints { get; }
int DepthMultiplier { get; }
// Surfacing
float SpeedTransitionDuration { get; }
float SurfacingSpeedFactor { get; }
float SurfacingSpawnDelay { get; }
// Tile Generation
int InitialTileCount { get; }
float TileSpawnBuffer { get; }
float MoveSpeed { get; }
float SpeedUpFactor { get; }
float SpeedUpInterval { get; }
float MaxMoveSpeed { get; }
float VelocityCalculationInterval { get; }
// Obstacles
float ObstacleSpawnInterval { get; }
float ObstacleSpawnIntervalVariation { get; }
int ObstacleMaxSpawnAttempts { get; }
float ObstacleSpawnCollisionRadius { get; }
float ObstacleMinMoveSpeed { get; }
float ObstacleMaxMoveSpeed { get; }
// Collision Handling
float DamageImmunityDuration { get; }
float BumpForce { get; }
float SmoothMoveSpeed { get; }
bool BlockInputDuringBump { get; }
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 54611ae012ab4455a53bd60961d9e7ea
timeCreated: 1758619892

View File

@@ -0,0 +1,100 @@
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
namespace AppleHills.Core.Settings
{
/// <summary>
/// Responsible for loading and caching settings from Addressables.
/// Uses synchronous loading to ensure settings are available immediately.
/// </summary>
public class SettingsProvider : MonoBehaviour
{
private static SettingsProvider _instance;
private Dictionary<string, BaseSettings> _settingsCache = new Dictionary<string, BaseSettings>();
// Singleton instance
public static SettingsProvider Instance
{
get
{
if (_instance == null)
{
GameObject go = new GameObject("Settings Provider");
_instance = go.AddComponent<SettingsProvider>();
DontDestroyOnLoad(go);
}
return _instance;
}
}
private void Awake()
{
if (_instance == null)
{
_instance = this;
DontDestroyOnLoad(gameObject);
}
else if (_instance != this)
{
Destroy(gameObject);
}
}
/// <summary>
/// Load settings synchronously using Addressables - blocks until complete
/// </summary>
public T LoadSettingsSynchronous<T>() where T : BaseSettings
{
string key = typeof(T).Name;
// Return from cache if already loaded
if (_settingsCache.TryGetValue(key, out BaseSettings cachedSettings))
{
return cachedSettings as T;
}
// Load using Addressables synchronously
try
{
// WaitForCompletion blocks until the asset is loaded
T settings = Addressables.LoadAssetAsync<T>($"Settings/{key}").WaitForCompletion();
if (settings != null)
{
_settingsCache[key] = settings;
return settings;
}
else
{
Debug.LogError($"Failed to load settings: {key}");
}
}
catch (Exception e)
{
Debug.LogError($"Error loading settings {key}: {e.Message}");
}
return null;
}
/// <summary>
/// Get cached settings or load them synchronously if not cached
/// </summary>
public T GetSettings<T>() where T : BaseSettings
{
string key = typeof(T).Name;
// Return from cache if already loaded
if (_settingsCache.TryGetValue(key, out BaseSettings cachedSettings))
{
return cachedSettings as T;
}
// Load synchronously if not in cache
return LoadSettingsSynchronous<T>();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4d212b25192045d198f2bf42ef74f278
timeCreated: 1758619879

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

Some files were not shown because too many files have changed in this diff Show More