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

Unity C#实现单次仅拾取一把枪械功能 修复按拾取键同时捡多枪问题

问题根因
  • 当前拾取逻辑挂载在每把独立的枪械预制体上,当多把枪械同时满足距离、触发条件时,按下E键会同步执行所有符合条件枪械的拾取逻辑,导致一次性拾取多把武器
  • 没有统一的玩家持械状态管理,无法在玩家已持有武器时拦截其余枪械的拾取请求
  • 原有OnTriggerStay2D逻辑存在错误:脚本挂载在枪械对象上,判断gameObject.tag == "player"永远不成立,导致dontpickup标记并未正常生效
修复方案
  1. 新增玩家侧统一武器管理脚本,全局记录玩家持械状态,避免多把武器同时抢占拾取权限
  2. 调整枪械侧拾取逻辑:新增范围标记、拾取状态标记,拾取前优先校验玩家全局持械状态
  3. 替换原有错误的触发检测逻辑,用OnTriggerEnter2D/OnTriggerExit2D准确标记枪械是否在可拾取范围内
完整实现代码

1. 玩家侧管理脚本(挂载到玩家对象上)

public class PlayerWeaponManager : MonoBehaviour
{
    // 全局单例,方便枪械脚本调用状态
    public static PlayerWeaponManager Instance;
    // 玩家当前是否持有武器
    public bool isHoldingWeapon = false;
    // 玩家当前持有的武器实例
    public GameObject currentWeapon;

    private void Awake()
    {
        if (Instance == null) Instance = this;
        else Destroy(gameObject);
    }
}

2. 枪械侧拾取/丢弃脚本(挂载到每把枪械对象上)

// 标记枪械是否在玩家拾取范围内
private bool inPickupRange = false;
// 标记当前枪械是否已被拾取
private bool isPicked = false;

private void Update()
{
    // 拾取逻辑:按下E、在范围内、未被拾取、玩家无持有武器时触发
    if (Input.GetKeyDown(KeyCode.E) && inPickupRange && !isPicked && !PlayerWeaponManager.Instance.isHoldingWeapon)
    {
        Pickup();
    }

    // 丢弃逻辑:按下Q、当前枪械是玩家持有武器时触发
    if (Input.GetKeyDown(KeyCode.Q) && isPicked && PlayerWeaponManager.Instance.currentWeapon == gameObject)
    {
        Dropdown();
    }
}

public void Pickup()
{
    // 二次校验玩家持械状态,避免异常
    if (PlayerWeaponManager.Instance.isHoldingWeapon) return;
    
    transform.SetParent(PlayerWeaponManager.Instance.transform);
    // 原有位置调整逻辑保留
    transform.position = PlayerWeaponManager.Instance.transform.position + new Vector3(4, 0, 0);
    
    Rigidbody2D rb = GetComponent<Rigidbody2D>();
    rb.isKinematic = true;
    Collider2D c = GetComponent<Collider2D>();
    c.isTrigger = true;
    
    // 更新全局和当前枪械的状态
    isPicked = true;
    PlayerWeaponManager.Instance.isHoldingWeapon = true;
    PlayerWeaponManager.Instance.currentWeapon = gameObject;
}

public void Dropdown()
{
    transform.SetParent(null);
    
    Rigidbody2D rb = GetComponent<Rigidbody2D>();
    rb.isKinematic = false;
    Collider2D c = GetComponent<Collider2D>();
    c.isTrigger = false;
    
    // 清空全局和当前枪械的状态
    isPicked = false;
    PlayerWeaponManager.Instance.isHoldingWeapon = false;
    PlayerWeaponManager.Instance.currentWeapon = null;
}

private void OnTriggerEnter2D(Collider2D other)
{
    // 进入玩家触发区时标记可拾取
    if (other.CompareTag("player") && !isPicked)
    {
        inPickupRange = true;
    }
}

private void OnTriggerExit2D(Collider2D other)
{
    // 离开玩家触发区时标记不可拾取
    if (other.CompareTag("player"))
    {
        inPickupRange = false;
    }
}
额外优化建议

如果需要进一步避免多枪在范围内的拾取冲突,可以把拾取的对象筛选逻辑放到PlayerWeaponManager中,按下E键时只选择距离玩家最近的一把可拾取枪械触发拾取,完全杜绝多捡的可能性。

内容的提问来源于stack exchange,提问作者lemons and giggles

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 13:45:00