【unity实战】FPS实现拾取和丢弃枪

简介: 【unity实战】FPS实现拾取和丢弃枪

定义枪物品

定义枪数据

[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,拾取文本就随便添加一个可以了

效果

image.png

目录
相关文章
|
6月前
|
图形学
【unity实战】时间控制 昼夜交替 四季变化 天气变化效果
【unity实战】时间控制 昼夜交替 四季变化 天气变化效果
164 0
|
4月前
|
开发者 图形学 Java
揭秘Unity物理引擎核心技术:从刚体动力学到关节连接,全方位教你如何在虚拟世界中重现真实物理现象——含实战代码示例与详细解析
【8月更文挑战第31天】Unity物理引擎对于游戏开发至关重要,它能够模拟真实的物理效果,如刚体运动、碰撞检测及关节连接等。通过Rigidbody和Collider组件,开发者可以轻松实现物体间的互动与碰撞。本文通过具体代码示例介绍了如何使用Unity物理引擎实现物体运动、施加力、使用关节连接以及模拟弹簧效果等功能,帮助开发者提升游戏的真实感与沉浸感。
124 1
|
3月前
|
图形学 C++ C#
Unity插件开发全攻略:从零起步教你用C++扩展游戏功能,解锁Unity新玩法的详细步骤与实战技巧大公开
【8月更文挑战第31天】Unity 是一款功能强大的游戏开发引擎,支持多平台发布并拥有丰富的插件生态系统。本文介绍 Unity 插件开发基础,帮助读者从零开始编写自定义插件以扩展其功能。插件通常用 C++ 编写,通过 Mono C# 运行时调用,需在不同平台上编译。文中详细讲解了开发环境搭建、简单插件编写及在 Unity 中调用的方法,包括创建 C# 封装脚本和处理跨平台问题,助力开发者提升游戏开发效率。
307 0
|
4月前
|
开发者 图形学 API
从零起步,深度揭秘:运用Unity引擎及网络编程技术,一步步搭建属于你的实时多人在线对战游戏平台——详尽指南与实战代码解析,带你轻松掌握网络化游戏开发的核心要领与最佳实践路径
【8月更文挑战第31天】构建实时多人对战平台是技术与创意的结合。本文使用成熟的Unity游戏开发引擎,从零开始指导读者搭建简单的实时对战平台。内容涵盖网络架构设计、Unity网络API应用及客户端与服务器通信。首先,创建新项目并选择适合多人游戏的模板,使用推荐的网络传输层。接着,定义基本玩法,如2D多人射击游戏,创建角色预制件并添加Rigidbody2D组件。然后,引入网络身份组件以同步对象状态。通过示例代码展示玩家控制逻辑,包括移动和发射子弹功能。最后,设置服务器端逻辑,处理客户端连接和断开。本文帮助读者掌握构建Unity多人对战平台的核心知识,为进一步开发打下基础。
159 0
|
4月前
|
开发者 图形学 C#
揭秘游戏沉浸感的秘密武器:深度解析Unity中的音频设计技巧,从背景音乐到动态音效,全面提升你的游戏氛围艺术——附实战代码示例与应用场景指导
【8月更文挑战第31天】音频设计在游戏开发中至关重要,不仅能增强沉浸感,还能传递信息,构建氛围。Unity作为跨平台游戏引擎,提供了丰富的音频处理功能,助力开发者轻松实现复杂音效。本文将探讨如何利用Unity的音频设计提升游戏氛围,并通过具体示例代码展示实现过程。例如,在恐怖游戏中,阴森的背景音乐和突然的脚步声能增加紧张感;在休闲游戏中,轻快的旋律则让玩家感到愉悦。
128 0
|
6月前
|
存储 JSON 关系型数据库
【unity实战】制作unity数据保存和加载系统——大型游戏存储的最优解
【unity实战】制作unity数据保存和加载系统——大型游戏存储的最优解
194 2
|
6月前
|
人工智能 定位技术 图形学
【unity实战】制作敌人的AI,使用有限状态机、继承和抽象类多态 定义不同状态的敌人行为
【unity实战】制作敌人的AI,使用有限状态机、继承和抽象类多态 定义不同状态的敌人行为
177 1
|
6月前
|
图形学
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统(下)
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统
93 0
|
6月前
|
图形学 容器
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统(上)
【unity实战】Unity中基于瓦片的网格库存系统——类似《逃离塔科夫》的库存系统
100 0
|
6月前
|
存储 JSON 图形学
【unity实战】制作unity数据保存和加载系统——小型游戏存储的最优解
【unity实战】制作unity数据保存和加载系统——小型游戏存储的最优解
203 0