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;