三处独立的"昼夜亮度控制"原本走不同曲线,夜景氛围调暗时角色/技能自发光还保持几百倍的白天乘数导致过曝。统一为一条共享曲线 GetDaylightFactor,三处消费方各取所需。
— V61 统一曲线的来源
一、三个独立问题 → 一个统一方案
| 问题 | 根因 | 修复手段 |
|---|---|---|
| 夜景整体太亮,没有夜晚氛围 | 场景 PPV 没做夜间压暗 | AutoExposureBias 负向偏移 |
| 角色发光纹路夜晚过曝 | 材质 Emissive 末尾乘数固定几百倍,昼夜不变 | 材质 × EffectBrightness 标量(Lerp 夜晚 0.03 / 白天 1.0) |
| 技能特效夜晚像白天一样亮 | 部分 Niagara 材质没接 MPC EmissiveScale | 52 个发光材质批量补 Multiply × CollectionParameter(EmissiveScale) |
二、V61 唯一权威曲线(三处共用)
静态函数 ATimeOfDayManager::GetDaylightFactor(float Hours) 返回 0(夜晚全暗)到 1(白天满亮)的因子。曝光/技能/角色三处消费方各取"1 − factor"或"直接用 factor"。
| 时段 | DaylightFactor | 曝光 DimFactor (=1−factor) | 技能 EmissiveScale | 角色 EffectBrightness |
|---|---|---|---|---|
| 09:00–18:15 | 1(满亮) | 0(不动) | 1.0 | 1.0 |
| 18:15–19:30 | 1→0.762 | 0→0.238 | 1→0.762 | 1→0.762 |
| 19:30–21:30 | 0.762→0 | 0.238→1 | 0.762→0 | 0.762→0 |
| 21:30–06:15 | 0(全暗) | 1(最大) | 0.000024 | 0.03 |
| 06:15–08:00 | 0→0.538 | 1→0.462 | 0.000024→0.538 | 0.03→0.538 |
| 08:00–09:00 | 0.538→1 | 0.462→0 | 0.538→1 | 0.538→1 |
曲线参数(可调杠杆)
constexpr float NightDimMaxEV = 4.0f; // 夜晚最多压暗的 EV(±1 EV ≈ 亮度 ×2 或 ÷2)
constexpr float DawnStartH = 6.25f; // 06:15 开始恢复
constexpr float DawnAccelEndH = 8.0f; // 08:00 加速段起点
constexpr float DawnRestoreEndH = 9.0f; // 09:00 完全恢复
constexpr float DuskStartH = 18.25f; // 18:15 开始压暗
constexpr float DuskAccelEndH = 19.5f; // 19:30 加速段起点
constexpr float DuskEndH = 21.5f; // 21:30 全暗
constexpr float NightEndH = 6.25f; // 06:15 结束
constexpr float NightEffBright = 0.03f; // 角色发光夜晚值(角色材质 Multiply)
constexpr float NightEmissive = 0.000024f; // 技能特效 MPC 夜晚值
三、曝光压暗实现(AutoExposureBias)
铁律:UE 的 AutoExposureBias 符号——正值 = 变亮,负值 = 变暗(每 ±1 EV 亮度约 ×2 或 ÷2)。初版 V48 注释错误写成"正=更暗",按注释写导致夜晚越加曝光越亮。
// TimeOfDayManager.cpp · ApplySunMoonIntensity() V61 块
// 缓存 PPV 的原始 EV 基值(避免每帧把上次写入值当基值导致漂移)
float CachedBaseBias = PPVCache.Get(PPV); // 首次读取 PPV->Settings.AutoExposureBias
const float DimFactor = 1.0f - GetDaylightFactor(CurrentHours);
const float Offset = NightDimMaxEV * DimFactor;
PPV->Settings.AutoExposureBias = CachedBaseBias - Offset; // 负方向 = 变暗 ✓
四、角色材质 EffectBrightness 接入
6 个发光母材质(M_Nyx_Emissive / M_Nyx_Body / M_Nyx_Clothes / M_Nyx_Fur / M_Nyx_Hair / M_Nyx_Ribbon)各在 EmissiveColor 输出前新增 Multiply 节点串联新标量参数 EffectBrightness(默认=1)。
// TransformCharacter.cpp · UpdateEffectBrightness()
// 白天=1(保持原大乘数不变),夜晚=0.03(压暗到接近默认)
const float Target = FMath::Lerp(NightEffBright, 1.0f,
ATimeOfDayManager::GetDaylightFactor(GetCurrentGameHours()));
// 对每个骨骼/静态网格材质槽创建 MID 并设 EffectBrightness
for (auto& Slot : MeshComponent->GetMaterials()) {
UMaterialInstanceDynamic* MID = MeshComponent->CreateAndSetMaterialInstanceDynamicFromMaterial(i, Slot);
MID->SetScalarParameterValue(TEXT("EffectBrightness"), Target);
}
五、技能特效 MPC EmissiveScale 接入
52 个技能发光材质,母材质链末端新增 Multiply × CollectionParameter(EmissiveScale),MPC 引用 /Game/TimeOfDay/MPC_GlobalEffectBrightness。TimeOfDayManager 每帧写入 MPC,三个昼夜曲线统一驱动。
六、复用要点(后续调亮调暗)
- 夜景太亮 → 调大
NightDimMaxEV(如 4→5);太暗 → 调小(如 4→3)。 - 压暗起止时间错位 → 只改
DuskStartH/DuskEndH/NightEndH/DawnRestoreEndH四个浮点即可。 - 角色发光夜晚过曝 → 调
NightEffBright从 0.03 增大到 0.05。 - 想临时关闭整套压暗 → 把
NightDimMaxEV设 0,或给消费方DimFactor赋 0。 - 加新的发光母材质 → 别忘了同样插 "Multiply × EffectBrightness",否则该材质不受昼夜缩放控制。
- 符号铁律再强调 → UE 曝光偏置 负 = 暗。任何照抄引擎曝光注释前先验证,V48 注释写反了。