You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity 3D:基于玩家垂直位置调整场景光照的高效方案问询

解决方案

方案1:使用URP后处理调整全局亮度(推荐)

这是最简洁高效的方式,完全不需要修改场景光照组件,直接通过后处理层统一控制整个画面的亮度:

  • 确保你的项目使用URP管线,并安装Post Processing包(Package Manager中搜索安装)。
  • 在场景中创建一个Global Volume对象,添加Color Adjustments后处理组件。
  • 编写脚本监听角色的Y轴高度,动态调整Color Adjustments中的Brightness参数:
using UnityEngine;
using UnityEngine.Rendering.Universal;

public class HeightBasedBrightness : MonoBehaviour
{
    public Transform player;
    public Volume globalVolume;
    public float minHeight = 0f; // 最低高度对应最亮
    public float maxHeight = 200f; // 最高高度对应最暗
    public float maxBrightness = 1f;
    public float minBrightness = -0.8f;

    private ColorAdjustments _colorAdjustments;

    void Start()
    {
        globalVolume.profile.TryGet(out _colorAdjustments);
    }

    void Update()
    {
        float heightRatio = Mathf.Clamp01((player.position.y - minHeight) / (maxHeight - minHeight));
        float targetBrightness = Mathf.Lerp(maxBrightness, minBrightness, heightRatio);
        
        _colorAdjustments.brightness.value = targetBrightness;
    }
}
  • 优势:性能开销极低,所有物体(包括角色、场景、UI)都会同步变暗,无需单独修改每个物体的材质。
  • 注意:如果用内置管线,可以替换为Image Effect中的Color Correction组件,逻辑一致。

方案2:Shader全局变量控制物体亮度

如果需要更精细的控制(比如某些物体不受亮度影响),可以通过自定义Shader实现:

  • 编写一个基础Shader(以Unlit为例),添加全局亮度控制变量:
Shader "Custom/HeightControlledUnlit"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            float _GlobalBrightness; // 全局亮度变量

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                col.rgb *= _GlobalBrightness; // 应用亮度调整
                return col;
            }
            ENDCG
        }
    }
}
  • 将场景中需要受亮度影响的物体材质替换为这个Shader,然后在脚本中更新全局变量:
using UnityEngine;

public class HeightBasedShaderBrightness : MonoBehaviour
{
    public Transform player;
    public float minHeight = 0f;
    public float maxHeight = 200f;
    public float maxBrightness = 1f;
    public float minBrightness = 0.3f;

    void Update()
    {
        float heightRatio = Mathf.Clamp01((player.position.y - minHeight) / (maxHeight - minHeight));
        float targetBrightness = Mathf.Lerp(maxBrightness, minBrightness, heightRatio);
        
        Shader.SetGlobalFloat("_GlobalBrightness", targetBrightness);
    }
}
  • 优势:可以灵活选择哪些物体受亮度影响,Shader层面计算性能优异。
  • 注意:如果使用Standard Shader,可以通过修改Shader变体或使用材质的Emission/Albedo颜色乘子实现类似效果,但自定义Shader更直接。

方案3:调整环境光强度(适合实时光照场景)

如果你需要保留场景的光照层次(比如阴影),可以直接调整全局环境光强度:

  • 编写脚本监听角色高度,动态修改环境光强度:
using UnityEngine;

public class HeightBasedAmbientLight : MonoBehaviour
{
    public Transform player;
    public float minHeight = 0f;
    public float maxHeight = 200f;
    public float maxAmbientIntensity = 1f;
    public float minAmbientIntensity = 0.2f;

    void Update()
    {
        float heightRatio = Mathf.Clamp01((player.position.y - minHeight) / (maxHeight - minHeight));
        float targetIntensity = Mathf.Lerp(maxAmbientIntensity, minAmbientIntensity, heightRatio);
        
        RenderSettings.ambientIntensity = targetIntensity;
        // 如需同步方向光强度,可添加以下代码
        // GetComponent<Light>().intensity = targetIntensity;
    }
}
  • 优势:无需额外依赖,适合简单实时光照场景。
  • 注意:如果场景中有烘焙光照,此方法无法影响烘焙部分,需配合实时光照使用。

为什么不推荐移动Sun?

移动方向光会触发Unity实时光照重新计算(包括阴影),每帧更新会带来不必要的性能开销,且你的Sun被2D背景遮挡,完全没必要通过移动光源模拟亮度变化。上述方案均为GPU层面的批量计算,性能开销可忽略不计。

内容的提问来源于stack exchange,提问作者Colin Andy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 22:06:26