Unity MVC实现背包系统(2)

news2024/11/28 11:55:05

在上一篇中,我们写了背包系统的伪代码,也说了mvc的设计思路,那么这一篇的任务就是将伪代码补全。 

首先制作一个背包面板,我这里比较简单,就是一个滚动视图,还有一个提示文本,外加两个按钮,一个是使用物品,一个是增加物品,然后给滚动视图的Content添加上布局组件,这样当我们动态添加物品预制体的时候就会自动布局了。

这里我们将背包的mvc三层脚本都挂载在背包面板的根节点上,方便互相获取调用,因为我们本篇是针对背包的实现进行的,至于mvc这三层脚本如何获取调用,实际上是由UI框架去决定的,包括代码的周期等等,所以我们这里方便测试,直接挂载在面板根节点。

首先,我们的背包是用来存放物品的,因此必须有一个物品类,来体现这个物品所具有的属性。

public class Item
{
    public ulong onlyId;
    public int spriteId;
}
这里我只记录了onlyId和这个物品对应的图片id,首先onlyId这是一个物品的唯一标识,因为每个物品都是不同的,即使两个物品完全一样,那么他们也是独立出来的两个物品,结合实际就可以想象得知。而图片是为了等下演示方便大家可以看出来是不同物品,这里写的很简陋了,大家可以自行添加,这里只是讲解思路。

然后在看到数据层脚本。

public class BagData : MonoBehaviour
{
    BagCtrl ctrl;
    Dictionary items;  //存储背包中所有物品

    ulong onlyId;

    private void Awake()
    {
        onlyId = 0;
        ctrl = GetComponent();
        items = new Dictionary();

    }

    public void TestAddItem()
    {
        onlyId++;
        Item newItem = new Item();
        newItem.onlyId = onlyId;
        newItem.spriteId = Random.Range(1, 6);
        items.Add(newItem.onlyId, newItem);

    }

    public Item[] GetItems()
    {
        if (items.Count == 0)
            return null;
        Item[] temp = new Item[items.Count];
        items.Values.CopyTo(temp, 0);
        //返回背包中所有物品
        return temp;
    }

    public void AddItem()
    {
        //增加物品
    }

    public void DelItem(ulong onlyId)
    {
        if (items.ContainsKey(onlyId))
            items.Remove(onlyId);
        //删除物品
    }

    public void UpdateItem()
    {
        //更新物品
    }

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }
}
首先获取逻辑层的引用,然后是实例化我们的物品字典,根据物品的唯一标识来存储物品信息,然后还写了一个测试添加物品的方法,因为我们游戏当中物品来源有很多种,比如打怪掉落,或者是商城购买等等,我们这里就直接给一个按钮去调用这个方法,然后每次新增物品onlyId都去自增,保证onlyId不重复,然后随机给一张图片,从1-6,因为我只放了五张图片资源。这个方法也很简单了,new一个物品对象然后存储在字典中。

还有删除方法,根据外部传进来的onlyId删除物品,还有一个获取背包当前所有物品的方法,也是很简单,直接返回字典中的所有物品信息。

接着看到逻辑层。

public class BagCtrl : MonoBehaviour
{
    BagView view;
    BagData data;

    private void Awake()
    {
        view = GetComponent();
        data = GetComponent();
    }

    public Item[] GetItems()
    {
        if (data.GetItems() == null)
            return null;
        return data.GetItems();
    }

    public void AddItem()
    {
        data.AddItem();
        view.UpdateView();
    }

    public void Add()
    {
        data.TestAddItem();
        view.UpdateView();
    }

    public void UpdateItem()
    {
        data.UpdateItem();
    }

    public void UseItem(ulong id)
    {
        //使用物品使用效果

        //删除该物品或减少该物品数量
        data.DelItem(id);
        view.UpdateView();
    }

