定义枪物品
定义枪数据
[CreateAssetMenu(menuName = "Data/Gun")] public class GunData : ScriptableObject { public int Index;//索引 public string Name;//名称 public GameObject GunPrefab;//枪预制体 }
在枪预制体上,绑定GunItem 代码,控制拾取和绑定GunData 枪数据
public class GunItem : MonoBehaviour { public GunData thisGunData;//绑定枪 }
新增GunManager,管理枪支丢弃拾取和切换
public class GunManager : MonoBehaviour { public static GunManager Instance; Dictionary<int, GunData> gunDictionary = new Dictionary<int, GunData>(); [HideInInspector] public GunData thisGunData;//当前选中 public Transform fpsCam; public Transform[] childObjects; private void Awake() { Instance = this; } private void Update() { // 数字切换武器 if (Input.GetKeyDown(KeyCode.Alpha1)) { SwitchGun(1); } else if (Input.GetKeyDown(KeyCode.Alpha2)) { SwitchGun(2); } else if (Input.GetKeyDown(KeyCode.Alpha3)) { SwitchGun(3); } //丢弃枪 if (Input.GetKeyDown(KeyCode.G)) { // 丢弃物体 Drop(); } // 遍历资源字典,输出每个资源类型及其对应的数量 foreach (int index in gunDictionary.Keys) { Debug.Log(gunDictionary[index].Name); } } private void Drop() { if(thisGunData == null) return; var res = Instantiate(thisGunData.GunPrefab, fpsCam.position+fpsCam.forward * 0.4f, Quaternion.identity); var rb = res.GetComponent<Rigidbody>(); // 添加力 rb.AddForce(fpsCam.forward * 5f, ForceMode.Impulse); rb.AddForce(fpsCam.up * 10f, ForceMode.Impulse); // 添加随机旋转 float random = UnityEngine.Random.Range(-1f, 1f); rb.AddTorque(new Vector3(random, random, random) * 10); //隐藏当前武器 childObjects[thisGunData.Index - 1].gameObject.SetActive(false); RemoveGun(); thisGunData = null; } // 切换武器 public void SwitchGun(int index) { // 如果资源字典中没有该编号的资源,直接返回 if (!gunDictionary.ContainsKey(index)) { return; } // 隐藏当前武器 if (thisGunData != null) { childObjects[thisGunData.Index - 1].gameObject.SetActive(false); } // 显示新的武器 thisGunData = gunDictionary[index]; childObjects[thisGunData.Index - 1].gameObject.SetActive(true); } //判断是否已存在枪 public bool isGun(GunData gunData) { return gunDictionary.ContainsKey(gunData.Index); } //添加 public void AddGun(GunData gunData) { gunDictionary.Add(gunData.Index, gunData); } //删除当前 public void RemoveGun() { gunDictionary.Remove(thisGunData.Index); } }
记得配置枪支碰撞检测为持续,防止丢弃时掉入地底
并且禁用枪支预制体和人物的碰撞
拾取脚本
using UnityEngine; //拾取脚本 public class PickUpController : MonoBehaviour { public float maxDistance = 3f; // 最大检测距离 public LayerMask layerMask; // 检测层级 public GameObject uiText; // 显示物品名称的 UI 文本组件 void Start() { uiText.SetActive(false); // 初始状态下 UI 文本组件不可见 } void Update() { // 从相机屏幕中心向前发射一条射线 Ray ray = Camera.main.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0f)); RaycastHit hitInfo; if (Physics.Raycast(ray, out hitInfo, maxDistance, layerMask)) { uiText.SetActive(true); //hitInfo.transform.CompareTag("PickUpItem") 需要的话可以再加标签判断 if (Input.GetKeyDown(KeyCode.E)) { PickUpItem(hitInfo.transform); } } else { uiText.SetActive(false); } } // 拾取物体 void PickUpItem(Transform item) { GunData thisGunData = item.GetComponent<GunItem>().thisGunData; if (GunManager.Instance.isGun(thisGunData)) { Debug.Log("位置已存在枪"); } else { GunManager.Instance.AddGun(thisGunData); GunManager.Instance.SwitchGun(thisGunData.Index); Destroy(item.gameObject); } } }
配置参数,记得修改拾取枪支预制体层级为GunItem,拾取文本就随便添加一个可以了
效果