diff --git a/Assets/Resources/PerformanceTestRunInfo.json b/Assets/Resources/PerformanceTestRunInfo.json deleted file mode 100644 index edd3a030..00000000 --- a/Assets/Resources/PerformanceTestRunInfo.json +++ /dev/null @@ -1 +0,0 @@ -{"TestSuite":"","Date":0,"Player":{"Development":false,"ScreenWidth":0,"ScreenHeight":0,"ScreenRefreshRate":0,"Fullscreen":false,"Vsync":0,"AntiAliasing":0,"Batchmode":false,"RenderThreadingMode":"MultiThreaded","GpuSkinning":false,"Platform":"","ColorSpace":"","AnisotropicFiltering":"","BlendWeights":"","GraphicsApi":"","ScriptingBackend":"IL2CPP","AndroidTargetSdkVersion":"AndroidApiLevelAuto","AndroidBuildSystem":"Gradle","BuildTarget":"Android","StereoRenderingPath":"MultiPass"},"Hardware":{"OperatingSystem":"","DeviceModel":"","DeviceName":"","ProcessorType":"","ProcessorCount":0,"GraphicsDeviceName":"","SystemMemorySizeMB":0},"Editor":{"Version":"6000.2.6f1","Branch":"6000.2/staging","Changeset":"cc51a95c0300","Date":1758053328},"Dependencies":["com.unity.2d.sprite@1.0.0","com.unity.2d.spriteshape@12.0.1","com.unity.addressables@2.7.3","com.unity.addressables.android@1.0.7","com.unity.cinemachine@3.1.4","com.unity.device-simulator.devices@1.0.0","com.unity.feature.2d@2.0.1","com.unity.film-internal-utilities@0.18.4-preview","com.unity.graphtoolkit@0.4.0-exp.2","com.unity.ide.rider@3.0.38","com.unity.ide.visualstudio@2.0.23","com.unity.inputsystem@1.14.2","com.unity.multiplayer.center@1.0.0","com.unity.render-pipelines.universal@17.2.0","com.unity.timeline@1.8.9","com.unity.ugui@2.0.0","com.unity.modules.accessibility@1.0.0","com.unity.modules.ai@1.0.0","com.unity.modules.androidjni@1.0.0","com.unity.modules.animation@1.0.0","com.unity.modules.assetbundle@1.0.0","com.unity.modules.audio@1.0.0","com.unity.modules.cloth@1.0.0","com.unity.modules.director@1.0.0","com.unity.modules.imageconversion@1.0.0","com.unity.modules.imgui@1.0.0","com.unity.modules.jsonserialize@1.0.0","com.unity.modules.particlesystem@1.0.0","com.unity.modules.physics@1.0.0","com.unity.modules.physics2d@1.0.0","com.unity.modules.screencapture@1.0.0","com.unity.modules.terrain@1.0.0","com.unity.modules.terrainphysics@1.0.0","com.unity.modules.tilemap@1.0.0","com.unity.modules.ui@1.0.0","com.unity.modules.uielements@1.0.0","com.unity.modules.umbra@1.0.0","com.unity.modules.unityanalytics@1.0.0","com.unity.modules.unitywebrequest@1.0.0","com.unity.modules.unitywebrequestassetbundle@1.0.0","com.unity.modules.unitywebrequestaudio@1.0.0","com.unity.modules.unitywebrequesttexture@1.0.0","com.unity.modules.unitywebrequestwww@1.0.0","com.unity.modules.vehicles@1.0.0","com.unity.modules.video@1.0.0","com.unity.modules.vr@1.0.0","com.unity.modules.wind@1.0.0","com.unity.modules.xr@1.0.0","com.unity.modules.subsystems@1.0.0","com.unity.modules.hierarchycore@1.0.0","com.unity.render-pipelines.core@17.2.0","com.unity.shadergraph@17.2.0","com.unity.render-pipelines.universal-config@17.0.3","com.unity.test-framework@1.6.0","com.unity.ext.nunit@2.0.5","com.unity.2d.animation@12.0.2","com.unity.2d.pixel-perfect@5.1.0","com.unity.2d.psdimporter@11.0.1","com.unity.2d.tilemap@1.0.0","com.unity.2d.tilemap.extras@5.0.1","com.unity.2d.aseprite@2.0.1","com.unity.splines@2.8.2","com.unity.profiling.core@1.0.2","com.unity.scriptablebuildpipeline@2.4.2","com.unity.2d.common@11.0.1","com.unity.mathematics@1.3.2","com.unity.searcher@4.9.3","com.unity.burst@1.8.24","com.unity.collections@2.5.7","com.unity.rendering.light-transport@1.0.1","com.unity.settings-manager@2.1.0","com.unity.nuget.mono-cecil@1.11.5","com.unity.test-framework.performance@3.1.0"],"Results":[]} \ No newline at end of file diff --git a/Assets/Resources/PerformanceTestRunInfo.json.meta b/Assets/Resources/PerformanceTestRunInfo.json.meta deleted file mode 100644 index 49de522c..00000000 --- a/Assets/Resources/PerformanceTestRunInfo.json.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: cb4b04b706692c14ab819cb590863198 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Resources/PerformanceTestRunSettings.json b/Assets/Resources/PerformanceTestRunSettings.json deleted file mode 100644 index 49438ae1..00000000 --- a/Assets/Resources/PerformanceTestRunSettings.json +++ /dev/null @@ -1 +0,0 @@ -{"MeasurementCount":-1} \ No newline at end of file diff --git a/Assets/Resources/PerformanceTestRunSettings.json.meta b/Assets/Resources/PerformanceTestRunSettings.json.meta deleted file mode 100644 index 0509e6a2..00000000 --- a/Assets/Resources/PerformanceTestRunSettings.json.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 4fcd6892d10380341866ac1c8a8c0ed9 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Scenes/MiniGames/DivingForPictures.unity b/Assets/Scenes/MiniGames/DivingForPictures.unity index 779bd1ff..56a723e3 100644 --- a/Assets/Scenes/MiniGames/DivingForPictures.unity +++ b/Assets/Scenes/MiniGames/DivingForPictures.unity @@ -342,17 +342,17 @@ LineRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_Positions: - - {x: -0.15602553, y: 7.6274276, z: 0} - - {x: -0.33293986, y: 6.2028694, z: 0} - - {x: -0.47067532, y: 4.9898887, z: 0} - - {x: -0.569232, y: 3.988484, z: 0} - - {x: -0.6286098, y: 3.1986566, z: 0} - - {x: -0.6488087, y: 2.6204057, z: 0} - - {x: -0.62982893, y: 2.2537322, z: 0} - - {x: -0.57167023, y: 2.0986352, z: 0} - - {x: -0.47433275, y: 2.1551156, z: 0} - - {x: -0.33781648, y: 2.4231722, z: 0} - - {x: -0.16212131, y: 2.9028063, z: 0} + - {x: -0.15602553, y: 4.0749445, z: 0} + - {x: -0.1566351, y: 3.9736378, z: 0} + - {x: -0.1572447, y: 3.8729858, z: 0} + - {x: -0.15785426, y: 3.7729874, z: 0} + - {x: -0.15846384, y: 3.6736438, z: 0} + - {x: -0.15907341, y: 3.5749543, z: 0} + - {x: -0.15968299, y: 3.4769194, z: 0} + - {x: -0.16029257, y: 3.3795385, z: 0} + - {x: -0.16090216, y: 3.2828126, z: 0} + - {x: -0.16151173, y: 3.1867406, z: 0} + - {x: -0.16212131, y: 3.0913231, z: 0} m_Parameters: serializedVersion: 3 widthMultiplier: 1 @@ -915,7 +915,7 @@ Transform: m_GameObject: {fileID: 747976396} serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 6.75, z: 0} + m_LocalPosition: {x: 0, y: 3.1975174, z: 0} m_LocalScale: {x: 0.57574, y: 0.57574, z: 0.57574} m_ConstrainProportionsScale: 0 m_Children: @@ -935,6 +935,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: d39dbaae819c4a128a11ca60fbbc98c9, type: 3} m_Name: m_EditorClassIdentifier: + edgeAnchor: {fileID: 747976407} --- !u!114 &747976399 MonoBehaviour: m_ObjectHideFlags: 0 @@ -1119,14 +1120,18 @@ MonoBehaviour: m_Name: m_EditorClassIdentifier: AppleHillsScripts::AppleHillsCamera.EdgeAnchor referenceMarker: {fileID: 1651034645} + cameraAdapter: {fileID: 224729335} anchorEdge: 0 useReferenceMargin: 0 - customMargin: 0 + customMargin: 2 adjustOnStart: 1 - adjustOnScreenResize: 1 + adjustOnScreenResize: 0 preserveOtherAxes: 1 + accountForObjectSize: 1 showVisualization: 1 - visualizationColor: {r: 1, g: 0, b: 0, a: 0.8} + visualizationColor: {r: 1, g: 0, b: 1, a: 1} + showObjectBounds: 1 + debugMode: 0 --- !u!1 &824396214 GameObject: m_ObjectHideFlags: 0 @@ -1362,17 +1367,17 @@ LineRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_Positions: - - {x: -0.15602553, y: 7.6274276, z: 0} - - {x: -0.29288492, y: 6.2025185, z: 0} - - {x: -0.39057457, y: 4.9891615, z: 0} - - {x: -0.44909453, y: 3.9873564, z: 0} - - {x: -0.4684448, y: 3.197105, z: 0} - - {x: -0.44862524, y: 2.6184058, z: 0} - - {x: -0.389636, y: 2.2512593, z: 0} - - {x: -0.2914771, y: 2.0956657, z: 0} - - {x: -0.15414846, y: 2.1516247, z: 0} - - {x: 0.022349834, y: 2.419136, z: 0} - - {x: 0.23801796, y: 2.8982003, z: 0} + - {x: -0.15602553, y: 4.074945, z: 0} + - {x: -0.11662118, y: 3.8796225, z: 0} + - {x: -0.07721684, y: 3.7057445, z: 0} + - {x: -0.03781248, y: 3.5533106, z: 0} + - {x: 0.0015918687, y: 3.4223216, z: 0} + - {x: 0.040996216, y: 3.3127766, z: 0} + - {x: 0.08040057, y: 3.2246757, z: 0} + - {x: 0.11980491, y: 3.1580195, z: 0} + - {x: 0.15920927, y: 3.1128078, z: 0} + - {x: 0.1986136, y: 3.0890403, z: 0} + - {x: 0.23801796, y: 3.0867171, z: 0} m_Parameters: serializedVersion: 3 widthMultiplier: 1 @@ -1905,17 +1910,17 @@ LineRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_Positions: - - {x: -0.15602553, y: 7.6274276, z: 0} - - {x: -0.36587217, y: 6.20166, z: 0} - - {x: -0.53654, y: 4.98747, z: 0} - - {x: -0.66802895, y: 3.984856, z: 0} - - {x: -0.76033914, y: 3.1938195, z: 0} - - {x: -0.81347036, y: 2.6143596, z: 0} - - {x: -0.82742286, y: 2.2464767, z: 0} - - {x: -0.80219656, y: 2.090171, z: 0} - - {x: -0.7377914, y: 2.1454425, z: 0} - - {x: -0.6342074, y: 2.4122903, z: 0} - - {x: -0.4914446, y: 2.8907156, z: 0} + - {x: -0.15602553, y: 4.074945, z: 0} + - {x: -0.18956745, y: 3.8764977, z: 0} + - {x: -0.22310936, y: 3.7000232, z: 0} + - {x: -0.25665125, y: 3.5455205, z: 0} + - {x: -0.29019317, y: 3.4129908, z: 0} + - {x: -0.32373506, y: 3.3024333, z: 0} + - {x: -0.35727698, y: 3.213848, z: 0} + - {x: -0.39081886, y: 3.1472356, z: 0} + - {x: -0.4243608, y: 3.1025953, z: 0} + - {x: -0.45790267, y: 3.0799277, z: 0} + - {x: -0.4914446, y: 3.0792325, z: 0} m_Parameters: serializedVersion: 3 widthMultiplier: 1 @@ -2445,7 +2450,7 @@ Transform: m_GameObject: {fileID: 2106431001} serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: -0.165, y: 2.509, z: 0} + m_LocalPosition: {x: -0.165, y: 2.697517, z: 0} m_LocalScale: {x: 0.57574, y: 0.57574, z: 0.57574} m_ConstrainProportionsScale: 0 m_Children: @@ -2474,7 +2479,7 @@ MonoBehaviour: bottleWobble: {fileID: 747976399} followStiffness: 4 useWobbleOffset: 1 - baseY: 2.5 + verticalDistance: 0.5 --- !u!114 &2106431004 MonoBehaviour: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/AppleHillsCamera/CameraScreenAdapter.cs b/Assets/Scripts/AppleHillsCamera/CameraScreenAdapter.cs index 88ec7b96..c986cfb1 100644 --- a/Assets/Scripts/AppleHillsCamera/CameraScreenAdapter.cs +++ b/Assets/Scripts/AppleHillsCamera/CameraScreenAdapter.cs @@ -1,5 +1,6 @@ using UnityEngine; using Unity.Cinemachine; +using System; namespace AppleHillsCamera { @@ -17,6 +18,9 @@ namespace AppleHillsCamera [Tooltip("Whether to adjust the camera automatically when the screen size changes")] public bool adjustOnScreenResize = true; + + // Event that other components can subscribe to when camera is adjusted + public event Action OnCameraAdjusted; private Camera _regularCamera; private CinemachineCamera _virtualCamera; @@ -104,8 +108,20 @@ namespace AppleHillsCamera else { Debug.LogWarning("CameraScreenAdapter: Regular camera is not in orthographic mode."); + return; } } + + // Notify subscribers that the camera has been adjusted + OnCameraAdjusted?.Invoke(); + } + + /// + /// Gets the camera component being controlled by this adapter + /// + public Camera GetControlledCamera() + { + return _usingCinemachine ? _virtualCamera.GetComponent() : _regularCamera; } } } diff --git a/Assets/Scripts/AppleHillsCamera/EdgeAnchor.cs b/Assets/Scripts/AppleHillsCamera/EdgeAnchor.cs index 57e9127a..74f18dab 100644 --- a/Assets/Scripts/AppleHillsCamera/EdgeAnchor.cs +++ b/Assets/Scripts/AppleHillsCamera/EdgeAnchor.cs @@ -1,4 +1,6 @@ -using UnityEngine; +using AppleHills.Core; +using UnityEngine; +using System; namespace AppleHillsCamera { @@ -8,6 +10,9 @@ namespace AppleHillsCamera [ExecuteInEditMode] // Make it run in the editor public class EdgeAnchor : MonoBehaviour { + // Event that fires when the anchor's position is updated + public event Action OnPositionUpdated; + public enum AnchorEdge { Top, @@ -19,6 +24,9 @@ namespace AppleHillsCamera [Tooltip("Reference marker that defines the screen edges and margins")] public ScreenReferenceMarker referenceMarker; + [Tooltip("Camera adapter to subscribe to for runtime updates")] + public CameraScreenAdapter cameraAdapter; + [Tooltip("Which screen edge to anchor to")] public AnchorEdge anchorEdge = AnchorEdge.Top; @@ -37,18 +45,29 @@ namespace AppleHillsCamera [Tooltip("Whether to preserve the object's position on other axes")] public bool preserveOtherAxes = true; + [Tooltip("Whether to account for this object's size in positioning")] + public bool accountForObjectSize = true; + [Header("Visualization")] [Tooltip("Whether to show the anchor visualization in the editor")] public bool showVisualization = true; [Tooltip("Color for the anchor visualization line")] public Color visualizationColor = new Color(1f, 0f, 0f, 0.8f); + + [Tooltip("Show object bounds in visualization")] + public bool showObjectBounds = true; + + [Tooltip("Debug mode - print position changes to console")] + public bool debugMode = false; private Camera _camera; private int _lastScreenWidth; private int _lastScreenHeight; + private float _lastOrthoSize = 0f; private Vector3 _originalPosition; private bool _initialized = false; + private Bounds _objectBounds; #if UNITY_EDITOR private void OnDrawGizmos() @@ -56,19 +75,39 @@ namespace AppleHillsCamera if (!showVisualization || referenceMarker == null) return; - // Draw a line from the object to its anchor point - Vector3 anchorPoint = GetAnchorPoint(); + // Find camera if needed + if (_camera == null) + FindCamera(); + + if (_camera == null) + return; + + // Calculate the anchor point (the exact point on the screen edge) + Vector3 anchorPoint = CalculateScreenEdgePoint(); // Save original color Color originalColor = Gizmos.color; // Draw line to anchor point Gizmos.color = visualizationColor; - Gizmos.DrawLine(gameObject.transform.position, anchorPoint); + Gizmos.DrawLine(transform.position, anchorPoint); // Draw a small sphere at the anchor point Gizmos.DrawSphere(anchorPoint, 0.1f); + // Draw object bounds if enabled + if (showObjectBounds && accountForObjectSize) + { + Bounds bounds = GetObjectBounds(); + if (bounds.size != Vector3.zero) + { + Color boundsColor = visualizationColor; + boundsColor.a *= 0.3f; + Gizmos.color = boundsColor; + Gizmos.DrawWireCube(bounds.center, bounds.size); + } + } + // Restore original color Gizmos.color = originalColor; } @@ -78,6 +117,10 @@ namespace AppleHillsCamera { _originalPosition = transform.position; FindCamera(); + if (_camera != null) + { + _lastOrthoSize = _camera.orthographicSize; + } _lastScreenWidth = Screen.width; _lastScreenHeight = Screen.height; _initialized = true; @@ -94,6 +137,12 @@ namespace AppleHillsCamera _initialized = true; } + // Subscribe to camera adapter events + if (Application.isPlaying && cameraAdapter != null) + { + cameraAdapter.OnCameraAdjusted += HandleCameraAdjusted; + } + // Adjust position immediately when enabled in editor #if UNITY_EDITOR if (!Application.isPlaying) @@ -103,18 +152,97 @@ namespace AppleHillsCamera #endif } + private void OnDisable() + { + // Unsubscribe from camera adapter events + if (cameraAdapter != null) + { + cameraAdapter.OnCameraAdjusted -= HandleCameraAdjusted; + } + } + + private void HandleCameraAdjusted() + { + // Update position when camera is adjusted + if (Application.isPlaying) + { + if (debugMode) + { + Debug.Log($"Camera adjusted event received by {gameObject.name}, updating position"); + } + + // Ensure we have the latest camera reference + FindCamera(); + UpdatePosition(); + } + } + private void Start() { + // If no camera adapter was manually set, try to find one in the scene + if (cameraAdapter == null && Application.isPlaying) + { + FindCameraAdapter(); + } + + // Ensure we're subscribed to camera adapter events + if (cameraAdapter != null && Application.isPlaying) + { + cameraAdapter.OnCameraAdjusted -= HandleCameraAdjusted; // Remove any duplicate subscriptions + cameraAdapter.OnCameraAdjusted += HandleCameraAdjusted; // Subscribe + } + if (adjustOnStart && Application.isPlaying) { UpdatePosition(); } } + private void FindCameraAdapter() + { + // Try to find the camera adapter in the scene + var adapters = FindObjectsOfType(); + if (adapters != null && adapters.Length > 0) + { + // Prioritize any adapter that's on the same camera we're using + foreach (var adapter in adapters) + { + if (_camera != null && adapter.GetControlledCamera() == _camera) + { + cameraAdapter = adapter; + Debug.Log($"EdgeAnchor on {gameObject.name} auto-connected to CameraScreenAdapter on {cameraAdapter.gameObject.name}"); + return; + } + } + + // If no matching camera found, use the first one + cameraAdapter = adapters[0]; + Debug.Log($"EdgeAnchor on {gameObject.name} auto-connected to CameraScreenAdapter on {cameraAdapter.gameObject.name}"); + } + } + private void Update() { bool shouldUpdate = false; + // Check if we have a valid camera + if (_camera == null) + { + FindCamera(); + if (_camera != null) shouldUpdate = true; + } + + // Check if camera's ortho size has changed + if (_camera != null && _camera.orthographicSize != _lastOrthoSize) + { + if (debugMode) + { + Debug.Log($"{gameObject.name}: Camera ortho size changed from {_lastOrthoSize} to {_camera.orthographicSize}"); + } + _lastOrthoSize = _camera.orthographicSize; + shouldUpdate = true; + } + // Update if screen size has changed if (adjustOnScreenResize && (Screen.width != _lastScreenWidth || Screen.height != _lastScreenHeight)) @@ -141,6 +269,18 @@ namespace AppleHillsCamera private void FindCamera() { + Camera prevCamera = _camera; + + // First check if we have a camera adapter reference + if (cameraAdapter != null) + { + _camera = cameraAdapter.GetControlledCamera(); + if (_camera != null) + { + return; + } + } + // Look for the main camera _camera = Camera.main; @@ -154,6 +294,43 @@ namespace AppleHillsCamera { Debug.LogError("EdgeAnchor: No camera found in the scene."); } + else if (_camera != prevCamera && debugMode) + { + Debug.Log($"{gameObject.name}: Camera reference updated to {_camera.name}"); + } + } + + /// + /// Get the combined bounds of all renderers on this object and its children + /// + private Bounds GetObjectBounds() + { + Bounds bounds = new Bounds(transform.position, Vector3.zero); + + // Get all renderers in this object and its children + Renderer[] renderers = GetComponentsInChildren(); + + if (renderers.Length > 0) + { + // Start with the first renderer's bounds + bounds = renderers[0].bounds; + + // Expand to include all other renderers + for (int i = 1; i < renderers.Length; i++) + { + bounds.Encapsulate(renderers[i].bounds); + } + } + else + { + // No renderers found, create a small placeholder bounds + bounds = new Bounds(transform.position, new Vector3(0.1f, 0.1f, 0.1f)); + } + + // Cache the bounds + _objectBounds = bounds; + + return bounds; } /// @@ -176,7 +353,7 @@ namespace AppleHillsCamera // Get the margin value to use float margin = GetMarginValue(); - // Calculate the new position based on anchor edge + // Calculate the new position based on anchor edge and object size Vector3 newPosition = CalculateAnchoredPosition(margin); // If preserving other axes, keep their original values @@ -198,7 +375,21 @@ namespace AppleHillsCamera } // Apply the new position + if (debugMode && Vector3.Distance(transform.position, newPosition) > 0.01f) + { + Debug.Log($"{gameObject.name} position updated: {transform.position} -> {newPosition}, Camera OrthoSize: {_camera.orthographicSize}"); + } + transform.position = newPosition; + + // Notify listeners that the position has been updated + OnPositionUpdated?.Invoke(); + + // Store the current ortho size for change detection + if (_camera != null) + { + _lastOrthoSize = _camera.orthographicSize; + } } private float GetMarginValue() @@ -225,36 +416,73 @@ namespace AppleHillsCamera private Vector3 CalculateAnchoredPosition(float margin) { - // Get the screen edges in world coordinates + if (_camera == null) + return transform.position; + + // Always get the CURRENT camera properties to ensure we have latest values float cameraOrthoSize = _camera.orthographicSize; float screenAspect = (float)Screen.width / Screen.height; float screenHeight = cameraOrthoSize * 2f; float screenWidth = screenHeight * screenAspect; Vector3 cameraPosition = _camera.transform.position; - Vector3 newPosition = transform.position; + // Calculate object size offset if needed + float offsetX = 0f; + float offsetY = 0f; + + if (accountForObjectSize) + { + Bounds bounds = GetObjectBounds(); + Vector3 extents = bounds.extents; // Half the size + Vector3 centerOffset = bounds.center - transform.position; // Offset from pivot to center + + switch (anchorEdge) + { + case AnchorEdge.Top: + // For top edge, offset is negative (moving down) by the top extent + offsetY = -extents.y - centerOffset.y; + break; + case AnchorEdge.Bottom: + // For bottom edge, offset is positive (moving up) by the bottom extent + offsetY = extents.y - centerOffset.y; + break; + case AnchorEdge.Left: + // For left edge, offset is positive (moving right) by the left extent + offsetX = extents.x - centerOffset.x; + break; + case AnchorEdge.Right: + // For right edge, offset is negative (moving left) by the right extent + offsetX = -extents.x - centerOffset.x; + break; + } + } + switch (anchorEdge) { case AnchorEdge.Top: // Position from the top of the screen - newPosition.y = cameraPosition.y + cameraOrthoSize - margin; + // When margin is 0, object's top edge is exactly at the top screen edge + newPosition.y = cameraPosition.y + cameraOrthoSize - margin + offsetY; break; case AnchorEdge.Bottom: // Position from the bottom of the screen - newPosition.y = cameraPosition.y - cameraOrthoSize + margin; + // When margin is 0, object's bottom edge is exactly at the bottom screen edge + newPosition.y = cameraPosition.y - cameraOrthoSize + margin + offsetY; break; case AnchorEdge.Left: // Position from the left of the screen - newPosition.x = cameraPosition.x - (screenWidth / 2f) + margin; + // When margin is 0, object's left edge is exactly at the left screen edge + newPosition.x = cameraPosition.x - (screenWidth / 2f) + margin + offsetX; break; case AnchorEdge.Right: // Position from the right of the screen - newPosition.x = cameraPosition.x + (screenWidth / 2f) - margin; + // When margin is 0, object's right edge is exactly at the right screen edge + newPosition.x = cameraPosition.x + (screenWidth / 2f) - margin + offsetX; break; } @@ -262,16 +490,13 @@ namespace AppleHillsCamera } /// - /// Gets the anchor point on the edge for visualization + /// Calculates the exact point on the screen edge for visualization purposes /// - private Vector3 GetAnchorPoint() + private Vector3 CalculateScreenEdgePoint() { if (_camera == null) - { - FindCamera(); - if (_camera == null) return transform.position; - } - + return transform.position; + // Get the screen edges in world coordinates float cameraOrthoSize = _camera.orthographicSize; float screenAspect = (float)Screen.width / Screen.height; @@ -279,32 +504,46 @@ namespace AppleHillsCamera float screenWidth = screenHeight * screenAspect; Vector3 cameraPosition = _camera.transform.position; - Vector3 anchorPoint = transform.position; + Vector3 objectPosition = transform.position; + // Calculate the point exactly on the screen edge that corresponds to the object's anchor switch (anchorEdge) { case AnchorEdge.Top: - // Anchor at top edge with same X as the object - anchorPoint.y = cameraPosition.y + cameraOrthoSize; - break; + // Point on top edge with same X coordinate as the object + return new Vector3( + objectPosition.x, + cameraPosition.y + cameraOrthoSize, + objectPosition.z + ); case AnchorEdge.Bottom: - // Anchor at bottom edge with same X as the object - anchorPoint.y = cameraPosition.y - cameraOrthoSize; - break; + // Point on bottom edge with same X coordinate as the object + return new Vector3( + objectPosition.x, + cameraPosition.y - cameraOrthoSize, + objectPosition.z + ); case AnchorEdge.Left: - // Anchor at left edge with same Y as the object - anchorPoint.x = cameraPosition.x - (screenWidth / 2f); - break; + // Point on left edge with same Y coordinate as the object + return new Vector3( + cameraPosition.x - (screenWidth / 2f), + objectPosition.y, + objectPosition.z + ); case AnchorEdge.Right: - // Anchor at right edge with same Y as the object - anchorPoint.x = cameraPosition.x + (screenWidth / 2f); - break; + // Point on right edge with same Y coordinate as the object + return new Vector3( + cameraPosition.x + (screenWidth / 2f), + objectPosition.y, + objectPosition.z + ); + + default: + return objectPosition; } - - return anchorPoint; } } } diff --git a/Assets/Scripts/Minigames/DivingForPictures/Player/PlayerController.cs b/Assets/Scripts/Minigames/DivingForPictures/Player/PlayerController.cs index f171b715..8cb2b7c7 100644 --- a/Assets/Scripts/Minigames/DivingForPictures/Player/PlayerController.cs +++ b/Assets/Scripts/Minigames/DivingForPictures/Player/PlayerController.cs @@ -1,6 +1,7 @@ using UnityEngine; using AppleHills.Core.Settings; using Input; +using AppleHillsCamera; namespace Minigames.DivingForPictures { @@ -10,6 +11,10 @@ namespace Minigames.DivingForPictures /// public class PlayerController : MonoBehaviour, ITouchInputConsumer { + + [Tooltip("Reference to the edge anchor that this player should follow for Y position")] + [SerializeField] private EdgeAnchor edgeAnchor; + // Settings reference private IDivingMinigameSettings _settings; @@ -42,6 +47,38 @@ namespace Minigames.DivingForPictures _targetFingerX = transform.position.x; _isTouchActive = false; + // Try to find edge anchor if not assigned + if (edgeAnchor == null) + { + // First try to find edge anchor on the same object or parent + edgeAnchor = GetComponentInParent(); + + // If not found, find any edge anchor in the scene + if (edgeAnchor == null) + { + edgeAnchor = FindObjectOfType(); + if (edgeAnchor == null) + { + Debug.LogWarning("[PlayerController] No EdgeAnchor found in scene. Origin Y position won't update with camera changes."); + } + else + { + Debug.Log($"[PlayerController] Auto-connected to EdgeAnchor on {edgeAnchor.gameObject.name}"); + } + } + } + + // Subscribe to edge anchor events if it exists + if (edgeAnchor != null) + { + // Unsubscribe first to prevent duplicate subscriptions + edgeAnchor.OnPositionUpdated -= UpdateOriginYFromAnchor; + edgeAnchor.OnPositionUpdated += UpdateOriginYFromAnchor; + + // Update origin Y based on current anchor position + UpdateOriginYFromAnchor(); + } + DivingGameManager.Instance.OnGameInitialized += Initialize; // If game is already initialized, initialize immediately @@ -70,6 +107,12 @@ namespace Minigames.DivingForPictures private void OnDestroy() { DivingGameManager.Instance.OnGameInitialized -= Initialize; + + // Unsubscribe from edge anchor events + if (edgeAnchor != null) + { + edgeAnchor.OnPositionUpdated -= UpdateOriginYFromAnchor; + } } /// @@ -185,5 +228,31 @@ namespace Minigames.DivingForPictures } transform.position = new Vector3(newX, newY, transform.position.z); } + + /// + /// Updates the origin Y position based on camera adjustments + /// + public void UpdateOriginY(float newOriginY) + { + _originY = newOriginY; + } + + /// + /// Updates the origin Y position based on the current position of the player + /// This method is intended to be called by the camera adapter when the camera is adjusted. + /// + private void UpdateOriginYFromCurrentPosition() + { + _originY = transform.position.y; + } + + /// + /// Updates the origin Y position based on the current position of the edge anchor + /// This method is intended to be called by the edge anchor when its position is updated. + /// + private void UpdateOriginYFromAnchor() + { + _originY = edgeAnchor.transform.position.y; + } } } \ No newline at end of file diff --git a/Assets/Scripts/Minigames/DivingForPictures/Player/RockFollower.cs b/Assets/Scripts/Minigames/DivingForPictures/Player/RockFollower.cs index b17ec7df..c8c46d8e 100644 --- a/Assets/Scripts/Minigames/DivingForPictures/Player/RockFollower.cs +++ b/Assets/Scripts/Minigames/DivingForPictures/Player/RockFollower.cs @@ -16,12 +16,43 @@ public class RockFollower : MonoBehaviour /// public bool useWobbleOffset = true; /// - /// The base Y position for the rock. + /// The vertical distance between the rock and the bottle. /// - public float baseY = -6f; + [SerializeField] private float verticalDistance = 6f; private float velocityX; // For SmoothDamp +#if UNITY_EDITOR + /// + /// Called in editor when properties are changed. + /// Updates the object's position when verticalDistance is modified. + /// + private void OnValidate() + { + // Only update position if playing or in prefab mode + if (Application.isPlaying || UnityEditor.PrefabUtility.IsPartOfPrefabAsset(this)) + return; + + if (bottleTransform != null) + { + // Calculate the new Y position based on bottle's position and the updated verticalDistance + float newY = bottleTransform.position.y - verticalDistance; + + // Apply the wobble offset if enabled + if (useWobbleOffset && bottleWobble != null) + { + newY += bottleWobble.VerticalOffset; + } + + // Update only the Y position, keeping X and Z unchanged + transform.position = new Vector3(transform.position.x, newY, transform.position.z); + + // Mark the scene as dirty to ensure changes are saved + UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(UnityEngine.SceneManagement.SceneManager.GetActiveScene()); + } + } +#endif + void Update() { if (bottleTransform == null) return; @@ -33,8 +64,8 @@ public class RockFollower : MonoBehaviour // Smoothly follow bottle's X with stiffer motion float newX = Mathf.SmoothDamp(currentX, targetX, ref velocityX, 1f / followStiffness); - // Calculate Y position - float newY = baseY; + // Calculate Y position based on bottle's position and vertical distance + float newY = bottleTransform.position.y - verticalDistance; if (useWobbleOffset && bottleWobble != null) { newY += bottleWobble.VerticalOffset;