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

Unity:竞技场射击风格武器拾取与切换系统问题求助

竞技场射击游戏武器拾取与切换问题解决

问题概述

我是新手程序员,正在搭建竞技场射击风格的武器拾取与切换系统,结合Brackey的武器切换代码和自定义拾取脚本时遇到以下问题:

  • 需求:玩家踏入武器触发区域时,拾取物消失,对应武器在玩家手中激活;拾取多把武器后可在它们之间切换
  • 当前问题:武器激活功能正常,但仍可通过滚轮或数字键切换到未拾取的武器

现有代码

武器切换脚本

//[SerializeField] public GameObject[] myGuns;
//[SerializeField] public GameObject[] theAmmo;

void Start()
{
    SelectWeapon();
}

void Update()
{
    int previousSelectedWeapon = selectedWeapon;

    if (Input.GetAxis("Mouse ScrollWheel") > 0f) // up
    {
        if (selectedWeapon >= transform.childCount - 1)
            selectedWeapon = 0;
        else
            selectedWeapon++;
    }
    if (Input.GetAxis("Mouse ScrollWheel") < 0f) // down
    {
        if (selectedWeapon <= 0)
            selectedWeapon = transform.childCount - 1;
        else
            selectedWeapon--;
    }

    if (Input.GetKeyDown(KeyCode.Alpha1))
    {
        selectedWeapon = 0;
    }

    if (Input.GetKeyDown(KeyCode.Alpha2) && transform.childCount >= 2)
    {
        selectedWeapon = 1;
    }

    if (Input.GetKeyDown(KeyCode.Alpha3) && transform.childCount >= 3)
    {
        selectedWeapon = 2;
    }

    if (Input.GetKeyDown(KeyCode.Alpha4) && transform.childCount >= 4)
    {
        selectedWeapon = 3;
    }

    if (Input.GetKeyDown(KeyCode.Alpha5) && transform.childCount >= 5)
    {
        selectedWeapon = 4;
    }

    if (Input.GetKeyDown(KeyCode.Alpha6) && transform.childCount >= 6)
    {
        selectedWeapon = 5;
    }

    if (Input.GetKeyDown(KeyCode.Alpha7) && transform.childCount >= 7)
    {
        selectedWeapon = 6;
    }

    if (Input.GetKeyDown(KeyCode.Alpha8) && transform.childCount >= 8)
    {
        selectedWeapon = 7;
    }

    if (Input.GetKeyDown(KeyCode.Alpha9) && transform.childCount >= 9)
    {
        selectedWeapon = 8;
    }

    if (Input.GetKeyDown(KeyCode.Alpha0) && transform.childCount >= 10)
    {
        selectedWeapon = 9;
    }

    if (previousSelectedWeapon != selectedWeapon)
    {
        SelectWeapon();
    }
}

void SelectWeapon()
{
    int i = 0;
    foreach (Transform weapon in transform)
    {
        if (i == selectedWeapon)
            weapon.gameObject.SetActive(true);
        else
            weapon.gameObject.SetActive(false);
        i++;
    }
}

武器拾取脚本

public GameObject weapon; //Place the weapon from the hierarchy here
public GameObject weaponHolder; //Place the weapon holder here
public GameObject weaponDummy; //Place the pickup here

void Start()
{
    weaponDummy.SetActive(true); //The weapon pickup is set to active
}

void OnTriggerEnter(Collider col)
{
    if (col.tag == "Player") //If player walks into gun collider
    {
        foreach (Transform obj in weaponHolder.transform)
        {
            obj.gameObject.SetActive(false); //Set all the weapons in the weapon holder to not active
    }
        weapon.SetActive(true); //Specified weapon is active
        weaponDummy.SetActive(false); //Set to false
    }
}

解决方案

核心思路

当前代码的问题是仅通过武器Holder的子物体数量判断可切换范围,未区分已拾取/未拾取的武器。需要:

  1. 维护一个已拾取武器列表,仅记录玩家实际获得的武器
  2. 切换逻辑限制在已拾取列表内循环
  3. 拾取时将武器加入已拾取列表,避免未拾取武器被选中

修改后的武器切换脚本

using System.Collections.Generic;
using UnityEngine;

public class WeaponSwitcher : MonoBehaviour
{
    private int selectedWeaponIndex = 0;
    // 存储已拾取的武器Transform
    private List<Transform> acquiredWeapons = new List<Transform>();

    void Start()
    {
        // 初始化:将初始激活的武器加入已拾取列表
        foreach (Transform weapon in transform)
        {
            if (weapon.gameObject.activeSelf)
            {
                acquiredWeapons.Add(weapon);
            }
            else
            {
                weapon.gameObject.SetActive(false);
            }
        }
        // 如果有已拾取武器,默认选中第一把
        if (acquiredWeapons.Count > 0)
        {
            SelectWeapon();
        }
    }

