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

tModLoader模组开发:跨类方法无法修改UI变量致纹理不更新

解决tModLoader模组UI纹理无法随连击等级更新的问题

核心问题分析

你遇到的本质是UI类实例引用不匹配:直接修改RankSign._rankID时,操作的可能不是当前正在渲染的UI实例,而是未绑定到界面的新实例或无效实例。而在Update方法内直接修改能生效,是因为那是当前活跃UI实例的方法上下文。

具体修复步骤

  1. 维护唯一可访问的UI实例
    在模组主类中定义静态变量存储活跃的UI实例,避免多处创建新对象:

    public class YourMod : Mod
    {
        public static RankSign ActiveRankUI;
    }
    

    在UI初始化(比如玩家进入世界、界面加载时)将实例赋值给该变量:

    // 示例:在UI创建逻辑中
    YourMod.ActiveRankUI = new RankSign();
    Main.playerInventoryUI.Add(YourMod.ActiveRankUI);
    
  2. 修正等级更新逻辑
    在btPlayer的RankExchange方法中,通过模组静态变量定位到活跃UI实例更新等级:

    public void RankExchange()
    {
        // 计算当前连击等级
        int Rank = CalculateCurrentRank();
        // 更新活跃UI的等级值
        if(YourMod.ActiveRankUI != null)
        {
            YourMod.ActiveRankUI._rankID = Rank;
            // 强制UI刷新布局和纹理
            YourMod.ActiveRankUI.Recalculate();
        }
    }
    
  3. 使用封装方法更新UI(推荐)
    在RankSign类中添加公开方法处理等级更新,替代直接修改私有字段,避免破坏封装性:

    public class RankSign : UIElement
    {
        private int _rankID;
        
        public void UpdateRank(int newRank)
        {
            _rankID = newRank;
            // 在此处直接触发纹理加载逻辑
            LoadRankTexture(newRank);
            Recalculate();
        }
    }
    

    然后在RankExchange中调用该方法:

    YourMod.ActiveRankUI?.UpdateRank(Rank);
    
  4. 验证Update方法的调用上下文
    确认btPlayer的Update方法是在当前操控的玩家实例上执行,可添加日志输出验证:

    public override void Update(Player player)
    {
        base.Update(player);
        Main.NewText($"当前更新的玩家ID: {player.whoAmI}");
        RankExchange();
    }
    

关键注意事项

  • tModLoader的UI系统基于实例运行,必须确保修改的是屏幕上正在渲染的那个UI对象。
  • 当UI元素被移除或重建时,要及时更新模组静态引用,避免空引用异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 19:42:15