    public void Discard(ulong id)
    {
        //删除该物品或减少该物品数量
        data.DelItem(id);
        view.UpdateView();
    }

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }
}
在上一篇我们已经说了,逻辑层是视图层以及数据层的中介,所以要先获取这两者的引用。然后向外提供一个获取所有物品的方法,目的是让视图层获取数据层的物品信息,还有添加物品方法。使用物品丢弃物品,这里我们直接将物品给删了,物品的效果,这个大家自行扩展了,比如你打开的是一个礼包,那么就是调用数据层的添加物品方法,然后再把这个礼包给删了,实际上都是一些简单逻辑。处理完数据,在调用视图层的UpdateView方法,也就是刷新视图层的显示,因为物品已经改变了,这里实际上最好应该先判断一下,如果背包面板没有打开的话,是不需要去刷新的。

最后看到视图层,

public class BagView : MonoBehaviour
{

    BagCtrl ctrl;
    public Button btn_use;
    public Button btn_add;
    public Text txt_tips;
    public Transform img_content;

    ulong current_onlyId;

    List items;

    private void Awake()
    {
        ctrl = GetComponent();
        items = new List();
    }

    // Start is called before the first frame update
    void Start()
    {
        current_onlyId = 0;
        btn_use.onClick.AddListener(() =>
        {
            if (current_onlyId == 0)
                return;
            ctrl.UseItem(current_onlyId);
            current_onlyId = 0;
        });
        btn_add.onClick.AddListener(() =>
        {
            ctrl.Add();
            current_onlyId = 0;
        });

        UpdateView();

    }

    public void UpdateView()
    {
        txt_tips.text = "当前没有选中的物品";
        if(items.Count > 0)
        {
            for(int i = 0; i < items.Count; i++)
            {
                Destroy(items[i]);
            }
        }
        items.Clear();

        if (ctrl.GetItems() == null)
            return;

        Item[] newItems = ctrl.GetItems();
        GameObject itemRes = Resources.Load("Prefab/Item");
        for(int i = 0; i < newItems.Length; i++)
        {
            GameObject newItem = Instantiate(itemRes);
            newItem.transform.SetParent(img_content);
            items.Add(newItem);
            Sprite spr = Resources.Load("Sprite/" + newItems[i].spriteId);
            Image img = newItem.transform.GetChild(0).GetComponent();
            img.sprite = spr;
            ulong temp = newItems[i].onlyId;
            newItem.GetComponent().onClick.AddListener(() =>
            {
                current_onlyId = temp;
                txt_tips.text = "当前选中的物品的onlyId是:" + temp;
            });
        }

    }

    // Update is called once per frame
    void Update()
    {

    }
}
最上面的几个参数,currentOnlyId,这个是用来记录当前玩家选中的物品的,还有一个items列表,是用来保存当前背包面板下的所有物品游戏对象的也就是GameObject类型的。一开始先将currentOnlyId归零,获取逻辑层的引用。给两个按钮添加监听,当按下使用按钮,则调用逻辑层的使用物品按钮,将当前选中的物品的onlyId传进去,添加物品就直接调用逻辑层的使用物品方法即可,最后调用一下刷新方法。

刷新方法,首先把提示信息重置一下,当前没有选择任何物品,然后将items列表中的所有游戏对象销毁掉,也就是清空操作,然后再从逻辑层获取现有的所有物品重新进行生成,就是获取物品预制体,然后实例化,根据物品信息的图片给物品修改图片,将物品存进items列表,挂载再content物品下自动布局。最后给物品添加监听,当按下物品时修改提示文案和cuurentOnlyId。这样就是一次刷新操作了。

大家可以可以复制代码自行测试下效果,工程我会放在qq群上,大家也可以加群获取。

最后补充一下,本文章讲的是一个mvc实现背包的一个设计思路,比如说上面的销毁,实际上可以放在对象池,等等的一些优化操作,这个视项目而定,因为本文章面向的是还无法自己完成背包系统的同学,所以会尽可能的只针对背包来讲,希望本文章对大家有所帮助。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/590412.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

20230530论文整理·1-课题组1

