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

关于eventData.pointerCurrentRaycast.gameObject及含Bug的OnPointerClick代码的咨询

问题分析与修复方案

Let's break down the bugs in your Unity UI click handler code and walk through practical fixes step by step:

1. 未处理空引用异常

你的代码直接访问eventData.pointerCurrentRaycast.gameObject却没有做判空检查。如果用户点击了没有射线检测目标的区域(比如UI面板外),这个gameObject会是null,后续访问selectedObject.name就会触发NullReferenceException。

修复方案:在后续逻辑前添加空值判断:

GameObject selectedObject = eventData.pointerCurrentRaycast.gameObject;
if (selectedObject == null) return;

2. 依赖脆弱的层级结构且缺少空值检查

selectedObject.transform.parent.Find("Card")完全依赖固定的UI层级结构,一旦你重命名"Card"节点、调整UI布局或者删除该节点,这段查找逻辑就会失效。更糟的是,你没有检查查找结果或GetComponent<CardInfo>()是否返回null,这会引发新的空引用错误。

修复方案:

  • 最佳实践是彻底避免使用Find:给你的CardSlotPanel脚本添加一个序列化字段,直接在Inspector面板关联CardInfo组件。
  • 如果必须使用查找逻辑,一定要添加严格的空值检查:
Transform cardTransform = selectedObject.transform.parent.Find("Card");
if (cardTransform == null) {
    Debug.LogError("无法在CardSlotPanel的父节点下找到'Card'对象!");
    return;
}

CardInfo cardInfo = cardTransform.GetComponent<CardInfo>();
if (cardInfo == null) {
    Debug.LogError("Card对象上没有挂载CardInfo组件!");
    return;
}

3. 缺失战术卡牌重复添加的警告逻辑

你的注释提到需要对重复添加的战术卡牌给出警告,但代码只是直接调用lineupBuilder.AddTactic(cardInfo),没有做任何重复检查。

修复方案:
首先在lineupBuilder类中添加一个检查重复战术的方法:

// 在LineupBuilder类中添加
public bool IsTacticAlreadyAdded(CardInfo tacticCard) {
    // 替换成你实际的已有战术检查逻辑,比如通过卡牌ID判断
    return currentTactics.Any(t => t.GetCardId() == tacticCard.GetCardId());
}

然后更新点击处理逻辑,加入检查和警告:

if (cardInfo.GetCardType() == "Tactic") {
    if (lineupBuilder.IsTacticAlreadyAdded(cardInfo)) {
        // 替换成你偏好的警告方式(比如UI弹窗、提示文本)
        Debug.LogWarning("该战术卡牌已添加到阵容中!");
        // 示例UI警告逻辑:
        // warningPanel.SetActive(true);
        // warningText.text = "战术卡牌已添加,请勿重复选择!";
    } else {
        lineupBuilder.AddTactic(cardInfo);
    }
}

4. 未完成的For循环(潜在风险)

你的代码写到for...就中断了——一定要补全循环逻辑,同时做好边界检查和空值安全。比如如果你要检查非战术卡牌的重复情况,可以用foreach循环实现清晰的逻辑:

string cardName = cardInfo.GetCardName();
bool isDuplicate = false;
foreach (var existingCard in lineupBuilder.GetCharacterCards()) {
    if (existingCard != null && existingCard.GetCardName() == cardName) {
        isDuplicate = true;
        break;
    }
}

if (isDuplicate) {
    Debug.LogWarning("该角色卡牌已添加到阵容中!");
} else {
    // 在这里添加你的角色卡牌添加逻辑
    // lineupBuilder.AddCharacterCard(cardInfo);
}

完整修复后的代码

下面是经过安全优化后的完整点击处理方法:

// 推荐:用常量代替硬编码字符串,避免拼写错误
private const string CARDSLOTPANEL = "CardSlotPanel";
private const string CARD_TYPE_TACTIC = "Tactic";

public void OnPointerClick(PointerEventData eventData) {
    if (!createLineupPanel.activeSelf) return;

    GameObject selectedObject = eventData.pointerCurrentRaycast.gameObject;
    if (selectedObject == null) return;

    if (selectedObject.name == CARDSLOTPANEL) {
        // 优先方案:用序列化引用代替Find查找
        // [SerializeField] private CardInfo _linkedCardInfo;
        // if (_linkedCardInfo == null) { /* 错误处理 */ }

        // 临时修复:带安全检查的查找逻辑
        Transform cardTransform = selectedObject.transform.parent.Find("Card");
        if (cardTransform == null) {
            Debug.LogError("CardSlotPanel父节点下未找到Card对象!");
            return;
        }

        CardInfo cardInfo = cardTransform.GetComponent<CardInfo>();
        if (cardInfo == null) {
            Debug.LogError("Card对象缺少CardInfo组件!");
            return;
        }

        if (cardInfo.GetCardType() == CARD_TYPE_TACTIC) {
            if (lineupBuilder.IsTacticAlreadyAdded(cardInfo)) {
                Debug.LogWarning("战术卡牌已添加到阵容!");
                // 这里添加UI警告逻辑
            } else {
                lineupBuilder.AddTactic(cardInfo);
            }
        } else {
            string cardName = cardInfo.GetCardName();
            bool isDuplicate = false;
            foreach (var existingCard in lineupBuilder.GetCharacterCards()) {
                if (existingCard != null && existingCard.GetCardName() == cardName) {
                    isDuplicate = true;
                    break;
                }
            }

            if (isDuplicate) {
                Debug.LogWarning("角色卡牌已添加到阵容!");
            } else {
                // 在这里添加角色卡牌的添加逻辑
            }
        }
    }
}

额外优化建议

  • 把所有硬编码字符串(比如"Tactic")替换成常量,避免拼写错误。
  • 尽可能用序列化引用代替Find/transform.parent这类查找方式,让代码更稳定、性能更好。
  • 给所有序列化字段(比如createLineupPanel和lineupBuilder)添加空值检查,提前发现配置错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 07:56:47