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);
                    }
                }
            }
            
        }
    }
相关推荐
kfepiza19 分钟前
Win11GBK, idea2024.2.4, 使用Gradle8.8本地安装构建,不使用包装器, 解决utf-8乱码问题, 笔记241028
笔记·gradle·intellij-idea·idea·intellij idea
黄交大彭于晏25 分钟前
第五天学习总结:C语言学习笔记 - 数组篇
c语言·笔记·学习
魔法自动机33 分钟前
Unity3D学习FPS游戏(3)玩家第一人称视角转动和移动
unity·1024程序员节·fps
Pandaconda1 小时前
【计算机网络 - 基础问题】每日 3 题(五十九)
开发语言·经验分享·笔记·后端·计算机网络·面试·职场和发展
爱编程的古惑仔1 小时前
leetcode刷题笔记——15.三数之和
笔记·算法·leetcode
zhentiya1 小时前
哈工大《理论力学》第九版课后答案解析及笔记PDF
笔记·pdf
tealcwu2 小时前
【Unity基础】初识UI Toolkit - 运行时UI
ui·unity·编辑器·游戏引擎
一心赚狗粮的宇叔2 小时前
java web调试时清理当前网址的缓存
java·前端·笔记·后端·缓存
呵呵哒( ̄▽ ̄)"2 小时前
尚硅谷-react教程-求和案例-最终版-笔记
笔记