diff --git a/packages/org.gamecult.eve.unity-scene/Runtime/EveUnityPlayableWorldCameraRig.cs b/packages/org.gamecult.eve.unity-scene/Runtime/EveUnityPlayableWorldCameraRig.cs index 9dc3ce7..2394723 100644 --- a/packages/org.gamecult.eve.unity-scene/Runtime/EveUnityPlayableWorldCameraRig.cs +++ b/packages/org.gamecult.eve.unity-scene/Runtime/EveUnityPlayableWorldCameraRig.cs @@ -45,9 +45,18 @@ namespace GameCult.Eve.UnityScene if (player == null) return false; - var target = player.transform.position; - var orbit = Quaternion.Euler(0f, yawDegrees, 0f) * (Vector3.back * Mathf.Max(0.1f, distance)); - var desiredPosition = target + orbit + (Vector3.up * Mathf.Max(0f, height)); + var cameraComponent = camera.GetComponent(); + var bounds = CalculateVisualBounds(player); + var target = bounds?.center ?? player.transform.position; + var radius = bounds?.extents.magnitude ?? 0f; + var verticalFov = cameraComponent != null ? cameraComponent.fieldOfView : 60f; + var framingDistance = radius > 0f + ? radius / Mathf.Sin(Mathf.Max(1f, verticalFov) * 0.5f * Mathf.Deg2Rad) * 1.15f + : 0f; + var resolvedDistance = Mathf.Max(0.1f, distance, framingDistance); + var resolvedHeight = Mathf.Max(0f, height, radius * 0.45f); + var orbit = Quaternion.Euler(0f, yawDegrees, 0f) * (Vector3.back * resolvedDistance); + var desiredPosition = target + orbit + (Vector3.up * resolvedHeight); var t = deltaTime <= 0f ? 1f : 1f - Mathf.Exp(-Mathf.Max(0.01f, followDamping) * deltaTime); @@ -57,6 +66,28 @@ namespace GameCult.Eve.UnityScene return true; } + private static Bounds? CalculateVisualBounds(EveUnityPlayableWorldEntityMarker player) + { + var renderers = player.GetComponentsInChildren(includeInactive: false); + Bounds? bounds = null; + foreach (var visual in renderers) + { + if (visual == null || !visual.enabled) + continue; + if (bounds.HasValue) + { + var combined = bounds.Value; + combined.Encapsulate(visual.bounds); + bounds = combined; + } + else + { + bounds = visual.bounds; + } + } + return bounds; + } + private void LateUpdate() { if (driveInLateUpdate) diff --git a/packages/org.gamecult.eve.unity-scene/Tests/Editor/EveUnitySceneSurfaceLowererTests.cs b/packages/org.gamecult.eve.unity-scene/Tests/Editor/EveUnitySceneSurfaceLowererTests.cs index ffadd0f..a044d0f 100644 --- a/packages/org.gamecult.eve.unity-scene/Tests/Editor/EveUnitySceneSurfaceLowererTests.cs +++ b/packages/org.gamecult.eve.unity-scene/Tests/Editor/EveUnitySceneSurfaceLowererTests.cs @@ -654,9 +654,15 @@ namespace GameCult.Eve.UnityScene.Tests rig.Host = host; rig.CameraTransform = cameraObject.transform; + var player = rootObject.GetComponentInChildren(); + Assert.That(player, Is.Not.Null); + var largeVisual = GameObject.CreatePrimitive(PrimitiveType.Cube); + largeVisual.transform.SetParent(player.transform, false); + largeVisual.transform.localScale = Vector3.one * 100f; + Assert.That(rig.ApplyRig(0f), Is.True); Assert.That(cameraObject.transform.position.y, Is.GreaterThan(0f)); - Assert.That(Vector3.Distance(cameraObject.transform.position, Vector3.zero), Is.GreaterThan(1f)); + Assert.That(Vector3.Distance(cameraObject.transform.position, largeVisual.transform.position), Is.GreaterThan(100f)); } finally {