1. 数据库脚本

1.1 元素(item)代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;[CreateAssetMenu(fileName ="New Item",menuName ="Inventory/New Item")]
public class Item : ScriptableObject
{public string itemName;//数据库物品名public Sprite image;//数据库物品图片public int itemHold;//数据库物品数量public bool equip;//数据库物品是否可装备public int objectIndex;//数据库物品序号(序号保持一致性)[TextArea]public string info;//数据库物品说明
}

1.2 数据库代码(ItemList)代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;[CreateAssetMenu(fileName ="New List",menuName ="Inventory/New List")]
public class ItemList : ScriptableObject
{public List<Item> itemList = new List<Item>();//item和itemscript的类名一样
}

2. 游戏世界物品

为了将sprite和数据库,元素连接我们需要在创建一个脚本挂在所有可收集的物品(item的)上

2.1 ItemOnWorld

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class ItemOnWorld : MonoBehaviour
{public Item TheItem;//对每个世界物品都要将世界物品绑定在此脚本上public ItemList List;//绑定我们的数据库mybagprivate void OnTriggerEnter2D(Collider2D collision){if (collision.gameObject.CompareTag("Player")){AddNewItem();//添加物品到背包数据库Destroy(gameObject);//销毁物品}}//数据库操作private void AddNewItem(){if (!List.itemList.Contains(TheItem))//判断包不包含,首先要创建相应的item项然后绑定在ItemOnWorld中{List.itemList.Add(TheItem);//不在则添加到背包数据库InventoryManager.CreateNewItem(TheItem);//并创建预制件在背包UI显示}else{TheItem.itemHold++;//包含则数量加1InventoryManager.RefreshItem(TheItem);//刷新数量}}}

3. 背包系统

3.1 Slot

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class Slot : MonoBehaviour
{public Item slotItem;//背包物品对象public Image slotImage;//背包物品图像public Text slotNum;//背包物品数量public int objectIndex;//背包物品序号(序号保持一致性)public void onClick(){GameObject.Find("Canvas").SendMessage("UpdateItemInfo", slotItem.info);}
}

3.2 ListManager

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class InventoryManager : MonoBehaviour
{static InventoryManager instance;public ItemList myBag;//背包连接的数据库:mybagpublic Slot slotPrefab;//背包物品预制件(可以和所有物品对应)public Text itemInformation;//背包物品说明public GameObject slotGrid;//unity背包网格(在其下创建子物体,方便与背包格子对齐)//单例模式private void Awake(){if (instance != null){Destroy(instance);}instance = this;}//每次进游戏刷新背包(根据背包数据库的内容创建预制件并在背包UI显示)private void OnEnable(){RefreshItem();}public static void CreateNewItem(Item item){//克隆预制件Slot newitem = Instantiate(instance.slotPrefab, instance.slotGrid.transform.position, Quaternion.identity);//为克隆预制件赋值(方便在背包UI显示)newitem.gameObject.transform.SetParent(instance.slotGrid.transform);//设置父物体newitem.slotItem = item;newitem.slotImage.sprite = item.image;newitem.slotNum.text = item.itemHold.ToString();newitem.objectIndex = item.objectIndex;}//刷新背包物品数量,注意与下面的区别开来,其实是专业叫做重载public static void RefreshItem(Item item){//利用transform遍历子对象foreach (Transform slot in instance.slotGrid.transform){//获取Slot脚本组件中的objectIndex进行匹配if (slot.gameObject.GetComponent<Slot>().objectIndex == item.objectIndex){slot.gameObject.GetComponent<Slot>().slotNum.text = item.itemHold.ToString();}}}public static void RefreshItem(){//数据库不为空,并且背包对象的子对象不为零(由于会获取到自身所以要<=1)if (instance.myBag.itemList.Count != 0 && instance.slotGrid.gameObject.GetComponentsInChildren<Transform>().Length <= 1){//重新进游戏时重新创建预制件for (int i = 0; i < instance.myBag.itemList.Count; i++){CreateNewItem(instance.myBag.itemList[i]);}}}//显示物品描述public void UpdateItemInfo(string info){itemInformation.text = info;}
}

解释:

冒号在C#中表示继承,ScriptableObject (脚本对象)是一个可独立于类实例来保存大量数据的数据容器,

最常用的功能就是背包系统的实现,ScriptableObject的特点是在游戏结束后,数据不会清除,依旧会保留游戏中产生的数据。所以可以利用这一点来做背包系统

就像MonoBehaviour一样,ScriptableObject派生自基本Unity对象,但与MonoBehaviour不同,不能将ScriptableObject附加到游戏对象,只能将他们保存在项目中

unity中[]表示具有特殊功能的标记。

[CreateAssetMenuAttribute]对 ScriptableObject 派生类型进行标记,使其自动列在 Assets/Create 子菜单中,以便能够轻松创建该类型的实例并将其作为“.asset”文件存储在项目中。

fileName: 此类型的新建实例使用的默认文件名。
menuName: Assets/Create 菜单中显示的此类型的显示名称。
order: Assets/Create 菜单中菜单项的位置。

效果图:

ItemOnWorld脚本中成员变量 的类型和Item和ItemList脚本的类相对应

[TextArea]为文本区域

List.itemList.Contains(TheItem)

List为对应的数据库类的实例,而itemList为数据库类的成员变量(真正的数据库),只不过我们对这个成员变量进行了实例化。

  1. 跨脚本调用函数
GameObject.Find("Canvas").SendMessage("UpdateItemInfo", slotItem.info)

对象.SendMeesage(函数名,参数,SendMessageOptions)

第三个参数的意义:
SendMessageOptions.RequireReceiver //如果没有找到相应函数,会报错(默认是这个状态)
SendMessageOptions.DontRequireReceiver //即使没有找到相应函数,也不会报错,自动忽略

static也可以跨脚本调用

单例模式:
单例模式(Singleton),也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在

实现单例模式(monobehavior):

public static test2 instance;// Use this for initializationvoid Awake () {instance = this;}

由于只存在一个实例所以常常用作管理器

  1. 判断标签:
//CompareTag()
//例子:if (collision.gameObject.CompareTag("Player")){AddNewItem();Destroy(gameObject);}
  1. list常用的方法
    unity:List数据类型常用方法和属性

  2. Instantiate

Instantiate(Object original):克隆物体original,其Position和Rotation取默认值,何为默认值呢?就是预制体的position,这里的position是世界坐标,无父物体

Instantiate(Object original, Transform parent):克隆物体original,拥有父物体,其Position和Rotation取默认值,这里的position是localposition,也就是相对于父物体的坐标,父物体为坐标原点

Instantiate(Object original, Transform parent, bool instantiateInWorldSpace):
若instantiateInWorldSpace=false,代表克隆的物体的坐标是localposition,则与Instantiate(Object original, Transform parent)的结果一样。
若instantiateInWorldSpace=true,则代表克隆的物体的坐标为世界坐标

Instantiate(Object original, Vector3 position, Quaternion rotation, Transform parent):这个比较好理解了,克隆物体original,拥有父物体,其Position和Rotation由人为设置,而且这里设置的坐标是世界坐标,不是localposition

Slot newitem = Instantiate(instance.slotPrefab, instance.slotGrid.transform.position, Quaternion.identity);

其中Quaternion.identity:该四元数对应于“no rotation”- 对象与世界轴或父轴完全对齐。

  1. 如何设置父对象
    子对象.transform.SetParent(父对象.transform)
    (好像关于父子对象都是用transform)

脚本也是一个组件,可以通过GetComponent<>()找到,所以想修改脚本或匹配脚本数据时可以用这样的方法

  1. 获取所有子元素
    GetComponentsInChildren()
TestComponent[] trans = GetComponentsInChildren<Transform>();//这样可以获取到自身
  1. 获取子物体数量
Transform.childCount
  1. OnEnable()
    当对象的激活时,并且脚本激活时(小勾勾)执行一次

  2. 静态变量可以跨场景传值。

快捷键:
Ctrl+K+D可以快事格式化代码

参考资料:

CreateAssetMenuAttribute
Unity 数据存储方式之一:ScriptableObject
Unity中的SendMessage的用法
Unity单例模式+例子
Unity3d设计模式之单例模式
Unity单例模式
Quaternion.identity
Unity3d GameObject.Instantiate函数理解
(Unity)Instantiate粗略讲解
nity从青铜 到 王者!只差这篇让你学会Unity中最重要的部分——脚本组件
Unity3D——GetComponentsInChildren()方法详解
获取子物体数量—Transform.childCount
Unity中关于transform.root和transform.parent的区别和联系?
unity实例化物体到父物体之下
使用Unity获取所有子对象及拓展方法的使用
Unity获取未激活游戏对象的方法
【Unity3D 灵巧小知识点】 ☀️ | 获取某个游戏对象下的所有子物体
【Unity3D日常开发】如何获取所有的子对象(child)
Unity3D如何获取对象和子对象
Unity开发备忘录000021:如何判断某一个对象是否有子对象
Unity Awake() OnEnable() Start()三个函数理解
Awake/Start/OnEnable 辨析
【Unity 05】C# static类及其使用方法
C# 静态类 静态变量 静态方法 在Unity中的使用
unity, 什么时候用静态类,什么时候用单例
c#中get set 的使用
C#中{get;set;}
【C#学习笔记】C#中set和get用法
Unity之背包系统(一):物品类的生成和背包的制作
unity开发背包系统
unity 背包系统之美

常见报错情况:
【解决】NullReferenceException: Object reference not set to an instance of an object XXXX
Unity报错之【NullReferenceException: Object reference not set to an instance of an object】
nity The referenced script (Unknown) on this Behaviour is missing!

Unity背包系统-2:数据库存储方法ScriptableObject和显示背包物品InventoryManager相关推荐

  1. 数据库存储图片路径并显示到前端

    数据库存储图片路径并显示到前端 -为啥不直接存图片:因为图片本身太大了,虽然存取方便了程序员,但对数据库不友好.所以采取存取路径,再根据路径解析的方法. 一.数据库表设计: 从以上思想出发,需要存图片 ...

  2. 微信昵称在数据库存储处理,解决显示乱码方案

    微信昵称在数据库存储处理,解决显示乱码方案 原理:我们先将微信昵称编码存入数据库,显示的时候解码,就可以避免数据库无法直接存储微信昵称中的特殊字符. 一.定义编码解码类 <?php /*** C ...

  3. 【Unity 3D游戏开发】在Unity使用NoSQL数据库方法介绍

    随着游戏体积和功能的不断叠加,游戏中的数据也变得越来越庞杂,这其中既包括玩家产生的游戏存档等数据,例如关卡数.金币等,也包括游戏配置数据,例如每一关的配置情况.尽管Unity提供了PlayerPref ...

  4. mysql5.7更改数据库存储位置_mysql 5.7更改数据库的数据存储位置的解决方法

    随着mysql数据库存储的数据逐渐变大,已经将原来的存储数据的空间占满了,导致mysql已经链接不上了.因此,必须要给存放的数据换个地方了.下面是操作过程中的一些步骤.记下来,以后日后查看. 1.修改 ...

  5. php上传文件并存储到mysql数据库的方法

    本文实例讲述了php上传文件并存储到mysql数据库的方法.分享给大家供大家参考.具体分析如下: 下面的代码分别用于创建mysql表和上传文件保存到mysql数据库 创建mysql表: 1 2 3 4 ...

  6. 数据库树形结构存储方法的选择

    树形结构存储方法的选择 简单的方法跟踪多级回复构成的树形分支:parent_id 一开始的思路 使用parent_id跟踪分支 使用先找出所有节点,按照一定顺序整合成树形结构 缺陷: 在深度过深时仅用 ...

  7. JS获取input框用户输入信息作为数组存储传输给后台数据库操作存储方法

    JS获取input框用户输入信息作为数组存储传输给后台数据库操作存储方法 获取input框用户输入信息数组存储 var datas = {Id: idData.id,OrderDetailCode: ...

  8. c 连接mysql批量存储数据库_C语言连接操作MySQL数据库的方法

    C语言连接操作MySQL数据库的方法 2014-07-13 16:20来源:中国存储网 导读:C语言连接mysql数据库,需要相应的头文件和lib文件,如果你安装Mysql数据库,会在安装目录下找到这 ...

  9. python中文件的存储类型_关于python中数据存储大总结,涵盖文件系统和数据库存储两种方法-文件系统类型...

    存储数据是python必不可免的话题,数据的存储类型也多种多样,文件系统存储(.txt..csv..json.多媒体存储).关系型数据库存储(MySQL等).非关系型数据库存储(MongoDB).今天 ...

最新文章

  1. 华北电力大学计算机导论试题,保定华北电力大学计算机与科学大一课程
  2. 你知道面试必问的AOP吗(1),2021吊打面试官系列
  3. qml: C++调用qml函数
  4. NeurIPS 2020 所有RL papers全扫荡
  5. Java jdk的安装 与 环境变量的配置
  6. 如何安装和使用Android夜神模拟器
  7. 服务器控制台网页登录,云服务器管理控制台登录网站
  8. 使用Spring-data-jpa修改数据后,查询到脏数据
  9. C语言的自动关机程序和一个用来整人的小程序
  10. 博客左侧导航栏添加打赏功能(添加微信赞赏码)
  11. 华为云服务器配置教程
  12. 机器学习笔记:随机深度网络 stochastic depth
  13. 交互设计指南 iphone_交互设计:角色创建指南
  14. 商标知识:食品行业商标注册应注册哪几个类别?
  15. 全选反选的逻辑和代码
  16. 简单大方的java自我介绍,简单大方的自我介绍
  17. 基于贝叶斯优化的离散组合序列问题调研
  18. Fiddler手机抓包,及HTTPS协议抓包【手机如何安装fiddler证书,以华为为例】
  19. xctf攻防世界 MISC高手进阶区 Miscellaneous-300
  20. 今天给大家带来满满的干货:华为的薪资与奖金

热门文章

  1. scpjsv3模组链接_我的世界scpv3模组
  2. vscode能写winform窗体吗_VSCode——愉快的写C#
  3. 排列组合相关笔试面试题(C++)
  4. Android自定义ViewGroup的布局,往往都是从流式布局开始
  5. 【最新技术早知道】PCIe Gen5 还没用上,Gen6 就来了?PCIe 6.0 系列文章之:《PCIe 6.0,到底 6 在哪?》
  6. P3374 【模板】树状数组 1( 单点修改 + 区间查询 )
  7. 疑因内部宫斗被离职,中兴 70 后程序员从公司坠楼 ​​​​
  8. ubuntu终端字体大小调整方法
  9. 手工彻底清除各种顽固性 Trojan Horse 木马的方法
  10. springboot 环境配置测试环境和线上环境配置