个人观点&#xff0c;现在的NLP文章&#xff0c;有些是在做积木&#xff0c;微创新&#xff0c;有些文章&#xff0c;是可以的&#xff0c;读起来很美&#xff0c;有些&#xff0c;太过逆了&#xff0c;吃起来没味道&#xff0c;反胃。 文章目录 1.CODEIE: Large Code Generat…

【.NET AI Books】问题分类和技能使用大全

第一章 问题分类 我会把问题设定放在首位&#xff0c;也就是我们的第一章。毕竟所有生成式的 AI 都是需要基于问题给出答案。所以我一直不认同人工智能会取代人类&#xff0c;没有人类哪来问题呢&#xff1f; ChatGPT 的神奇之处在于它可以根据你的问题去完成不同的工作&…

【Python实战】Python采集C站热榜数据

前言 大家好,我们今天来爬取c站的热搜榜,把其文章名称,链接和作者获取下来,我们保存到本地,我们通过测试,发现其实很简单,我们只要简单获取数据就可以。没有加密的东西。 效果如下: 环境使用 python 3.9pycharm模块使用 requests模块介绍 requests requests是…

95后阿里P7架构师晒出工资单:狠补了这个,真香...

最近一哥们跟我聊天装逼&#xff0c;说他最近从阿里跳槽了&#xff0c;我问他跳出来拿了多少&#xff1f;哥们表示很得意&#xff0c;说跳槽到新公司一个月后发了工资&#xff0c;月入5万多&#xff0c;表示很满足&#xff01;这样的高薪资着实让人羡慕&#xff0c;我猜这是税后…

阿里云的消息队列(MQ)服务如何帮助解决应用程序中的消息传递问题?

阿里云的消息队列(MQ)服务如何帮助解决应用程序中的消息传递问题&#xff1f;   [本文由阿里云代理商[聚搜云www.4526.cn]撰写]   随着企业应用程序的复杂性不断增加&#xff0c;消息传递在系统间的通信与协作中扮演着越来越重要的角色。本文将探讨阿里云的消息队列&#x…

Vue-组件的嵌套

组件的嵌套 组件的嵌套也是开发中比较常见的方式 一个大组件里面有多个小组件&#xff0c;大组件一般称为父组件&#xff0c;小组件称为子组件 1 编写案例 首先定义一个school组件 提出新的需求:现在我想在school里面定义一个子组件(student)出现 首先创建student组件&…

uni-app扩展组件(uni-ui)

目录 数字角标(uni-badge) 代码示例&#xff1a; 面包屑(uni-breadcrumb) 代码示例&#xff1a; 日历 代码示例 卡片(uni-card) 代码示例 倒计时(uni-countdown) 更多内容请访问官网 数字角标(uni-badge) 数字角标一般和其它控件&#xff08;列表、9宫格等&#xff0…

网络编程--多线程服务器客户端

写在前面 此前的回声服务器/客户端都是在主线程中阻塞交互&#xff0c;本文将使用多线程方式实现服务器/客户端。 互斥量相关接口 使用多线程&#xff0c;自然避免不了线程同步问题。 因本文使用互斥量实现线程同步&#xff0c;因此仅介绍互斥量相关接口&#xff0c;其他实…

【MySQL高级篇笔记-索引的数据结构 (中) 】

此笔记为尚硅谷MySQL高级篇部分内容 目录 一、索引及其优缺点 1、索引概述 2、优点 3、缺点 二、InnoDB中索引的推演 1、设计索引 1.一个简单的索引设计方案 2.InnoDB中的索引方案 2、常见索引概念 1. 聚簇索引 2. 二级索引&#xff08;辅助索引、非聚簇索引&#…

Java阶段三Day06

Java阶段三Day06 文章目录 Java阶段三Day06同步请求和异步请求案例演示创建SpringBoot工程application.propertiesUserControllerUserMapper静态页面 JSONSpring Security引入SpringSecurity框架对项目的影响关于SpringSecurity的配置默认登录表单设置白名单模拟登录使用自己的…

用pycharm来下载super-grandients 出现的错误

