diff --git a/Assets/Data/Bootstrap/Runtime/CustomBootSettings_Runtime.asset b/Assets/Data/Bootstrap/Runtime/CustomBootSettings_Runtime.asset index 8936563c..b5e80b82 100644 --- a/Assets/Data/Bootstrap/Runtime/CustomBootSettings_Runtime.asset +++ b/Assets/Data/Bootstrap/Runtime/CustomBootSettings_Runtime.asset @@ -25,3 +25,4 @@ MonoBehaviour: - {fileID: 3528960956969533010, guid: 53eea3840d3cde34a9768b8773a3a7e8, type: 3} - {fileID: 5034240524438268576, guid: b15ba9d3d508ef244b0eeb76404dc9de, type: 3} - {fileID: 7207007194116694737, guid: 7180ae585f0db8044ba048426f72d995, type: 3} + - {fileID: 4983412436654784526, guid: fcb8163ded24853438b30c37ddf2edeb, type: 3} diff --git a/Assets/External/Placeholders/direction_pin.png b/Assets/External/Placeholders/direction_pin.png new file mode 100644 index 00000000..2c19f1c8 Binary files /dev/null and b/Assets/External/Placeholders/direction_pin.png differ diff --git a/Assets/External/Placeholders/direction_pin.png.meta b/Assets/External/Placeholders/direction_pin.png.meta new file mode 100644 index 00000000..7619436b --- /dev/null +++ b/Assets/External/Placeholders/direction_pin.png.meta @@ -0,0 +1,195 @@ +fileFormatVersion: 2 +guid: 8644828a229b5e34fb635653ae864d8e +TextureImporter: + internalIDToNameTable: + - first: + 213: -3432867975278251356 + second: direction_pin_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: direction_pin_0 + rect: + serializedVersion: 2 + x: 0 + y: 0 + width: 600 + height: 600 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + customData: + outline: [] + physicsShape: [] + tessellationDetail: -1 + bones: [] + spriteID: 4a2b9bcb3c00c50d0800000000000000 + internalID: -3432867975278251356 + vertices: [] + indices: + edges: [] + weights: [] + outline: [] + customData: + physicsShape: [] + bones: [] + spriteID: 9922cdfd3cfd3a445add26a083e9e24d + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spriteCustomMetadata: + entries: [] + nameFileIdTable: + direction_pin_0: -3432867975278251356 + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/Placeholders/pulver_portrait.png b/Assets/External/Placeholders/pulver_portrait.png new file mode 100644 index 00000000..c5bf3653 Binary files /dev/null and b/Assets/External/Placeholders/pulver_portrait.png differ diff --git a/Assets/External/Placeholders/pulver_portrait.png.meta b/Assets/External/Placeholders/pulver_portrait.png.meta new file mode 100644 index 00000000..c9a0c8b4 --- /dev/null +++ b/Assets/External/Placeholders/pulver_portrait.png.meta @@ -0,0 +1,203 @@ +fileFormatVersion: 2 +guid: 31cfa2eea2b70af4b97a7a588fad0758 +TextureImporter: + internalIDToNameTable: + - first: + 213: -4695408507704126972 + second: pulver_portrait_0 + - first: + 213: 3051712845612519695 + second: pulver_portrait_1 + - first: + 213: 5677750735195355539 + second: pulver_portrait_2 + 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: pulver_portrait_0 + rect: + serializedVersion: 2 + x: 0 + y: 0 + width: 512 + height: 512 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + customData: + outline: [] + physicsShape: [] + tessellationDetail: -1 + bones: [] + spriteID: 402d2fee6de86deb0800000000000000 + internalID: -4695408507704126972 + vertices: [] + indices: + edges: [] + weights: [] + outline: [] + customData: + physicsShape: [] + bones: [] + spriteID: dcca4d5ff8b0cef4e9930d67f16d1ab3 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spriteCustomMetadata: + entries: + - key: SpriteEditor.SliceSettings + value: '{"sliceOnImport":false,"gridCellCount":{"x":1.0,"y":1.0},"gridSpriteSize":{"x":512.0,"y":512.0},"gridSpriteOffset":{"x":0.0,"y":0.0},"gridSpritePadding":{"x":0.0,"y":0.0},"pivot":{"x":0.5,"y":0.5},"pivotPixels":{"x":0.0,"y":0.0},"autoSlicingMethod":0,"spriteAlignment":0,"pivotUnitMode":0,"slicingType":2,"keepEmptyRects":false,"isAlternate":false}' + nameFileIdTable: + pulver_portrait_0: -4695408507704126972 + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/External/Placeholders/worker_portrait.png b/Assets/External/Placeholders/worker_portrait.png new file mode 100644 index 00000000..82f32ed7 Binary files /dev/null and b/Assets/External/Placeholders/worker_portrait.png differ diff --git a/Assets/External/Placeholders/worker_portrait.png.meta b/Assets/External/Placeholders/worker_portrait.png.meta new file mode 100644 index 00000000..626b7fd9 --- /dev/null +++ b/Assets/External/Placeholders/worker_portrait.png.meta @@ -0,0 +1,195 @@ +fileFormatVersion: 2 +guid: 58037dbd810a63a47a68876b0c3fd806 +TextureImporter: + internalIDToNameTable: + - first: + 213: 3598403321438170730 + second: worker_portrait_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: worker_portrait_0 + rect: + serializedVersion: 2 + x: 96 + y: 0 + width: 389 + height: 458 + alignment: 0 + pivot: {x: 0, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + customData: + outline: [] + physicsShape: [] + tessellationDetail: -1 + bones: [] + spriteID: a6e68e471c810f130800000000000000 + internalID: 3598403321438170730 + vertices: [] + indices: + edges: [] + weights: [] + outline: [] + customData: + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spriteCustomMetadata: + entries: [] + nameFileIdTable: + worker_portrait_0: 3598403321438170730 + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/Characters/PlayerCharacter.prefab b/Assets/Prefabs/Characters/PlayerCharacter.prefab index 29511fc0..507f9441 100644 --- a/Assets/Prefabs/Characters/PlayerCharacter.prefab +++ b/Assets/Prefabs/Characters/PlayerCharacter.prefab @@ -17,6 +17,7 @@ GameObject: - component: {fileID: 6336381894250237969} - component: {fileID: 8135726788839410285} - component: {fileID: 6886292839344240547} + - component: {fileID: 2906571682423105610} m_Layer: 7 m_Name: PlayerCharacter m_TagString: Player @@ -90,6 +91,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 2ecb5bf6d8f447368687404e1b24278d, type: 3} m_Name: m_EditorClassIdentifier: + moveSpeed: 5 obstacleMask: serializedVersion: 2 m_Bits: 576 @@ -235,6 +237,18 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d5435358d90b4c29982a670998cd9a56, type: 3} m_Name: m_EditorClassIdentifier: +--- !u!114 &2906571682423105610 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4157358163210553531} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1788298f42bd40f6b077ca3719861752, type: 3} + m_Name: + m_EditorClassIdentifier: AppleHillsScripts::UI.Tracking.TrackingDistanceSource --- !u!1001 &5987404377581859689 PrefabInstance: m_ObjectHideFlags: 0 diff --git a/Assets/Prefabs/Characters/PulverCharacter.prefab b/Assets/Prefabs/Characters/PulverCharacter.prefab index 20c39b93..2999c216 100644 --- a/Assets/Prefabs/Characters/PulverCharacter.prefab +++ b/Assets/Prefabs/Characters/PulverCharacter.prefab @@ -18,6 +18,7 @@ GameObject: - component: {fileID: 2639422347702149680} - component: {fileID: 4467608046243604209} - component: {fileID: 887004370483616855} + - component: {fileID: 3342764969520326238} m_Layer: 8 m_Name: PulverCharacter m_TagString: Pulver @@ -143,7 +144,7 @@ MonoBehaviour: radius: 2 height: 2 canMove: 1 - maxSpeed: 30 + maxSpeed: 15 gravity: {x: 0, y: 0, z: 0} groundMask: serializedVersion: 2 @@ -160,7 +161,7 @@ MonoBehaviour: maximumInterval: 2 visualizeSensitivity: 0 targetCompatibility: {fileID: 0} - maxAcceleration: 10000 + maxAcceleration: 1000 rotationSpeed: 360 slowdownDistance: 3 pickNextWaypointDist: 2 @@ -364,6 +365,20 @@ MonoBehaviour: audioSource: {fileID: 0} clipPriority: 0 sourcePriority: 0 +--- !u!114 &3342764969520326238 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1102400833121127473} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e41f200c954677b4b8bde8cafa01d5f1, type: 3} + m_Name: + m_EditorClassIdentifier: AppleHillsScripts::UI.Tracking.TrackableTarget + icon: {fileID: -4695408507704126972, guid: 31cfa2eea2b70af4b97a7a588fad0758, type: 3} + trackDistance: 0 --- !u!1 &5934518940303293264 GameObject: m_ObjectHideFlags: 0 @@ -398,6 +413,7 @@ Transform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!212 &2099200424669714683 SpriteRenderer: + serializedVersion: 2 m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} @@ -443,6 +459,7 @@ SpriteRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 1 + m_MaskInteraction: 0 m_Sprite: {fileID: 0} m_Color: {r: 1, g: 1, b: 1, a: 1} m_FlipX: 0 @@ -452,7 +469,6 @@ SpriteRenderer: m_AdaptiveModeThreshold: 0.5 m_SpriteTileMode: 0 m_WasSpriteAssigned: 0 - m_MaskInteraction: 0 m_SpriteSortPoint: 0 --- !u!1001 &403634400421951211 PrefabInstance: diff --git a/Assets/Prefabs/Minigames/Airplane/Airplanes/AirPlane.prefab b/Assets/Prefabs/Minigames/Airplane/Airplanes/AirPlane.prefab index 57932dfb..f21724ff 100644 --- a/Assets/Prefabs/Minigames/Airplane/Airplanes/AirPlane.prefab +++ b/Assets/Prefabs/Minigames/Airplane/Airplanes/AirPlane.prefab @@ -12,6 +12,7 @@ GameObject: - component: {fileID: 8935501695810778450} - component: {fileID: 7899983481931266200} - component: {fileID: 413068145424314250} + - component: {fileID: 2888024828059124793} m_Layer: 0 m_Name: AirPlane m_TagString: Untagged @@ -129,8 +130,19 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: AppleHillsScripts::Minigames.Airplane.Core.AirplaneController gravity: 9.81 - rotateToVelocity: 1 showDebugLogs: 0 +--- !u!114 &2888024828059124793 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2043346932243838886} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1788298f42bd40f6b077ca3719861752, type: 3} + m_Name: + m_EditorClassIdentifier: AppleHillsScripts::UI.Tracking.TrackingDistanceSource --- !u!1 &5971651627485237503 GameObject: m_ObjectHideFlags: 0 @@ -165,6 +177,7 @@ Transform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!212 &2064624806715645393 SpriteRenderer: + serializedVersion: 2 m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} @@ -210,6 +223,7 @@ SpriteRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_MaskInteraction: 0 m_Sprite: {fileID: 1411070990185071134, guid: 4f579a820baebc14a9151832fbe37559, type: 3} m_Color: {r: 1, g: 1, b: 1, a: 1} m_FlipX: 0 @@ -219,5 +233,4 @@ SpriteRenderer: m_AdaptiveModeThreshold: 0.5 m_SpriteTileMode: 0 m_WasSpriteAssigned: 1 - m_MaskInteraction: 0 m_SpriteSortPoint: 0 diff --git a/Assets/Prefabs/Minigames/Airplane/Airplanes/AirPlane_blue.prefab b/Assets/Prefabs/Minigames/Airplane/Airplanes/AirPlane_blue.prefab index 11c1cb73..98f83498 100644 --- a/Assets/Prefabs/Minigames/Airplane/Airplanes/AirPlane_blue.prefab +++ b/Assets/Prefabs/Minigames/Airplane/Airplanes/AirPlane_blue.prefab @@ -12,6 +12,7 @@ GameObject: - component: {fileID: 8935501695810778450} - component: {fileID: 7899983481931266200} - component: {fileID: 413068145424314250} + - component: {fileID: 6006429398821988093} m_Layer: 0 m_Name: AirPlane_blue m_TagString: Untagged @@ -130,6 +131,18 @@ MonoBehaviour: m_EditorClassIdentifier: AppleHillsScripts::Minigames.Airplane.Core.AirplaneController gravity: 9.81 showDebugLogs: 0 +--- !u!114 &6006429398821988093 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2043346932243838886} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1788298f42bd40f6b077ca3719861752, type: 3} + m_Name: + m_EditorClassIdentifier: AppleHillsScripts::UI.Tracking.TrackingDistanceSource --- !u!1 &5971651627485237503 GameObject: m_ObjectHideFlags: 0 @@ -164,6 +177,7 @@ Transform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!212 &2064624806715645393 SpriteRenderer: + serializedVersion: 2 m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} @@ -209,6 +223,7 @@ SpriteRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_MaskInteraction: 0 m_Sprite: {fileID: -1386115237479607260, guid: ba6d4f958f29f8b45a8f670d869733fe, type: 3} m_Color: {r: 1, g: 1, b: 1, a: 1} m_FlipX: 0 @@ -218,5 +233,4 @@ SpriteRenderer: m_AdaptiveModeThreshold: 0.5 m_SpriteTileMode: 0 m_WasSpriteAssigned: 1 - m_MaskInteraction: 0 m_SpriteSortPoint: 0 diff --git a/Assets/Prefabs/Minigames/Airplane/Airplanes/AirPlane_red.prefab b/Assets/Prefabs/Minigames/Airplane/Airplanes/AirPlane_red.prefab index 6c5484a7..9ba778e9 100644 --- a/Assets/Prefabs/Minigames/Airplane/Airplanes/AirPlane_red.prefab +++ b/Assets/Prefabs/Minigames/Airplane/Airplanes/AirPlane_red.prefab @@ -12,6 +12,7 @@ GameObject: - component: {fileID: 8935501695810778450} - component: {fileID: 7899983481931266200} - component: {fileID: 413068145424314250} + - component: {fileID: 2300146628333848023} m_Layer: 0 m_Name: AirPlane_red m_TagString: Untagged @@ -130,6 +131,18 @@ MonoBehaviour: m_EditorClassIdentifier: AppleHillsScripts::Minigames.Airplane.Core.AirplaneController gravity: 9.81 showDebugLogs: 0 +--- !u!114 &2300146628333848023 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2043346932243838886} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 1788298f42bd40f6b077ca3719861752, type: 3} + m_Name: + m_EditorClassIdentifier: AppleHillsScripts::UI.Tracking.TrackingDistanceSource --- !u!1 &5971651627485237503 GameObject: m_ObjectHideFlags: 0 @@ -164,6 +177,7 @@ Transform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!212 &2064624806715645393 SpriteRenderer: + serializedVersion: 2 m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} @@ -209,6 +223,7 @@ SpriteRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_MaskInteraction: 0 m_Sprite: {fileID: -5545584635573524598, guid: 333a17a4395130b46984c04bbb6e09ea, type: 3} m_Color: {r: 1, g: 1, b: 1, a: 1} m_FlipX: 0 @@ -218,5 +233,4 @@ SpriteRenderer: m_AdaptiveModeThreshold: 0.5 m_SpriteTileMode: 0 m_WasSpriteAssigned: 1 - m_MaskInteraction: 0 m_SpriteSortPoint: 0 diff --git a/Assets/Prefabs/Minigames/Airplane/PlaceholderSpawns/Placeholder_Target_Bob.prefab b/Assets/Prefabs/Minigames/Airplane/PlaceholderSpawns/Placeholder_Target_Bob.prefab index 042d458a..519d494b 100644 --- a/Assets/Prefabs/Minigames/Airplane/PlaceholderSpawns/Placeholder_Target_Bob.prefab +++ b/Assets/Prefabs/Minigames/Airplane/PlaceholderSpawns/Placeholder_Target_Bob.prefab @@ -12,6 +12,7 @@ GameObject: - component: {fileID: 8972759402263058808} - component: {fileID: 2399602594988894182} - component: {fileID: 7284054513935473023} + - component: {fileID: 6758778020698182616} m_Layer: 0 m_Name: Placeholder_Target_Bob m_TagString: Untagged @@ -156,3 +157,17 @@ MonoBehaviour: activeColor: {r: 0, g: 0.45736456, b: 1, a: 1} inactiveColor: {r: 0.10131009, g: 0.1014865, b: 0.10188681, a: 0.40784314} showDebugLogs: 0 +--- !u!114 &6758778020698182616 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3207629437433571205} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e41f200c954677b4b8bde8cafa01d5f1, type: 3} + m_Name: + m_EditorClassIdentifier: AppleHillsScripts::UI.Tracking.TrackableTarget + icon: {fileID: 3598403321438170730, guid: 58037dbd810a63a47a68876b0c3fd806, type: 3} + trackDistance: 1 diff --git a/Assets/Prefabs/UI/PinObject.prefab b/Assets/Prefabs/UI/PinObject.prefab new file mode 100644 index 00000000..8a3efff5 --- /dev/null +++ b/Assets/Prefabs/UI/PinObject.prefab @@ -0,0 +1,343 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &2168646030163318459 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1596482297290732782} + - component: {fileID: 492048457633891032} + - component: {fileID: 3585638817739766931} + m_Layer: 5 + m_Name: Distance Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1596482297290732782 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2168646030163318459} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 4925962893293172708} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0} + m_AnchorMax: {x: 0.5, y: 0} + m_AnchoredPosition: {x: 0, y: -50} + m_SizeDelta: {x: 200, y: 50} + m_Pivot: {x: 0.5, y: 0} +--- !u!222 &492048457633891032 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2168646030163318459} + m_CullTransparentMesh: 1 +--- !u!114 &3585638817739766931 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2168646030163318459} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: Unity.TextMeshPro::TMPro.TextMeshProUGUI + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: New Text + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 4aca0db6ec111b5418bdc747168f9474, type: 2} + m_sharedMaterial: {fileID: -1441574381962284772, guid: 4aca0db6ec111b5418bdc747168f9474, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 75 + m_fontSizeBase: 75 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 1 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 512 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_characterHorizontalScale: 1 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_TextWrappingMode: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 0 + m_ActiveFontFeatures: 6e72656b + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_EmojiFallbackSupport: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!1 &3681137558538519531 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8947314070958479690} + - component: {fileID: 2195622622585202139} + - component: {fileID: 6159723260156442503} + m_Layer: 5 + m_Name: Pin + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &8947314070958479690 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3681137558538519531} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 2.4999998, y: 2.4999998, z: 2.4999998} + m_ConstrainProportionsScale: 1 + m_Children: [] + m_Father: {fileID: 1958129250542972046} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &2195622622585202139 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3681137558538519531} + m_CullTransparentMesh: 1 +--- !u!114 &6159723260156442503 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3681137558538519531} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: -3432867975278251356, guid: 8644828a229b5e34fb635653ae864d8e, type: 3} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!1 &4155011984757282289 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4925962893293172708} + - component: {fileID: 8838619832563665425} + - component: {fileID: 43833759675514098} + m_Layer: 5 + m_Name: Icon + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4925962893293172708 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4155011984757282289} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1596482297290732782} + m_Father: {fileID: 1958129250542972046} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 1, y: 1} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!222 &8838619832563665425 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4155011984757282289} + m_CullTransparentMesh: 1 +--- !u!114 &43833759675514098 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4155011984757282289} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: -4695408507704126972, guid: 31cfa2eea2b70af4b97a7a588fad0758, type: 3} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!1 &7127236600888353108 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1958129250542972046} + - component: {fileID: 7536436777668941654} + m_Layer: 5 + m_Name: PinObject + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1958129250542972046 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7127236600888353108} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 8947314070958479690} + - {fileID: 4925962893293172708} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 150, y: 150} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &7536436777668941654 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7127236600888353108} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 548d13ffdad349b6939e2b873a39b54e, type: 3} + m_Name: + m_EditorClassIdentifier: AppleHillsScripts::UI.Tracking.OffScreenPin + iconImage: {fileID: 43833759675514098} + frameImage: {fileID: 6159723260156442503} + distanceText: {fileID: 3585638817739766931} diff --git a/Assets/Prefabs/UI/PinObject.prefab.meta b/Assets/Prefabs/UI/PinObject.prefab.meta new file mode 100644 index 00000000..d3378c0d --- /dev/null +++ b/Assets/Prefabs/UI/PinObject.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d1b3fa267ed6c3041957552e81a91c73 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/UI/PinTrackingManager.prefab b/Assets/Prefabs/UI/PinTrackingManager.prefab new file mode 100644 index 00000000..af7c7f28 --- /dev/null +++ b/Assets/Prefabs/UI/PinTrackingManager.prefab @@ -0,0 +1,51 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &4983412436654784526 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6155272180318036701} + - component: {fileID: 1982229890245376539} + m_Layer: 0 + m_Name: PinTrackingManager + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &6155272180318036701 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4983412436654784526} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 23.15202, y: 16.06491, 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 &1982229890245376539 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4983412436654784526} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 8599140fd23e492fa7f14cb7633209fe, type: 3} + m_Name: + m_EditorClassIdentifier: AppleHillsScripts::UI.Tracking.OffScreenTrackerManager + pinPrefab: {fileID: 7536436777668941654, guid: d1b3fa267ed6c3041957552e81a91c73, type: 3} + screenPadding: 150 + spawnDebounceDelay: 0.3 + despawnDebounceDelay: 0.2 + updateInterval: 0.1 diff --git a/Assets/Prefabs/UI/PinTrackingManager.prefab.meta b/Assets/Prefabs/UI/PinTrackingManager.prefab.meta new file mode 100644 index 00000000..72cb3755 --- /dev/null +++ b/Assets/Prefabs/UI/PinTrackingManager.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: fcb8163ded24853438b30c37ddf2edeb +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/UI/Tracking.meta b/Assets/Prefabs/UI/Tracking.meta new file mode 100644 index 00000000..c8265251 --- /dev/null +++ b/Assets/Prefabs/UI/Tracking.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 00c5e51bbfd27b54ea95aa706a48cdc0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Examples.meta b/Assets/Scripts/Examples.meta deleted file mode 100644 index b41c61b7..00000000 --- a/Assets/Scripts/Examples.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: d5112d15beb144088e8b8752879deda3 -timeCreated: 1760105142 \ No newline at end of file diff --git a/Assets/Scripts/Examples/QuickAccessExample.cs b/Assets/Scripts/Examples/QuickAccessExample.cs deleted file mode 100644 index 6c113601..00000000 --- a/Assets/Scripts/Examples/QuickAccessExample.cs +++ /dev/null @@ -1,86 +0,0 @@ -using UnityEngine; -using AppleHills.Core; -using Core; - -namespace AppleHills.Examples -{ - /// - /// Example script demonstrating how to use QuickAccess to quickly retrieve and use game objects - /// - public class QuickAccessExample : MonoBehaviour - { - void Start() - { - // Retrieve player and follower objects using QuickAccess - GameObject player = QuickAccess.Instance.PlayerGameObject; - GameObject follower = QuickAccess.Instance.FollowerGameObject; - - // Print info about the player - if (player != null) - { - Logging.Debug($"[QuickAccessExample] Player found: {player.name}"); - Logging.Debug($"[QuickAccessExample] Player position: {player.transform.position}"); - - // Access player controller - var playerController = QuickAccess.Instance.PlayerController; - if (playerController != null) - { - Logging.Debug($"[QuickAccessExample] Player controller found on object"); - } - else - { - Logging.Warning($"[QuickAccessExample] Player controller not found"); - } - } - else - { - Logging.Warning($"[QuickAccessExample] Player not found in scene"); - } - - // Print info about the follower (Pulver) - if (follower != null) - { - Logging.Debug($"[QuickAccessExample] Follower found: {follower.name}"); - Logging.Debug($"[QuickAccessExample] Follower position: {follower.transform.position}"); - - // Access follower controller - var followerController = QuickAccess.Instance.FollowerController; - if (followerController != null) - { - Logging.Debug($"[QuickAccessExample] Follower controller found on object"); - } - else - { - Logging.Warning($"[QuickAccessExample] Follower controller not found"); - } - } - else - { - Logging.Warning($"[QuickAccessExample] Follower not found in scene"); - } - - // Access camera - var camera = QuickAccess.Instance.MainCamera; - if (camera != null) - { - Logging.Debug($"[QuickAccessExample] Main camera found: {camera.name}"); - Logging.Debug($"[QuickAccessExample] Camera position: {camera.transform.position}"); - } - else - { - Logging.Warning($"[QuickAccessExample] Main camera not found"); - } - - // Access managers - try - { - Logging.Debug($"[QuickAccessExample] Game Manager instance accessed: {QuickAccess.Instance.GameManager != null}"); - Logging.Debug($"[QuickAccessExample] Input Manager instance accessed: {QuickAccess.Instance.InputManager != null}"); - } - catch (System.Exception e) - { - Debug.LogError($"[QuickAccessExample] Error accessing managers: {e.Message}"); - } - } - } -} diff --git a/Assets/Scripts/Examples/QuickAccessExample.cs.meta b/Assets/Scripts/Examples/QuickAccessExample.cs.meta deleted file mode 100644 index 1e28d7e1..00000000 --- a/Assets/Scripts/Examples/QuickAccessExample.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: c6086c2645c14cad92be0a9c7c191fdc -timeCreated: 1760105142 \ No newline at end of file diff --git a/Assets/Scripts/UI/Tracking.meta b/Assets/Scripts/UI/Tracking.meta new file mode 100644 index 00000000..8dfd229d --- /dev/null +++ b/Assets/Scripts/UI/Tracking.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2ea2c8cb26e7d7a44b21c052322ab6ba +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/UI/Tracking/OffScreenPin.cs b/Assets/Scripts/UI/Tracking/OffScreenPin.cs new file mode 100644 index 00000000..709331d7 --- /dev/null +++ b/Assets/Scripts/UI/Tracking/OffScreenPin.cs @@ -0,0 +1,237 @@ +using UnityEngine; +using UnityEngine.UI; +using AppleHills.Core; + +namespace UI.Tracking +{ + /// + /// UI pin that displays on screen edges pointing to off-screen targets. + /// Consists of a static icon in the center and a rotatable frame that points toward the target. + /// Optionally displays distance to target if enabled. + /// Updates every frame for smooth tracking. + /// + public class OffScreenPin : MonoBehaviour + { + [Header("References")] + [Tooltip("The image component that displays the target's icon (static, in center)")] + [SerializeField] private Image iconImage; + + [Tooltip("The image component that rotates to point toward the target (default: pointing downward)")] + [SerializeField] private Image frameImage; + + [Tooltip("Optional: Text component to display distance to target")] + [SerializeField] private TMPro.TextMeshProUGUI distanceText; + + private RectTransform _rectTransform; + private TrackableTarget _target; + private bool _isInitialized; + private float _screenPadding; + private bool _trackDistance; + + private void Awake() + { + _rectTransform = GetComponent(); + } + + private void Update() + { + // Update position and rotation every frame for smooth tracking + if (_isInitialized && _target != null) + { + Camera mainCamera = QuickAccess.Instance?.MainCamera; + if (mainCamera != null) + { + UpdatePositionAndRotation(mainCamera, _screenPadding); + } + + // Update distance display if enabled + if (_trackDistance && distanceText != null) + { + UpdateDistanceDisplay(); + } + } + } + + /// + /// Initialize the pin with a target reference and set the icon + /// + public void Initialize(TrackableTarget target, float screenPadding) + { + _target = target; + _isInitialized = true; + _screenPadding = screenPadding; + _trackDistance = target.TrackDistance; + + // Set the icon sprite if available + if (iconImage != null && target.Icon != null) + { + iconImage.sprite = target.Icon; + iconImage.enabled = true; + } + else if (iconImage != null) + { + iconImage.enabled = false; + } + + // Configure distance text + if (distanceText != null) + { + distanceText.gameObject.SetActive(_trackDistance); + } + } + + /// + /// Update the pin's position and rotation based on the target's world position. + /// Called by the manager each update cycle. + /// + public void UpdatePositionAndRotation(Camera cam, float screenPadding) + { + if (!_isInitialized || _target == null) + return; + + // Get target position in screen space + Vector3 targetScreenPos = cam.WorldToScreenPoint(_target.WorldPosition); + + // Calculate direction from screen center to target + Vector2 screenCenter = new Vector2(Screen.width / 2f, Screen.height / 2f); + Vector2 targetScreenPos2D = new Vector2(targetScreenPos.x, targetScreenPos.y); + Vector2 directionToTarget = (targetScreenPos2D - screenCenter).normalized; + + // Calculate screen bounds with padding (inset from edges) + float minX = screenPadding; + float maxX = Screen.width - screenPadding; + float minY = screenPadding; + float maxY = Screen.height - screenPadding; + + // Find intersection point with screen bounds + Vector2 intersectionPoint = CalculateScreenEdgeIntersection( + screenCenter, + directionToTarget, + minX, maxX, minY, maxY + ); + + // Offset the intersection point slightly toward the center to ensure pin is fully visible + Vector2 offsetTowardCenter = -directionToTarget * screenPadding * 0.5f; + Vector2 finalPosition = intersectionPoint + offsetTowardCenter; + + // Update pin position + _rectTransform.position = finalPosition; + + // Update frame rotation to point toward target + // Frame's default orientation points downward (0 degrees in UI space) + // In UI space: 0° = down, 90° = right, 180° = up, 270° = left + // Atan2(y, x) gives angle from right (+X axis), so we need to adjust + float angle = Mathf.Atan2(directionToTarget.y, directionToTarget.x) * Mathf.Rad2Deg; + // Add 90 to convert from "right is 0°" to align with down-pointing sprite + angle = angle + 90f; + + if (frameImage != null) + { + frameImage.rectTransform.localRotation = Quaternion.Euler(0, 0, angle); + } + } + + /// + /// Update the distance display text + /// + private void UpdateDistanceDisplay() + { + // Get distance source (typically the player) + if (TrackingDistanceSource.Instance == null) + { + distanceText.text = "???"; + return; + } + + // Calculate distance between source and target + float distance = Vector3.Distance(TrackingDistanceSource.Instance.WorldPosition, _target.WorldPosition); + + // Format distance nicely (meters with 1 decimal place) + distanceText.text = $"{distance:F1}m"; + } + + /// + /// Calculate the intersection point of a ray from center in given direction with screen bounds + /// + private Vector2 CalculateScreenEdgeIntersection( + Vector2 center, + Vector2 direction, + float minX, float maxX, float minY, float maxY) + { + // Calculate intersection with each edge and find the closest one + float tMin = float.MaxValue; + Vector2 intersection = center; + + // Check intersection with right edge (x = maxX) + if (direction.x > 0.001f) + { + float t = (maxX - center.x) / direction.x; + float y = center.y + t * direction.y; + if (y >= minY && y <= maxY && t < tMin) + { + tMin = t; + intersection = new Vector2(maxX, y); + } + } + + // Check intersection with left edge (x = minX) + if (direction.x < -0.001f) + { + float t = (minX - center.x) / direction.x; + float y = center.y + t * direction.y; + if (y >= minY && y <= maxY && t < tMin) + { + tMin = t; + intersection = new Vector2(minX, y); + } + } + + // Check intersection with top edge (y = maxY) + if (direction.y > 0.001f) + { + float t = (maxY - center.y) / direction.y; + float x = center.x + t * direction.x; + if (x >= minX && x <= maxX && t < tMin) + { + tMin = t; + intersection = new Vector2(x, maxY); + } + } + + // Check intersection with bottom edge (y = minY) + if (direction.y < -0.001f) + { + float t = (minY - center.y) / direction.y; + float x = center.x + t * direction.x; + if (x >= minX && x <= maxX && t < tMin) + { + tMin = t; + intersection = new Vector2(x, minY); + } + } + + return intersection; + } + + /// + /// Reset the pin for pooling reuse + /// + public void ResetPin() + { + _target = null; + _isInitialized = false; + + if (iconImage != null) + { + iconImage.sprite = null; + iconImage.enabled = false; + } + } + + /// + /// Get the current target (for null checking) + /// + public TrackableTarget Target => _target; + } +} + diff --git a/Assets/Scripts/UI/Tracking/OffScreenPin.cs.meta b/Assets/Scripts/UI/Tracking/OffScreenPin.cs.meta new file mode 100644 index 00000000..49605a8f --- /dev/null +++ b/Assets/Scripts/UI/Tracking/OffScreenPin.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 548d13ffdad349b6939e2b873a39b54e +timeCreated: 1766074498 \ No newline at end of file diff --git a/Assets/Scripts/UI/Tracking/OffScreenTrackerManager.cs b/Assets/Scripts/UI/Tracking/OffScreenTrackerManager.cs new file mode 100644 index 00000000..39d189fb --- /dev/null +++ b/Assets/Scripts/UI/Tracking/OffScreenTrackerManager.cs @@ -0,0 +1,494 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using Core; +using Core.Lifecycle; +using AppleHills.Core; + +namespace UI.Tracking +{ + /// + /// Singleton manager that tracks off-screen targets and displays directional pins. + /// Uses ManagedBehaviour pattern and lazily accesses camera via QuickAccess (like AudioManager). + /// + public class OffScreenTrackerManager : ManagedBehaviour + { + [Header("Configuration")] + [Tooltip("Prefab for the off-screen tracking pin")] + [SerializeField] private OffScreenPin pinPrefab; + + [Tooltip("Pixel padding from screen edges (pins appear this many pixels from edge)")] + [SerializeField] private float screenPadding = 50f; + + [Tooltip("Buffer zone in pixels to prevent spawn/despawn flickering (spawn is stricter than despawn)")] + [SerializeField] private float bufferZone = 100f; + + [Tooltip("Time in seconds a target must be off-screen before pin appears")] + [SerializeField] private float spawnDebounceDelay = 0.3f; + + [Tooltip("Time in seconds a target must be on-screen before pin disappears")] + [SerializeField] private float despawnDebounceDelay = 0.2f; + + [Tooltip("Update interval in seconds for checking target visibility")] + [SerializeField] private float updateInterval = 0.1f; + + // Singleton instance + private static OffScreenTrackerManager _instance; + public static OffScreenTrackerManager Instance => _instance; + + // Tracking data + private Dictionary _trackedTargets = new Dictionary(); + + // Pin pooling + private List _inactivePins = new List(); + + // Coroutine tracking + private Coroutine _updateCoroutine; + + // Auto-created canvas for pins + private Canvas _pinCanvas; + private RectTransform _pinContainer; + + /// + /// Nested class to track per-target state and timers + /// + private class TargetTrackingData + { + public TrackableTarget Target; + public OffScreenPin ActivePin; + public float OffScreenTimer; + public float OnScreenTimer; + public bool IsCurrentlyOffScreen; + + public TargetTrackingData(TrackableTarget target) + { + Target = target; + ActivePin = null; + OffScreenTimer = 0f; + OnScreenTimer = 0f; + IsCurrentlyOffScreen = false; + } + } + + internal override void OnManagedAwake() + { + // Set singleton instance + _instance = this; + } + + internal override void OnManagedStart() + { + // Validate configuration + if (pinPrefab == null) + { + Logging.Error("[OffScreenTrackerManager] Pin prefab not assigned!"); + return; + } + + // Create dedicated canvas for pins + CreatePinCanvas(); + + // Subscribe to scene load events from SceneManagerService (like InputManager does) + // This must happen in ManagedStart because SceneManagerService instance needs to be set first + if (SceneManagerService.Instance != null) + { + SceneManagerService.Instance.SceneLoadCompleted += OnSceneLoadCompleted; + Logging.Debug("[OffScreenTrackerManager] Subscribed to SceneLoadCompleted events"); + } + + // Initialize for current scene and start coroutine + InitializeForCurrentScene(); + } + + /// + /// Called when any scene finishes loading. Refreshes camera and restarts coroutine. + /// + private void OnSceneLoadCompleted(string sceneName) + { + Logging.Debug($"[OffScreenTrackerManager] Scene loaded: {sceneName}, reinitializing camera and coroutine"); + InitializeForCurrentScene(); + } + + /// + /// Initialize camera reference and start/restart tracking coroutine for current scene + /// + private void InitializeForCurrentScene() + { + // Stop existing coroutine if running + if (_updateCoroutine != null) + { + StopCoroutine(_updateCoroutine); + _updateCoroutine = null; + Logging.Debug("[OffScreenTrackerManager] Stopped previous coroutine"); + } + + // Start the tracking coroutine (camera accessed lazily via QuickAccess) + _updateCoroutine = StartCoroutine(UpdateTrackingCoroutine()); + Logging.Debug("[OffScreenTrackerManager] Started tracking coroutine"); + } + + internal override void OnManagedDestroy() + { + // Unsubscribe from SceneManagerService events (like InputManager does) + if (SceneManagerService.Instance != null) + { + SceneManagerService.Instance.SceneLoadCompleted -= OnSceneLoadCompleted; + } + } + + private void OnDestroy() + { + // Stop coroutine + if (_updateCoroutine != null) + { + StopCoroutine(_updateCoroutine); + } + + // Clean up pooled pins + foreach (var pin in _inactivePins) + { + if (pin != null) + { + Destroy(pin.gameObject); + } + } + _inactivePins.Clear(); + + // Clean up active pins + foreach (var data in _trackedTargets.Values) + { + if (data.ActivePin != null) + { + Destroy(data.ActivePin.gameObject); + } + } + _trackedTargets.Clear(); + + // Clean up canvas + if (_pinCanvas != null) + { + Destroy(_pinCanvas.gameObject); + } + + // Clear singleton + if (_instance == this) + { + _instance = null; + } + } + + /// + /// Create a dedicated canvas for pins with sort order 50 + /// + private void CreatePinCanvas() + { + // Create a new GameObject for the canvas + GameObject canvasObj = new GameObject("OffScreenPinCanvas"); + canvasObj.transform.SetParent(transform, false); + + // Add and configure Canvas + _pinCanvas = canvasObj.AddComponent(); + _pinCanvas.renderMode = RenderMode.ScreenSpaceOverlay; + _pinCanvas.sortingOrder = 50; + + // Add CanvasScaler for consistent sizing + var scaler = canvasObj.AddComponent(); + scaler.uiScaleMode = UnityEngine.UI.CanvasScaler.ScaleMode.ScaleWithScreenSize; + scaler.referenceResolution = new Vector2(1920, 1080); + scaler.screenMatchMode = UnityEngine.UI.CanvasScaler.ScreenMatchMode.MatchWidthOrHeight; + scaler.matchWidthOrHeight = 0.5f; + + // Add GraphicRaycaster (required for UI) + canvasObj.AddComponent(); + + // Get RectTransform for pin container + _pinContainer = canvasObj.GetComponent(); + + Logging.Debug("[OffScreenTrackerManager] Created dedicated pin canvas with sort order 50"); + } + + /// + /// Register a target for tracking + /// + public void RegisterTarget(TrackableTarget target) + { + if (target == null) + return; + + if (_trackedTargets.ContainsKey(target)) + { + Logging.Warning($"[OffScreenTrackerManager] Target {target.name} is already registered"); + return; + } + + _trackedTargets.Add(target, new TargetTrackingData(target)); + Logging.Debug($"[OffScreenTrackerManager] Registered target: {target.name}"); + } + + /// + /// Unregister a target from tracking + /// + public void UnregisterTarget(TrackableTarget target) + { + if (target == null) + return; + + if (_trackedTargets.TryGetValue(target, out TargetTrackingData data)) + { + // Despawn pin if active + if (data.ActivePin != null) + { + DespawnPin(data); + } + + _trackedTargets.Remove(target); + Logging.Debug($"[OffScreenTrackerManager] Unregistered target: {target.name}"); + } + } + + /// + /// Main update coroutine that runs every updateInterval seconds + /// + private IEnumerator UpdateTrackingCoroutine() + { + Logging.Debug("[OffScreenTrackerManager] Tracking coroutine started"); + WaitForSeconds wait = new WaitForSeconds(updateInterval); + + while (true) + { + yield return wait; + + // Get camera lazily via QuickAccess (like AudioManager does) + Camera mainCamera = QuickAccess.Instance?.MainCamera; + + if (mainCamera == null) + { + // Camera not available yet (early in boot or scene transition) + continue; + } + + // Create list of targets to remove (for null cleanup) + List targetsToRemove = new List(); + + foreach (var kvp in _trackedTargets) + { + TrackableTarget target = kvp.Key; + TargetTrackingData data = kvp.Value; + + // Check if target was destroyed + if (target == null) + { + targetsToRemove.Add(target); + if (data.ActivePin != null) + { + DespawnPin(data); + } + continue; + } + + // Check if target is off-screen + bool isOffScreen = IsTargetOffScreen(target, mainCamera); + + // Update timers and state + if (isOffScreen) + { + // Target is off-screen + data.OffScreenTimer += updateInterval; + data.OnScreenTimer = 0f; + + // Check if we should spawn a pin + if (!data.IsCurrentlyOffScreen && data.OffScreenTimer >= spawnDebounceDelay) + { + data.IsCurrentlyOffScreen = true; + SpawnPin(data); + } + // Pin updates itself every frame, no need to call UpdatePositionAndRotation here + } + else + { + // Target is on-screen + data.OnScreenTimer += updateInterval; + data.OffScreenTimer = 0f; + + // Check if we should despawn the pin + if (data.IsCurrentlyOffScreen && data.OnScreenTimer >= despawnDebounceDelay) + { + data.IsCurrentlyOffScreen = false; + if (data.ActivePin != null) + { + DespawnPin(data); + } + } + } + } + + // Clean up null targets + foreach (var target in targetsToRemove) + { + _trackedTargets.Remove(target); + } + } + } + + /// + /// Check if a target is off-screen by checking its actual bounds. + /// - For SPAWNING: Entire object must be off-screen (all corners outside viewport) + /// - For DESPAWNING: Any part of object on-screen triggers despawn (any corner inside viewport) + /// Uses bufferZone to prevent flickering at boundaries. + /// + private bool IsTargetOffScreen(TrackableTarget target, Camera cam) + { + // Get the world bounds of the target + Bounds worldBounds = target.GetWorldBounds(); + + // Get the 8 corners of the bounds (we only need the min/max points in 2D) + Vector3 min = worldBounds.min; + Vector3 max = worldBounds.max; + + // Convert corners to screen space + Vector3 minScreen = cam.WorldToScreenPoint(new Vector3(min.x, min.y, worldBounds.center.z)); + Vector3 maxScreen = cam.WorldToScreenPoint(new Vector3(max.x, max.y, worldBounds.center.z)); + + // Check if behind camera + if (minScreen.z < 0 && maxScreen.z < 0) + return true; + + // Shrink detection zones to 80% of screen (10% inset on each side) + // This makes spawn/despawn more conservative + float insetPercent = 0.1f; // 10% on each side = 80% total + float horizontalInset = Screen.width * insetPercent; + float verticalInset = Screen.height * insetPercent; + + float screenLeft = horizontalInset; + float screenRight = Screen.width - horizontalInset; + float screenBottom = verticalInset; + float screenTop = Screen.height - verticalInset; + + // Check if ENTIRELY off-screen (all corners outside viewport) + // This is when we should spawn the pin + bool entirelyOffScreenLeft = maxScreen.x < screenLeft; + bool entirelyOffScreenRight = minScreen.x > screenRight; + bool entirelyOffScreenBottom = maxScreen.y < screenBottom; + bool entirelyOffScreenTop = minScreen.y > screenTop; + + bool entirelyOffScreen = entirelyOffScreenLeft || entirelyOffScreenRight || + entirelyOffScreenBottom || entirelyOffScreenTop; + + // Apply buffer zone to prevent flickering + // If already off-screen, require target to move bufferZone pixels on-screen before considering it "on-screen" + // This creates hysteresis to prevent rapid spawn/despawn cycles + if (entirelyOffScreen) + { + return true; // Definitely off-screen + } + + // Check if ANY part is on-screen (for despawn logic) + // We add bufferZone to make despawn slightly more eager + bool anyPartOnScreen = !(minScreen.x > screenRight - bufferZone || + maxScreen.x < screenLeft + bufferZone || + minScreen.y > screenTop - bufferZone || + maxScreen.y < screenBottom + bufferZone); + + // If any part is on-screen (with buffer), consider it "on-screen" (pin should despawn) + return !anyPartOnScreen; + } + + /// + /// Spawn a pin for the given target data + /// + private void SpawnPin(TargetTrackingData data) + { + // Try to get pin from pool + OffScreenPin pin = GetPinFromPool(); + + // Initialize the pin (this also caches the target and settings) + pin.Initialize(data.Target, screenPadding); + + // CRITICAL: Update position BEFORE activating to prevent flicker + // Get camera for immediate position update + Camera mainCamera = QuickAccess.Instance?.MainCamera; + if (mainCamera != null) + { + pin.UpdatePositionAndRotation(mainCamera, screenPadding); + } + + // Now activate the pin at the correct position + pin.gameObject.SetActive(true); + + + data.ActivePin = pin; + + Logging.Debug($"[OffScreenTrackerManager] Spawned pin for target: {data.Target.name}"); + } + + /// + /// Despawn a pin and return it to the pool + /// + private void DespawnPin(TargetTrackingData data) + { + if (data.ActivePin == null) + return; + + OffScreenPin pin = data.ActivePin; + data.ActivePin = null; + + // Reset and return to pool + pin.ResetPin(); + pin.gameObject.SetActive(false); + _inactivePins.Add(pin); + + Logging.Debug($"[OffScreenTrackerManager] Despawned pin for target: {data.Target?.name ?? "null"}"); + } + + /// + /// Get a pin from the pool or instantiate a new one + /// + private OffScreenPin GetPinFromPool() + { + // Try to reuse an inactive pin + if (_inactivePins.Count > 0) + { + OffScreenPin pin = _inactivePins[_inactivePins.Count - 1]; + _inactivePins.RemoveAt(_inactivePins.Count - 1); + return pin; + } + + // Create a new pin + OffScreenPin newPin = Instantiate(pinPrefab, _pinContainer); + newPin.gameObject.SetActive(false); + return newPin; + } + + #region Public Configuration Accessors + + /// + /// Get or set the screen padding in pixels + /// + public float ScreenPadding + { + get => screenPadding; + set => screenPadding = Mathf.Max(0f, value); + } + + /// + /// Get or set the spawn debounce delay + /// + public float SpawnDebounceDelay + { + get => spawnDebounceDelay; + set => spawnDebounceDelay = Mathf.Max(0f, value); + } + + /// + /// Get or set the despawn debounce delay + /// + public float DespawnDebounceDelay + { + get => despawnDebounceDelay; + set => despawnDebounceDelay = Mathf.Max(0f, value); + } + + #endregion + } +} + diff --git a/Assets/Scripts/UI/Tracking/OffScreenTrackerManager.cs.meta b/Assets/Scripts/UI/Tracking/OffScreenTrackerManager.cs.meta new file mode 100644 index 00000000..15b2c397 --- /dev/null +++ b/Assets/Scripts/UI/Tracking/OffScreenTrackerManager.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8599140fd23e492fa7f14cb7633209fe +timeCreated: 1766074538 \ No newline at end of file diff --git a/Assets/Scripts/UI/Tracking/TrackableTarget.cs b/Assets/Scripts/UI/Tracking/TrackableTarget.cs new file mode 100644 index 00000000..3d5db0bb --- /dev/null +++ b/Assets/Scripts/UI/Tracking/TrackableTarget.cs @@ -0,0 +1,84 @@ +using UnityEngine; + +namespace UI.Tracking +{ + /// + /// Component that marks a GameObject as trackable by the OffScreenTrackerManager. + /// Automatically registers/unregisters with the manager when enabled/disabled. + /// + public class TrackableTarget : MonoBehaviour + { + [Header("Configuration")] + [Tooltip("Icon to display in the off-screen tracking pin")] + [SerializeField] private Sprite icon; + + [Tooltip("Should this target display distance to the TrackingDistanceSource (e.g., player)?")] + [SerializeField] private bool trackDistance = false; + + /// + /// The icon to display in the tracking pin + /// + public Sprite Icon => icon; + + /// + /// Should this target track and display distance? + /// + public bool TrackDistance => trackDistance; + + /// + /// The world position of this target + /// + public Vector3 WorldPosition => transform.position; + + /// + /// Get the screen-space bounds of this target's visual representation. + /// Checks for Renderer or Collider2D to determine size. + /// + public Bounds GetWorldBounds() + { + // Try to get bounds from Renderer first (most accurate for visuals) + Renderer renderer = GetComponentInChildren(); + if (renderer != null) + { + return renderer.bounds; + } + + // Fallback to Collider2D + Collider2D collider = GetComponent(); + if (collider != null) + { + return collider.bounds; + } + + // Last resort: just return position with minimal bounds + return new Bounds(transform.position, Vector3.one * 0.1f); + } + + private void OnEnable() + { + // Register with the manager when enabled + if (OffScreenTrackerManager.Instance != null) + { + OffScreenTrackerManager.Instance.RegisterTarget(this); + } + } + + private void OnDisable() + { + // Unregister from the manager when disabled + if (OffScreenTrackerManager.Instance != null) + { + OffScreenTrackerManager.Instance.UnregisterTarget(this); + } + } + + /// + /// Allow runtime icon changes + /// + public void SetIcon(Sprite newIcon) + { + icon = newIcon; + } + } +} + diff --git a/Assets/Scripts/UI/Tracking/TrackableTarget.cs.meta b/Assets/Scripts/UI/Tracking/TrackableTarget.cs.meta new file mode 100644 index 00000000..2b4a59ce --- /dev/null +++ b/Assets/Scripts/UI/Tracking/TrackableTarget.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: e41f200c954677b4b8bde8cafa01d5f1 \ No newline at end of file diff --git a/Assets/Scripts/UI/Tracking/TrackingDistanceSource.cs b/Assets/Scripts/UI/Tracking/TrackingDistanceSource.cs new file mode 100644 index 00000000..0a32cf5e --- /dev/null +++ b/Assets/Scripts/UI/Tracking/TrackingDistanceSource.cs @@ -0,0 +1,43 @@ +using UnityEngine; + +namespace UI.Tracking +{ + /// + /// Marks a GameObject as the source point for distance calculations in the tracking system. + /// Typically attached to the player or camera. Only one should be active at a time. + /// + public class TrackingDistanceSource : MonoBehaviour + { + private static TrackingDistanceSource _instance; + + /// + /// The currently active distance source (typically the player) + /// + public static TrackingDistanceSource Instance => _instance; + + /// + /// The world position of this distance source + /// + public Vector3 WorldPosition => transform.position; + + private void OnEnable() + { + // Set as the active instance + if (_instance != null && _instance != this) + { + Debug.LogWarning($"[TrackingDistanceSource] Multiple distance sources detected. Overwriting previous instance ({_instance.name}) with {name}"); + } + _instance = this; + } + + private void OnDisable() + { + // Clear instance if this was the active one + if (_instance == this) + { + _instance = null; + } + } + } +} + diff --git a/Assets/Scripts/UI/Tracking/TrackingDistanceSource.cs.meta b/Assets/Scripts/UI/Tracking/TrackingDistanceSource.cs.meta new file mode 100644 index 00000000..c44ec38e --- /dev/null +++ b/Assets/Scripts/UI/Tracking/TrackingDistanceSource.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1788298f42bd40f6b077ca3719861752 +timeCreated: 1766077591 \ No newline at end of file