在本教程中,您将学习如何在Unity中创建和使用脚本对象。 可编写脚本的对象可以帮助改善您的工作流程,减少内存占用,甚至允许您拆分代码体系结构。
根据
Unity文档,ScriptableObject是一个类代码,允许您在游戏中创建Scriptable Objects,以存储独立于脚本实例的大量共享数据。
在Unity中使用脚本对象的原因很多。 它们可以减少用于每个其他预制件的内存量,因为Scriptable Object本质上遵循
Flyweight设计模式。
可脚本化对象的另一个优点(将成为本教程的主题)是它们可用于方便的数据传输。 我们将以此属性为例,创建一个剑商人商店,该商店将显示各种剑的参数,价格和说明。
注意:本教程假定您熟悉Unity编辑器。 您必须了解如何在代码编辑器中编辑代码,并且具有基本的C#知识。 如果您需要提高Unity技能,请查看其他Unity教程 。
开始工作
让我们开始
下载所需的资料 。
将下载的文件解压缩到方便的位置,然后在Unity中打开
Scriptable Object Tutorial-Starter项目。
您应该看到在项目采购中创建了以下文件夹:
- _Setup :对于本教程而言,不需要此文件夹。
- 场景 :包含Sword Merchant场景,我们将在整个教程中进行介绍。 打开这个场景。
- 脚本 :到目前为止,只有一个脚本,但是在教程中,我们将创建一个新脚本。
- 剑图标 :包含各个剑的静止图像。
- Sword Prefabs :包含Sword Merchant场景中所有剑的预制件。
创建可编写脚本的对象
首先,请转到
Sword Merchant场景。 它看起来应该像这样:
准备脚本对象
现在该创建第一个可编写脚本的对象了!
在“
脚本”文件夹中,创建一个名为
SwordData的新脚本。 此类将用作剑商人商店中显示的所有剑数据的容器。
在此类内部,首先从
ScriptableObject
继承而不是
MonoBehaviour
:
public class SwordData : ScriptableObject { }
该动作告诉Unity,我们仍然希望像常规MonoBehaviour一样使用Unity的功能和方法,但是我们不再需要将此脚本附加到GameObject。 取而代之的是,它将像处理任何常规资产一样进行处理,可以像创建预制件,场景或材料一样进行创建。
用序列化字段填充脚本,其中将包含与Sword Merchant UI中显示的信息相对应的所有数据。
public class SwordData : ScriptableObject { [SerializeField] private string swordName; [SerializeField] private string description; [SerializeField] private Sprite icon; [SerializeField] private int goldCost; [SerializeField] private int attackDamage; }
- swordName :
string
,其中将存储剑的名称。 - description :
string
,将在其中存储剑的描述。 - icon :将包含剑图标的精灵。
- goldCost : 将剑的价值存储在黄金中的
int
。 - AttackDamage :用于存储用剑攻击时的伤害的
int
。
注意:SerializeField
在Unity中,SerializeField属性使您可以在Inspector中使用私有脚本变量。 它将允许您在编辑器中设置值,而无需提供其他脚本对变量的访问。
每把剑都将需要其自己的Scriptable Object
SwordData实现 。 但是在创建这些实现之前,我们需要向“资产”菜单添加一个可脚本编写的对象。
通过将以下属性添加到
SwordData类,将我们的脚本对象添加到资产菜单:
[CreateAssetMenu(fileName = "New SwordData", menuName = "Sword Data", order = 51)] public class SwordData : ScriptableObject
- fileName :创建资产时的默认名称。
- menuName :在资产菜单中显示的资产名称。
- order :资产菜单中的资产放置。 Unity将资产分为因子为50的子组。即,值51将新资产放置在Asset Menu的第二组中。
如果一切正确完成,则可以转到
Assets >> Create ,然后在菜单中查看新的
Sword Data资产。 它应该位于Folder资产下的第二组中:
您还可以在“项目”窗口中右键单击,还可以看到新的Sword Data资产:
新增资料
我们
将通过在Scripts文件夹中创建一个名为
Scriptable Objects的文件夹,并在该文件夹内创建一个名为
Sword Data的文件夹,来
组织项目。
在新创建的Sword Data文件夹中,创建我们的第一个Sword Data资产。
新的Sword Data资产仍应具有先前指定的默认名称
fileName 。 选择一种资产,然后将其复制六次(
Ctrl / Cmd + D ),以创建七个Sword Data资产,每个剑一个。 现在根据预制件重命名每个资产:
单击“ Sword数据”文件夹中的第一个
Sword数据资产,然后查看“
检查器”窗口:
在这里,我们看到一种资产,其中将存储有关特定剑的信息。 填写每把剑的信息。 尝试给他们一个独特的描述,攻击时的金钱价值和伤害。 在“图标精灵”字段中,使用“
剑图标”文件夹中的相应精灵:
恭喜你! 您创建了一个脚本对象,并使用此脚本对象配置了多个资产。
使用脚本对象
现在,我们将开始从这些可编写脚本的对象中获取数据。
首先,我们需要添加一些公共的getter方法,以便其他脚本可以访问Scriptable Object内部的私有字段。 打开
SwordData.cs并在之前添加的字段下添加以下内容:
public string SwordName { get { return swordName; } } public string Description { get { return description; } } public Sprite Icon { get { return icon; } } public int GoldCost { get { return goldCost; } } public int AttackDamage { get { return attackDamage; } }
打开
Sword.cs并添加以下代码:
[SerializeField] private SwordData swordData;
这是我们使用此代码添加的内容:
- 此剑数据的数据容器。
- OnMouseDown是内置的MonoBehaviour函数,当用户按下鼠标左键时会调用该函数。
- 如何从可脚本化对象资产中获取数据的示例
返回到Unity并转到“
层次结构”窗口。 在剑的预制中选择1_Longsword游戏对象。 将适当的1_Longsword Data资产添加到Inspector窗口中Sword.cs脚本的Sword Data变量中:
在Unity编辑器中单击“播放”(
Ctrl / Cmd + P ),然后单击最左边的剑:
控制台应显示类似于从Sword Data资产传输的数据的信息。
可编写脚本的对象使替换此数据变得容易。 尝试将不同的Sword Data可编写脚本的对象插入到剑的Sword Data字段中。
事件脚本对象
因此,我们创建了一个可脚本编写的对象,您了解了如何在游戏中访问其数据。 但是我们仍然需要将Sword Data与UI集成在一起!
您可以为此使用快速脏的
Singleton模式。 但是,我们现在还有其他可能性...
...即可编写脚本的对象! 我们将使用它们来创建干净整洁的代码。
在本节中,您将学习如何使用
UnityEvent类创建游戏事件。
游戏活动和听众
在“脚本”文件夹中,创建两个脚本:
GameEvent.cs和
GameEventListener.cs 。 它们彼此依赖,因此要消除错误,您需要同时创建两者。
using System.Collections.Generic; using UnityEngine; [CreateAssetMenu(fileName = "New Game Event", menuName = "Game Event", order = 52)]
这是上面的代码的作用:
- 将GameEvent作为资产添加到“资产”菜单。
- GameEvent是一个可编写脚本的对象,因此应从ScriptableObject继承。
- 要订阅GameEvent的GameEventListener的列表。
- 调用所有GameEvent订阅者的方法。
- 最后签名的GameEventListener将是第一个被调用的(后进先出)。
- 调用每个UnityEvent GameEventListeners。
- 一种允许GameEventListeners订阅此GameEvent的方法。
- 一种允许GameEventListener取消订阅此GameEvent的方法。
using UnityEngine; using UnityEngine.Events;
在上面显示的代码中,项目将继续开发:
- 使用UnityEvent类的要求。
- 此GameEventListener将订阅的GameEvent。
- GameEvent事件引发此GameEventListener时将引发的UnityEvent响应。
- 启用此GameObject后,将GameEvent绑定到GameEventListener。
- 禁用此GameObject时,从GameEventListener绑定GameEvent。
- 当生成GameEvent导致GameEventListener调用UnityEvent事件时调用。
有困难吗? 没什么,随着时间的推移您会发现!
编辑培训
返回Unity编辑器,并在脚本>> ScriptableObjects中创建一个新的
Game Events文件夹。 然后,像我们对每个Sword Data资产所做的那样,从Asset菜单创建七个Game Events。 将它们放在新的“游戏事件”文件夹中。
用以下几行替换
Sword.cs脚本中的代码:
[SerializeField] private GameEvent OnSwordSelected;
此代码为剑商人的商店增加了两种可能性:
- 选择剑时产生游戏事件。
- 单击剑时发生事件。
保存脚本。 现在,在剑的每个Hierarchy GameObject中,连接相应的OnSwordSelected事件。
现在,每把剑都有指向该事件的链接,该事件在单击该剑时触发。
UI整合
现在,您需要使UI工作。 我们的目标是在单击每把剑时显示相应的剑数据。
UI链接
在更新UI之前,您必须获得指向UI的每个元素的链接。 首先,创建一个名为
SwordMerchant.cs的新脚本,并将以下代码添加到该新脚本中:
using UnityEngine; using UnityEngine.UI; public class SwordMerchant : MonoBehaviour { [SerializeField] private Text swordName;
使用此代码,我们添加了以下内容:
- 对NameText游戏对象的Text组件的引用。
- 链接到DescriptionText游戏对象的Text组件。
- 链接到Sword_Icon游戏对象的“图像”组件。
- 链接到GoldText游戏对象的Text组件。
- 指向AttackText游戏对象的Text组件的链接。
上述游戏对象位于“层次结构”窗口的
SwordMerchantCanvas >> SwordMerchantPanel中 。 将脚本添加到
GameObject SwordMerchantCanvas ,然后配置所有链接:
侦听器和UI响应
所有剑都有一个事件,UI可以使用
GameEventListener脚本进行订阅。 为每个OnSwordSelected事件添加一个GameEventListener到
GameObject SwordMerchantCanvas :
如您所见,我们的Game Event Listener有两个字段:它侦听的Game Event事件,以及在生成Game Event时引发的响应。
在我们的情况下,响应将由UI更新。 将以下方法添加到
SwordMerchant.cs脚本中:
public void UpdateDisplayUI(SwordData swordData) { swordName.text = swordData.SwordName; description.text = swordData.Description; icon.sprite = swordData.Icon; goldCost.text = swordData.GoldCost.ToString(); attackDamage.text = swordData.AttackDamage.ToString(); }
此方法接收Sword Data资产,然后使用相应Sword Data字段的值更新每个UI字段。 请注意,
GoldCost和
AttackDamage返回一个
int
,因此您需要将其转换为文本字符串。
使用我们的新方法,我们可以向每个
GameEventListener添加响应。
对于您添加的每个响应,您都需要一个指向
SwordMerchantCanvas游戏对象的链接,作为
None(对象) 字段的值 。 之后,从“
仅运行时”下拉列表右侧的下拉菜单中选择
SwordMerchant.UpdateDisplayUI 。
请小心,并为每个
OnSwordSelected事件使用正确的Sword Data资源。
现在,我们可以开始游戏,单击剑,然后查看相应的UI更新!
由于我们使用游戏事件,因此您可以简单地使用
SwordMerchantCanvas ,并且
即使没有UI也可以正常运行。 这意味着剑的预制件与
SwordMerchantCanvas是分开的。
接下来要去哪里?
如果您在故事中错过任何内容,则可以
下载完成的项目 ,该
项目位于教程的材料中。
如果要继续前进,请尝试使每把剑重现自己的声音。 尝试扩展可编写脚本的对象剑数据并侦听
OnSwordSelected
事件。
想更多地了解Unity?
观看我们的Unity
视频系列或阅读
Unity教程 。