From b22d2ed34290e6722367461a2c052464c8f773fd Mon Sep 17 00:00:00 2001 From: MelekTaus Moribundus Date: Tue, 30 Jun 2026 21:32:25 +0200 Subject: [PATCH] Scale the hero cutout with the player's PlayerScaler The cutout cone's radius and feather are now multiplied by the hero target's uniform world scale (lossyScale.x, the same body-scale source the orbit input uses). The authored values are the scale-1 sizes, so the see-through hole and its soft edge keep the same on-screen proportion for a small hider or a large hunter, and a mid-match conversion tracks live since lossyScale is read every frame. Co-Authored-By: Claude Opus 4.8 --- Assets/Scripts/HeroCutout.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Assets/Scripts/HeroCutout.cs b/Assets/Scripts/HeroCutout.cs index b44f649..23f9fa3 100644 --- a/Assets/Scripts/HeroCutout.cs +++ b/Assets/Scripts/HeroCutout.cs @@ -47,11 +47,15 @@ public class HeroCutout : MonoBehaviour public bool replaceDeoccluderPullIn = true; [Header("Cutout cone")] - [Tooltip("Radius of the see-through cone AT THE PLAYER, in metres. The cone tapers to nothing at the " + + [Tooltip("Radius of the see-through cone AT THE PLAYER, in metres, AT PLAYER SCALE 1. The live radius is " + + "multiplied by the hero target's uniform world scale (PlayerScaler) so the hole keeps the same " + + "on-screen size for a small hider or a large hunter. The cone also tapers to nothing at the " + "camera, so the hole keeps a constant on-screen size at every occluder depth.")] [Range(0.05f, 3f)] public float radius = 0.5f; - [Tooltip("Soft-edge width of the cone wall at the player, in metres (also tapers toward the camera).")] + [Tooltip("Soft-edge width of the cone wall at the player, in metres, AT PLAYER SCALE 1 (also tapers " + + "toward the camera). Like the radius, the live value is multiplied by the hero target's uniform " + + "world scale (PlayerScaler) so the soft edge keeps the same on-screen proportion at any size.")] [Range(0f, 1f)] public float feather = 0.15f; [Tooltip("Soft depth band (m) straddling the player: instead of stopping at a hard plane at the " + @@ -134,6 +138,11 @@ public class HeroCutout : MonoBehaviour Vector3 heroPos = target.position + Vector3.up * heightOffset; Vector3 camPos = cam.transform.position; + // Body-relative cone: the authored radius is the scale-1 size, scaled by the hero's uniform world + // size so the hole stays the same on screen for a small hider or a large hunter. lossyScale captures + // the full hierarchy (PlayerScaler drives localScale); reading it live tracks a mid-match conversion. + float bodyScale = Mathf.Max(1e-4f, target.lossyScale.x); + // Only punch the tube when something actually stands between the player and the camera; with a // clear view the occluders stay solid. A short hold after the last blocked frame avoids flicker // when the single ray grazes an occluder edge. @@ -142,7 +151,7 @@ public class HeroCutout : MonoBehaviour // Same hero point feeds the ray and the cone axis, so the gate and the cut volume agree. Shader.SetGlobalVector(TargetId, new Vector4(heroPos.x, heroPos.y, heroPos.z, 1f)); - Shader.SetGlobalVector(ParamsId, new Vector4(Mathf.Max(0f, radius), Mathf.Max(1e-4f, feather), Mathf.Max(1e-4f, depthFeather), 0f)); + Shader.SetGlobalVector(ParamsId, new Vector4(Mathf.Max(0f, radius * bodyScale), Mathf.Max(1e-4f, feather * bodyScale), Mathf.Max(1e-4f, depthFeather), 0f)); } ///