如何基于第三人称相机与平行光设置Unity UI阴影偏移距离?
解决UI阴影effectDistance随相机与平行光动态调整的问题
核心思路
UI阴影的effectDistance是屏幕空间的2D偏移量,需要把平行光的世界空间光照方向转换为相机视角下的屏幕偏移,再结合相机旋转修正方向,最终映射为UI阴影的偏移值。
修正后的代码实现
using UnityEngine; using UnityEngine.UI; public class DynamicUIShadow : MonoBehaviour { public Shadow uiShadow; public Camera thirdPersonCamera; public Light directionalLight; public float shadowIntensity = 100f; // 控制阴影偏移强度,可按需调整 void Update() { if (uiShadow == null || thirdPersonCamera == null || directionalLight == null) return; // 获取平行光的世界空间光照方向(Unity平行光forward指向光源,光照方向为其反方向) Vector3 worldLightDir = -directionalLight.transform.forward; // 将世界空间光照方向转换为相机局部空间(相对于相机的方向) Vector3 cameraSpaceLightDir = thirdPersonCamera.transform.InverseTransformDirection(worldLightDir); // 投影到UI的2D平面:忽略Z轴深度,取X(水平)和Y(垂直)分量,反转Y匹配阴影偏移逻辑 Vector2 effectOffset = new Vector2(cameraSpaceLightDir.x, -cameraSpaceLightDir.y); // 修正相机俯仰旋转带来的垂直偏移方向 float cameraPitch = thirdPersonCamera.transform.eulerAngles.x; if (cameraPitch > 180f) { effectOffset.y *= -1; } // 缩放偏移量并赋值给阴影 uiShadow.effectDistance = effectOffset * shadowIntensity; } }
关键逻辑说明
- 空间转换:用
InverseTransformDirection把平行光方向转成相机视角下的相对方向,确保相机任意旋转时,光照对应的屏幕偏移始终正确。 - 2D投影修正:忽略Z轴后,X对应屏幕水平方向,Y对应垂直方向;反转Y是因为UI阴影的
effectDistance.y正方向向上,而阴影需要朝向光照的反方向。 - 俯仰适配:相机俯仰超过180度(向下看)时,反转垂直偏移方向,避免阴影方向错乱。
- 强度可控:
shadowIntensity替代硬编码的缩放值,方便根据UI风格调整阴影大小。
原代码问题分析
原代码直接拼接相机transform分量计算,没有完成平行光方向到相机空间的转换,导致仅平行光Y轴为0时表现正常。新代码通过空间转换逻辑,彻底适配平行光与相机的任意旋转状态。
内容的提问来源于stack exchange,提问作者MarioM
相关产品推荐
相关产品推荐