主要用来记录我用pycharm来下载super-grandients的一些错误 文章目录 1、UserWarning: Distutils was imported before Setuptools.1、distutils 2、pycharm的虚拟环境安装的包在c盘3、虚拟内存不够 1、UserWarning: Distutils was imported before Setuptools. UserWarning: …

系统集成项目管理工程师(系统集成基础知识)

第一章信息化知识 一、信息的概述 1、信息(information)是客观事物状态和运动特征的一种普遍形式&#xff1b;事物的本体论信息&#xff0c;就是事物的运动状态和状态变化方式的自我表述。 二、信息的传递 2、信息技术主要为解决信息的采集、加工、存储、传输、处理、计算、…

设计模式之~适配器模式

描述&#xff1a; adapter将一个类的接口转换成客户希望的另外一个接口。adapter模式使得原本由于接口不兼容而不能一起工作的类可以一起工作。 在软件开发中&#xff0c;当系统的数据和行为都正确&#xff0c;但接口不符时&#xff0c;我们应该考虑使用适配器&#xff0c;目的…

Node.js详解(二):Node.js与JS的关系

一、简介 Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境&#xff0c;是一个让 JavaScript 运行在服务端的开发平台&#xff0c;它让 JavaScript 成为与PHP、Python、Perl、Ruby 等服务端语言平起平坐的脚本语言。 JavaScript一种直译式脚本语言&#xff0c;是一种…

NMS非极大值抑制

文章目录 一、NMS详解二、NMS具体步骤与实现1.步骤2、代码(pytorch版本) 一、NMS详解 NMS即非极大值抑制&#xff0c;常被用于目标检测等&#xff0c;即只保留检测同一物体置信度最大的框。 具体作用可以看图&#xff1a; 可以看出&#xff0c;未经过nms的图片&#xff0c;有…

基于Freertos的ESP-IDF开发——8.使用wifi访问HTTP服务器

目录 0. 前言其他ESP-IDF文章 1. 前期准备1.1头文件准备1.2 http 服务器搭建 2. 连接 wifi3.http访问任务4. 完整代码 0. 前言 使用ESP32使用 wifi 访问 http 服务器 开发环境&#xff1a;ESP-IDF 4.2 操作系统&#xff1a;Ubuntu22.04 开发板&#xff1a;自制的ESP32-WROOM-…

流行框架(二)网络请求库 OKhttp

文章目录 概述HttpURLConnectionGET和POST获取文本数据GETPOST OKHttp基本使用依赖与权限发起一个get请求重要概念OkHttpClientRequestCallRealCallAsyncCall 请求调度器Dispatcher同步请求execute的执行异步请求enqueue的执行两种请求方式的总结 OkHttp拦截器链拦截器种类addI…

字节狂问1小时,小伙offer到手,太狠了!(字节面试真题)

前言&#xff1a; 在尼恩的&#xff08;50&#xff09;读者社群中&#xff0c;经常有小伙伴&#xff0c;需要面试 头条、美团、阿里、京东等大厂。 下面是一个小伙伴成功拿到字节飞书offer&#xff0c;通过一小时拷问的面试经历&#xff0c;就两个字&#xff1a; 深&#xf…

基于STM32的SYN6288语音播报模块驱动实验(代码开源)

前言&#xff1a;本文为手把手教学 SYN6288 语音播报模块的驱动实验&#xff0c;本教程的 MCU 采用STM32F103ZET6。通过 CubeMX 软件配置 UART 串口协议驱 SYN6288 模块进行规定的语音播报。考虑到 SYN6288 模块的集成化与智能化很高&#xff0c;所以该模块的使用是极其便利的。…

【HarmonyOS】初识低代码平台开发元服务

【关键字】 HarmonyOS、低代码平台、元服务开发、拖拽式开发 【写在前面】 今天要分享的是HarmonyOS中的低代码开发相关的内容&#xff0c;低代码开发是DevEco Studio提供的一种UI界面可视化的构建方式&#xff0c;通过图形化的自由拖拽数据的参数化配置&#xff0c;可以快速…