Unity 3D无尽跑酷脚本如何正确识别playerContainer下激活的子对象
问题原因
你使用的GameObject.FindGameObjectWithTag()API默认逻辑是返回场景中第一个匹配对应标签的对象,不会过滤对象的激活状态,也不会优先匹配当前正在使用的玩家下的子对象,所以才会一直拿到首个playerContainer下的Coin Detect对象,哪怕它已经被禁用。
最优修复方案(无需修改角色选择脚本,仅调整Magnet脚本即可)
不需要在Magnet脚本启动时提前查找Coin Detect对象,可以在触发碰撞时直接从碰撞到的当前激活玩家对象下查找对应的子碰撞盒,永远不会出现找错的情况:
using System.Collections; using UnityEngine; public class Magnet : MonoBehaviour { void Start() { // 移除原来的全局查找逻辑,将每个玩家的Coin Detect默认设为禁用即可 Debug.Log("Magnet initialized"); } private void OnTriggerEnter(Collider other) { if(other.gameObject.CompareTag("Player")) { // 直接从当前碰撞到的激活玩家身上查找Coin Detect对象 Transform coinDetect = other.transform.Find("Coin Detect"); if(coinDetect != null) { StartCoroutine(coinActivate(coinDetect.gameObject)); } Destroy(transform.GetChild(0).gameObject); } } IEnumerator coinActivate(GameObject coinDetect) { Debug.Log("Magnet activated"); coinDetect.SetActive(true); yield return new WaitForSeconds(5f); coinDetect.SetActive(false); } }
方案说明
- 碰撞时的
other对象就是当前正在使用的激活玩家对象,直接从它的子节点按名称查找Coin Detect,100%匹配当前使用的角色 - 不需要维护全局的玩家引用,逻辑更简洁,不会出现匹配错误问题
备选方案(适合多脚本需要调用当前玩家的场景)
如果你的项目中多个道具脚本都需要访问当前激活的玩家,可以修改EnablePlayerSelector脚本,把当前激活的玩家存为静态变量,方便全局调用:
修改后的EnablePlayerSelector脚本
using UnityEngine; public class EnablePlayerSelector : MonoBehaviour { public GameObject[] players; public int currPlayerCount; // 新增静态变量,全局可访问当前激活的玩家 public static GameObject CurrentActivePlayer; void Start() { currPlayerCount = PlayerPrefs.GetInt("SelectedPlayer", 0); foreach (GameObject player in players) player.SetActive(false); players[currPlayerCount].SetActive(true); // 赋值当前激活的玩家 CurrentActivePlayer = players[currPlayerCount]; } }
之后任意脚本需要查找当前玩家的Coin Detect,都可以用以下代码获取:
GameObject coinDetect = EnablePlayerSelector.CurrentActivePlayer.transform.Find("Coin Detect").gameObject;
层级结构参考

注意事项
- 确保每个玩家prefab下的Coin Detect对象名称完全一致,不要出现拼写错误
- 建议把Coin Detect的默认状态设为禁用,不需要在Magnet的Start方法里统一处理
内容的提问来源于stack exchange,提问作者drunkdazed
相关产品推荐
相关产品推荐