    void Update()
    {
        // 没有已拾取武器时不处理切换逻辑
        if (acquiredWeapons.Count == 0) return;

        int previousSelected = selectedWeaponIndex;

        // 滚轮切换:仅在已拾取武器范围内循环
        if (Input.GetAxis("Mouse ScrollWheel") > 0f)
        {
            selectedWeaponIndex = (selectedWeaponIndex + 1) % acquiredWeapons.Count;
        }
        if (Input.GetAxis("Mouse ScrollWheel") < 0f)
        {
            selectedWeaponIndex = (selectedWeaponIndex - 1 + acquiredWeapons.Count) % acquiredWeapons.Count;
        }

        // 数字键切换:仅当对应武器已拾取时生效
        if (Input.GetKeyDown(KeyCode.Alpha1)) TrySelectWeaponByIndex(0);
        if (Input.GetKeyDown(KeyCode.Alpha2)) TrySelectWeaponByIndex(1);
        if (Input.GetKeyDown(KeyCode.Alpha3)) TrySelectWeaponByIndex(2);
        if (Input.GetKeyDown(KeyCode.Alpha4)) TrySelectWeaponByIndex(3);
        if (Input.GetKeyDown(KeyCode.Alpha5)) TrySelectWeaponByIndex(4);
        if (Input.GetKeyDown(KeyCode.Alpha6)) TrySelectWeaponByIndex(5);
        if (Input.GetKeyDown(KeyCode.Alpha7)) TrySelectWeaponByIndex(6);
        if (Input.GetKeyDown(KeyCode.Alpha8)) TrySelectWeaponByIndex(7);
        if (Input.GetKeyDown(KeyCode.Alpha9)) TrySelectWeaponByIndex(8);
        if (Input.GetKeyDown(KeyCode.Alpha0)) TrySelectWeaponByIndex(9);

        if (previousSelected != selectedWeaponIndex)
        {
            SelectWeapon();
        }
    }

    // 尝试根据武器在Holder中的原始索引切换,仅当该武器已拾取时生效
    private void TrySelectWeaponByIndex(int originalIndex)
    {
        if (originalIndex >= transform.childCount) return;
        Transform targetWeapon = transform.GetChild(originalIndex);
        if (acquiredWeapons.Contains(targetWeapon))
        {
            selectedWeaponIndex = acquiredWeapons.IndexOf(targetWeapon);
        }
    }

    void SelectWeapon()
    {
        // 先关闭所有武器
        foreach (Transform weapon in transform)
        {
            weapon.gameObject.SetActive(false);
        }
        // 激活当前选中的已拾取武器
        acquiredWeapons[selectedWeaponIndex].gameObject.SetActive(true);
    }

    // 供拾取脚本调用,添加新拾取的武器
    public void AddAcquiredWeapon(Transform weapon)
    {
        if (!acquiredWeapons.Contains(weapon))
        {
            acquiredWeapons.Add(weapon);
            // 如果是第一把拾取的武器,直接选中
            if (acquiredWeapons.Count == 1)
            {
                selectedWeaponIndex = 0;
                SelectWeapon();
            }
        }
    }
}

修改后的武器拾取脚本

using UnityEngine;

public class WeaponPickup : MonoBehaviour
{
    public GameObject weapon; // 拖入Hierarchy中的武器对象
    public GameObject weaponHolder; // 拖入武器Holder对象
    public GameObject weaponDummy; // 拖入拾取道具对象

    void Start()
    {
        weaponDummy.SetActive(true);
        // 初始状态下武器设为未激活
        weapon.SetActive(false);
    }

    void OnTriggerEnter(Collider col)
    {
        if (col.CompareTag("Player"))
        {
            weaponDummy.SetActive(false);
            weapon.SetActive(true);
            // 调用切换脚本的添加方法,记录已拾取武器
            WeaponSwitcher switcher = weaponHolder.GetComponent<WeaponSwitcher>();
            switcher.AddAcquiredWeapon(weapon.transform);
        }
    }
}

额外优化建议

  • 给每个武器添加Weapon组件,记录武器名称、索引、弹药等信息,方便后续扩展UI和功能
  • 用循环简化数字键判断逻辑,避免重复代码:
    for (int i = 0; i < 10; i++)
    {
        KeyCode key = i == 9 ? KeyCode.Alpha0 : (KeyCode)System.Enum.Parse(typeof(KeyCode), $"Alpha{i+1}");
        if (Input.GetKeyDown(key))
        {
            TrySelectWeaponByIndex(i);
            break;
        }
    }
    
  • 添加UI显示已拾取武器的图标或名称,提升玩家体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 22:45:39