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);
                    }
                }
            }
            
        }
    }
相关推荐
zzzkk20099 分钟前
BambuStudio学习笔记:MTUtils
笔记·学习
虾球xz22 分钟前
游戏引擎学习第151天
学习·游戏引擎
爱学习的小王!28 分钟前
有关MyBatis的动态SQL
java·笔记·sql·学习·mybatis
一条晒干的咸魚38 分钟前
【C#学习笔记03】进制转换与反码、补码、原码
开发语言·笔记·学习·c#
王嘉俊9251 小时前
MySQL 入门笔记
数据库·笔记·sql·mysql·adb
你的微笑像拥抱1 小时前
npm-shrinkwrap.json 与 package-lock.json 区别和联系
笔记
niu_sama2 小时前
[杂学笔记] TCP和UDP的区别,对http接口解释 , Cookie和Session的区别 ,http和https的区别 , 智能指针 ,断点续传
笔记·tcp/ip·http
淳杰2 小时前
ubuntu-学习笔记-nginx+php
笔记·学习·ubuntu
阿噜噜小栈2 小时前
如何用AI制作我们记忆中的乡村夜景
人工智能·经验分享·笔记
Angindem2 小时前
RabbitMQ (Java)学习笔记
笔记·学习·rabbitmq