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的子物体数量判断可切换范围,未区分已拾取/未拾取的武器。需要:
- 维护一个已拾取武器列表,仅记录玩家实际获得的武器
- 切换逻辑限制在已拾取列表内循环
- 拾取时将武器加入已拾取列表,避免未拾取武器被选中
修改后的武器切换脚本
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
相关产品推荐
相关产品推荐

