Unity吃鸡背包系统笔记

功能需求

  1. 查看玩家拥有的所有物品,可以放下其中的任意物品;
  2. 查看已死的他人背包的物品,可以拿起其中的任意物品;
  3. 查看附近的物品,可以拿起其中的任意物品(暂时不考虑背包容量);

难点

1.背包里的物品数据存在脚本里,玩家不可能直接在检查器面板查看背包的物品,必须把它们呈现到UI界面上,这就使同一份数据在脚本和UI界面存在两份,必须使两份数据保持一致。玩家通过UI界面操作改变脚本里的数据时,为了保持两份数据一致理论上UI界面的数据必须总是从脚本读取,而不能直接操作UI界面,比如从场景拿一个弹匣到背包里,如果用代码把附近物品栏的这个弹匣删掉,再在背包物品栏加上这个弹匣,实际上进行了脚本数据和UI界面的两线操作,造成了两边数据不一致的可能性。比如如果弹匣UI的脚本记录的是自己在背包物品列表的索引,玩家拿起了不是最后一个的弹匣,那么被拿起弹匣后面的弹匣在背包物品列表的索引实际上变化了,这时候就应该把附近物品列表的所有物品删除,重新从脚本读取显示。

2.玩家从场景拿起一个物品放进背包时需要把该物品销毁,从背包放下物品时需要把物品实例化。实例化时需要知道实例化哪个物品,背包里的物品没有场景里的实例,只是数据,这个数据就要记录如果自己被放到场景里需要实例化一个什么物体,即记录自己的预制体。

背包里记录弹匣数据的结构体定义为:

cs 复制代码
[Serializable]
    public struct MagInPack{
        public Mag magPrefab;
        public int ammoNum;
        public MagInPack(Mag magPrefab, int ammoNum){
            this.magPrefab=magPrefab;
            this.ammoNum=ammoNum;
        }
    }

然后我发现拾取场景里的弹匣时我只知道这个实体弹匣,这个弹匣放进背包时这个物体就销毁了,背包里的弹匣数据结构体需要记录弹匣的预制体,也就是场景里的弹匣实体都要记录自己的预制体,捡起放进背包时存入弹匣结构体。

然后我发现让一个预制体的脚本里一个引用指向预制体它自己,预制体实例化后这个引用指向的也是场景里的实例它自己了。 不能让一个预制体脚本里的引用指向它自己来记录预制体。

背包里的弹匣结构体保存有它的预制体,放下弹匣的时候把预制体引用传给实例的预制体引用;拿起弹匣的时候则从实例的预制体引用传给背包里的结构体。

背包界面的物品UI,在场景里的有对应物体,在玩家背包里和附近其他人背包里的物品在场景里没有物体,都要生成物品UI。

子弹信息记录的数据结构

而换弹的逻辑我没写把背包的子弹加到弹匣,而是没打完的弹匣放回背包,在弹匣队列尾部。这样背包里的子弹数不能用一个数字记录,必须用一个列表:

这样换弹的时候会麻烦点,需要在列表里遍历,直到找到需要的子弹。

后来发现,如果换弹逻辑做成把背包里的子弹加到弹匣里,那么应该定义子弹种类的枚举,然后使用相同子弹的不同枪从同一个子弹数字段里取子弹;如果换弹逻辑做成把背包里的弹匣换上,没打完的弹匣放回背包,那么使用相同子弹的不同枪的弹匣也是不通用的,比如G17和M9使用同一种子弹,但是弹匣不通用,容弹量不一样,应该定义枪的型号的枚举,定义子弹型号的枚举就没有意义。

需要做的测试

1.点开背包界面,显示的物品和人物拥有的一致

2.走近其他物品,点开背包界面,其他物品出现在附近物品栏

3.点拥有的枪或物品,把它放下,此物品出现在附近物品栏;如果是弹匣这样在背包里没有实体的物品,附近应该出现它的实体

4.捡起身上没有的物品,此物品从附近物品栏消失,加入拥有的物品;如果是弹匣,此物品在场景里的实体消失

5.和附近的枪交换

6.打开背包界面查看附近的物品,按F拾取,再打开背包界面,该物品从附近物品栏消失

7.打开背包界面查看附近的物品,按F放下枪,再打开背包界面,该物品出现在附近物品栏

附近物品列表及其维护

背包脚本声明了一个列表记录周围可拾取的物品:

如果不做可拾取物品列表,背包界面不显示附近可拾取物品,拾取物品一律按F拾取,背包系统会简单很多。但是就无法拿其他人背包里的物品。

Physics.OverlapSphere()检测附近物品

打开背包界面时用Physics.OverlapSphere()得到一个球形区域的碰撞体,筛选出可拾取的、没有主人的物品,加入附近物品列表。加之前要先把附近物品列表清空。

cs 复制代码
 public float pickUpRange=2;
    public LayerMask packCheckLayerMask;
    public void CheckItemsAround(){
        itemsAround.Clear();
        packsAround.Clear();
        Collider[] thingsAround=Physics.OverlapSphere(transform.position,pickUpRange,packCheckLayerMask);//检测周围球形区域里的物品
        Item item;
        Weapon gun;
        MyCharacter other;
        for(int i=0;i<thingsAround.Length;i++){
            if(thingsAround[i].TryGetComponent(out item)){//检测到是物品
                if(item is Weapon){
                    gun=item as Weapon;
                    if(gun!=myCharacter.rifleScript&&gun!=myCharacter.pistolScript&&gun.owner==null){//不是人物自己的枪&&枪没有主人
                        itemsAround.Add(item);
                    }
                }
            }
            else if(thingsAround[i].TryGetComponent(out other)){//检测到是人
                if(other.life<=0&&other.backpack){//人已经死了&&人有背包
                    for(int j=0;j<other.backpack.magsInPack.Count;j++){
                        packsAround.Add(other.backpack);
                    }
                }
            }
            
        }
    }
相关推荐
m0_6371469311 分钟前
计算机网络基础总结:TCP/IP 模型、TCP vs UDP、DNS 查询过程
笔记·tcp/ip·计算机网络
Lester_110128 分钟前
嵌入式学习笔记 - freeRTOS vTaskPlaceOnEventList()函数解析
笔记·学习
moxiaoran57532 小时前
uni-app学习笔记二十三--交互反馈showToast用法
笔记·学习·uni-app
scdifsn9 小时前
动手学深度学习12.7. 参数服务器-笔记&练习(PyTorch)
pytorch·笔记·深度学习·分布式计算·数据并行·参数服务器
jackson凌12 小时前
【Java学习笔记】SringBuffer类(重点)
java·笔记·学习
huangyuchi.13 小时前
【Linux】LInux下第一个程序:进度条
linux·运维·服务器·笔记·进度条·c/c++
大写-凌祁14 小时前
论文阅读:HySCDG生成式数据处理流程
论文阅读·人工智能·笔记·python·机器学习
Unpredictable22214 小时前
【VINS-Mono算法深度解析:边缘化策略、初始化与关键技术】
c++·笔记·算法·ubuntu·计算机视觉
傍晚冰川15 小时前
FreeRTOS任务调度过程vTaskStartScheduler()&任务设计和划分
开发语言·笔记·stm32·单片机·嵌入式硬件·学习
Love__Tay16 小时前
【学习笔记】Python金融基础
开发语言·笔记·python·学习·金融