Minecraft 1.12.2雾色平滑过渡代码故障排查求助
问题:Minecraft 1.12.2模组下雨时雾色平滑过渡失效
使用Forge API 2859开发1.12.2模组,需求是下雨时让雾色从当前值平滑过渡到设定值。现有代码通过EntityViewRenderEvent.FogColors事件每tick(每秒20次)检测下雨状态并执行雾色调整,但尝试lerp插值、逐帧增加红色通道值等方法均失效:红色通道值增长到0.25后便停止变化,无法完成完整过渡。
原代码
import net.minecraft.client.Minecraft; import net.minecraftforge.client.event.EntityViewRenderEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; public class RustWaterFog { static public double lerp(double fromValue, double toValue, double progress) { return fromValue + (toValue - fromValue) * progress; } double[] dod = {0.0, 0.0, 0.0}; float[] progcon = {0.0001f, 0.0001f, 0.0001f}; @SubscribeEvent public void onEntityViewRender(EntityViewRenderEvent.FogColors event) { double[] BLOOD_COLOR = {event.getRed(), event.getGreen(), event.getBlue()}; if (Minecraft.getMinecraft().world.isRaining()) { /* event.setBlue(lerp(BLOOD_COLOR[2], 0.02f, progcon[2])); event.setGreen(lerp(BLOOD_COLOR[1], 0.02f, progcon[1])); event.setRed(lerp(BLOOD_COLOR[0], 0.50f, progcon[0])); dod[0] = Math.round(lerp(BLOOD_COLOR[0], 0.50f, progcon[0]) * 100.0) / 100.0; dod[1] = Math.round(lerp(BLOOD_COLOR[1], 0.02f, progcon[1]) * 100.0) / 100.0; dod[2] = Math.round(lerp(BLOOD_COLOR[2], 0.02f, progcon[2]) * 100.0) / 100.0; if (dod[0] < 0.50) { progcon[0] += 0.0009f; } else { } if (dod[1] < 0.02) { progcon[1] += 0.0009f; } if (dod[2] < 0.02) { progcon[2] += 0.0009f; } System.out.println(dod[1]); double dolboeb = 0.001; //dolboeb+=0.001; double red = event.getRed(); float red1 = (float)Math.round(lerp(event.getRed()*100, 58, dolboeb) * 1000.0) / 1000; event.setRed(red1); /*event.setGreen(); event.setBlue();*/ dod[0] = (Math.round(BLOOD_COLOR[0] * 100.0) / 100.0)+0.1; float dodred = (float)dod[0]; event.setRed(dodred); System.out.println(dodred); } } }
控制台输出
0.2 0.22 0.22 0.22 0.23 0.23 0.23 0.23 0.23 0.23 0.23 0.23 0.23 0.23 0.23 0.23 0.23 0.23 0.23 0.23 0.23 0.23 0.23 0.23 0.23 0.23 0.23 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.24 0.25
问题分析
- 状态丢失:每次事件触发时直接取
event.getRed()作为起始值,但这个值是游戏当前的默认雾色,而非你上次修改后的值。游戏会在事件触发间重置雾色,导致你每次都在默认值基础上修改,无法累积过渡进度。 - 逻辑混乱:没有维护独立的过渡状态变量,而是混用临时计算值,导致过渡逻辑被游戏默认值打断。
- 步长控制不当:逐帧加固定值的方式没有考虑与目标值的距离,容易卡在某个数值后无法继续接近目标。
解决方案
维护独立的雾色过渡状态,基于保存的当前值向目标值做平滑线性插值,确保每tick的过渡进度能持续累积。
修正后的代码
import net.minecraft.client.Minecraft; import net.minecraftforge.client.event.EntityViewRenderEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; public class RustWaterFog { // 下雨时的目标雾色 private static final float TARGET_RAIN_RED = 0.50f; private static final float TARGET_RAIN_GREEN = 0.02f; private static final float TARGET_RAIN_BLUE = 0.02f; // 每tick的过渡进度比例,0.05表示每秒完成100%(20*0.05)的过渡,可根据需求调整 private static final float TRANSITION_SPEED = 0.05f; // 保存当前过渡中的雾色值,初始化为-1标记未初始化 private float currentRed = -1f; private float currentGreen = -1f; private float currentBlue = -1f; @SubscribeEvent public void onEntityViewRender(EntityViewRenderEvent.FogColors event) { Minecraft mc = Minecraft.getMinecraft(); if (mc.world == null) return; // 第一次触发时,初始化当前雾色为游戏默认值 if (currentRed == -1f) { currentRed = event.getRed(); currentGreen = event.getGreen(); currentBlue = event.getBlue(); } if (mc.world.isRaining()) { // 向下雨目标色平滑过渡 currentRed = lerp(currentRed, TARGET_RAIN_RED, TRANSITION_SPEED); currentGreen = lerp(currentGreen, TARGET_RAIN_GREEN, TRANSITION_SPEED); currentBlue = lerp(currentBlue, TARGET_RAIN_BLUE, TRANSITION_SPEED); } else { // 停止下雨时,过渡回游戏默认雾色(不需要可删除此块) currentRed = lerp(currentRed, event.getRed(), TRANSITION_SPEED); currentGreen = lerp(currentGreen, event.getGreen(), TRANSITION_SPEED); currentBlue = lerp(currentBlue, event.getBlue(), TRANSITION_SPEED); } // 设置最终雾色 event.setRed(currentRed); event.setGreen(currentGreen); event.setBlue(currentBlue); } // 线性插值工具方法 private float lerp(float from, float to, float progress) { return from + (to - from) * progress; } }
关键修正点
- 新增
currentRed/Green/Blue变量保存当前过渡状态,避免被游戏默认值覆盖。 - 使用固定比例的过渡速度,确保平滑且持续地接近目标值。
- 第一次触发事件时初始化状态,保证起始值正确。
- 加入停止下雨时的反向过渡逻辑,让雾色自然恢复(可选)。
内容的提问来源于stack exchange,提问作者Ego Solus
相关产品推荐
相关产品推荐

