背包系统03:数据库存储方法ScriptableObject

利用ScriptableObject实现数据持久化

Monobehavior:每次重新打开游戏时,数据都会初始化为一开始的状态,而不会保存上一次游玩的数据。
ScriptableObject可以保存数据(在本地),即实现存档。而且它无需挂载在任何节点上,就可以生效。

本节课的内容

  1. 创建管理物品的脚本Item
  2. 创建管理背包的脚本Inventory(因为除了主角,npc也会有背包)
  3. 创建管理场景中物品的脚本ItemOnWorld,当角色碰到场景中的item,将该item的数据存入背包

Step1

增加菜单栏的选项,代码如下:

[CreateAssetMenu(fileName ="New Item",menuName ="Inventory/New Item")]

filename指的是文件的默认名称,menuname则是菜单栏中显示的选项名。

在Unity中,右键,就可以看见菜单栏中多了一项:
在这里插入图片描述

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 itemImage;//物品图片
    public int itemHeld;//物品数量
    [TextArea]
    public string itemInfo;//详细信息
}

现在创建一把剑,
在这里插入图片描述
inspector中就可以设置参数:(如果后续想增加参数,修改脚本即可)
在这里插入图片描述
小知识点:[TextArea]即显示一段文字区域。
在这里插入图片描述
若没有[TextArea],是这样的:
在这里插入图片描述

Step2

现在创建Inventory的脚本,希望它是一个列表,将所有的物品都存在该列表中。这样就可以利用这个脚本创建不同角色的背包。

Inventory代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(fileName = "New Inventory", menuName = "Inventory/New Inventory")]
public class Inventory : ScriptableObject
{
    public List<Item> itemList = new List<Item>();
}

创建一个玩家的背包:
在这里插入图片描述
首先,我们设置背包中默认的物品是1把剑:
在这里插入图片描述
注意:这里的Size指的是种类的多少(即占据了多少格子)。

Step3

接下来,在场景中放上这把剑。当游戏角色碰到剑时,能识别到剑在数据库里的信息,并将它保存进背包中。
对于场景中放置好的物体,我们需要知道两个信息:(1)它属于数据库里的哪个item(2)该物体应该存入哪个背包
脚本如下:

public class ItemOnWorld : MonoBehaviour
{
    public Item thisItem;
    public Inventory playerInventory;
}

场景中放置剑:
在这里插入图片描述

public class ItemOnWorld : MonoBehaviour
{
    public Item thisItem;
    public Inventory playerInventory;

    private void OnTriggerEnter2D(Collider2D other)
    {
        if(other.gameObject.CompareTag("Player"))
        {
            AddNewItem();
            Destroy(gameobject);
        }
    }

    void AddNewItem()
    {
        //如果背包中没有该物品,添加
        if(!playerInventory.itemList.Contains(thisItem))
        {
            playerInventory.itemList.Add(thisItem);
        }
        //反之,增加物品数量
        else
        {
            thisItem.itemHeld += 1;
        }
    }
}

注意:compareTag里的Player要首字母大小!否则会出现报错:
在这里插入图片描述
这里不要写成Destroy(this)!

脚本拖给场景中的剑:
在这里插入图片描述

运行游戏

当角色吃掉场景中的剑时,可以看见数量增加。
在这里插入图片描述

【评论区大佬】
首先感谢Up主辛苦制作了这么多精品视频,但是对于ScriptableObject,UP主的讲解有些问题,我来解释一下:
1、游戏数据根据可变性分成两种:不可变数据和可变数据,前者主要对应于配置数据(也就是策划配表,比如视频中的Item的名字、描述),而后者就是玩家的自身数据(比如视频中Item的数量)
2、这两者在(商业化)游戏开发中是要独立开来的,最好不要混在一起,以视频为例,玩家真正存盘时,实际上只存储物品Id和数量。至于物品名称、描述,都是在表格中的,不需要处理。
3、ScriptObject这个东西有这么个特点:1、如果使用Editor运行,那么Editor运行期的变化会被保持下来(也即持久化);2、而一旦版本发布后(也即安装到设备上),运行期的变化时不会被保存的!!!(官方原文:如果使用 Editor,可以在编辑时和运行时将数据保存到 ScriptableObjects,因为 ScriptableObjects 使用 Editor 命名空间和 Editor 脚本。但是,在已部署的构建中,不能使用 ScriptableObjects 来保存数据,但可以使用在开发期间设置的 ScriptableObject 资源中保存的数据。 从 Editor 工具作为资源保存到 ScriptableObjects 的数据将写入磁盘,因此将在会话之间一直保留。可以看官方文档:https://docs.unity3d.com/cn/current/Manual/class-ScriptableObject.html)

一句话总结:ScriptObject不能这么直接使用,因为它在Edtor期间会修改本来不应该去修改的“不可变数据”;而在部署构建期间又没有做本职工作,去持久化应该去改变的“可变数据”。

所以,就本视频来说,按照上述第2/3条的观念,首先需要把Item进行拆分,例如:ItemConfig和ItemData(也即配表和玩家数据),前者作为不可变数据(可以使用ScriptableObject),后者作为可变数据进行持久化(当然仍然可以使用ScriptableObject,但是需要额外去持久化操作)

好了,下一步就是让增加的数量显示在背包中就好啦!

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值