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

Unity钓鱼游戏Power Meter动画下fishAmount变量精准更新问题

问题根源分析
  1. OnTriggerStay2D持续触发的不确定性:该方法每帧都会执行,只要箭头处于碰撞区域内就会更新fishAmount。如果玩家点击瞬间箭头刚好移动到新区域,最终传入CatchFish的数值会是最后一帧触发的区域值,和玩家视觉上看到的区域不匹配。
  2. 静态变量的全局干扰风险:fishAmount被声明为static,若场景中存在多个FishinDeckController实例,或其他逻辑意外修改该变量,会直接导致数值混乱。
  3. 缺失触发器离开逻辑:未实现OnTriggerExit2D,导致区域提示文本不会自动关闭,玩家看到的提示可能和箭头当前所在区域脱节,进一步引发认知错误。
  4. ClickDeck执行顺序漏洞:先关闭动画再获取fishAmount,但当前帧内OnTriggerStay2D仍可能执行,导致数值被再次修改。
针对性修复方案

1. 替换实时更新为点击时主动检测

移除OnTriggerStay2D中的fishAmount赋值逻辑,改为在玩家点击时主动检测箭头当前位置对应的区域,确保数值完全匹配点击瞬间的状态:

步骤1:添加箭头引用

在FishinDeckController中添加箭头的Transform引用:

public Transform arrowTransform; // 在Inspector中拖入箭头对象

步骤2:重构区域提示逻辑

删除原OnTriggerStay2D中的数值赋值,保留UI提示的显示逻辑,并新增OnTriggerExit2D处理提示关闭:

private void OnTriggerEnter2D(Collider2D other)
{
    if (!_animation.enabled)
    {
        ShowFeedbackText(other.tag);
    }
}

private void OnTriggerExit2D(Collider2D other)
{
    HideAllFeedbackTexts();
}

private void ShowFeedbackText(string tag)
{
    HideAllFeedbackTexts();
    switch(tag)
    {
        case "Green":
            perfectText.SetActive(true);
            break;
        case "LightGreen":
            goodText.SetActive(true);
            break;
        case "Red":
        case "Orange":
            notBadText.SetActive(true);
            break;
    }
}

private void HideAllFeedbackTexts()
{
    perfectText.SetActive(false);
    goodText.SetActive(false);
    notBadText.SetActive(false);
}

步骤3:修改ClickDeck方法,点击时主动检测

public void ClickDeck()
{
    _animation.enabled = false;
    HideAllFeedbackTexts();

    // 主动检测箭头当前位置的碰撞区域
    int currentFishAmount = 0;
    Collider2D[] hitColliders = Physics2D.OverlapPointAll(arrowTransform.position);
    foreach (var collider in hitColliders)
    {
        if (collider.CompareTag("Green"))
        {
            currentFishAmount = 3;
            break;
        }
        else if (collider.CompareTag("LightGreen"))
        {
            currentFishAmount = 2;
            break;
        }
        else if (collider.CompareTag("Red") || collider.CompareTag("Orange"))
        {
            currentFishAmount = 1;
            break;
        }
    }

    CatchFish(currentFishAmount);
    StartCoroutine(DeckCloser());
}

2. 移除静态变量修饰符

将原静态变量改为私有实例变量(甚至可以直接删除,因为现在用局部变量):

// 替换原public static int fishAmount = 0;
private int fishAmount = 0; // 若后续不需要可直接删除

3. 优化执行顺序

在ClickDeck中先隐藏提示文本,再检测数值,避免视觉残留误导。

最佳实践替代方案

1. UI射线检测(更适合UI元素)

因为Power Meter是UI组件,使用Unity的EventSystem进行射线检测比2D碰撞体更准确:

  • 给每个颜色区域的Image添加EventTrigger组件
  • 监听PointerEnter和PointerExit事件,记录当前选中的区域标签
  • 点击时直接使用记录的标签获取对应的鱼数量

2. 状态机管理钓鱼流程

将钓鱼过程拆分为准备→箭头移动→等待点击→捕获四个状态,用状态机(如自定义枚举或Unity的State Machine Behaviour)管理:

  • 仅在等待点击状态下允许检测区域和处理点击
  • 状态切换时锁定相关逻辑,避免跨状态的意外数值修改

3. 数值快照缓存

若坚持使用触发器,可在玩家按下点击的瞬间(Input.GetMouseButtonDown)立即缓存当前的fishAmount,确保后续逻辑使用的是点击瞬间的数值:

private int cachedFishAmount = 0;
private bool isClicking = false;

private void Update()
{
    if (Input.GetMouseButtonDown(0) && !_animation.enabled)
    {
        cachedFishAmount = fishAmount;
        isClicking = true;
    }
}

public void ClickDeck()
{
    if (!isClicking) return;
    _animation.enabled = false;
    CatchFish(cachedFishAmount);
    StartCoroutine(DeckCloser());
    isClicking = false;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 09:14:51