• 游戏
  • 工业
  • 资源
  • 社区
  • 学习
  • 支持
开发
Unity 引擎
为任何平台构建2D和3D游戏
下载计划和定价
商业化
应用内购买(IAP)
发现并管理各商店的IAP
聚合平台
最大化收入并优化变现
Ad Quality
保护您应用的用户体验
Tapjoy
建立长期用户忠诚度
所有变现产品
用户获取
用户获取
被发现并获取移动用户
Unity向量AI
将玩家与合适的游戏连接
Aura设备内广告
在用户高峰参与时触达用户
所有增长产品
使用案例
3D协作
实时构建和审查3D项目
沉浸式培训
在沉浸式环境中培训
客户体验
创建互动3D体验
所有行业解决方案
行业
制造业
实现运营卓越
零售
将店内体验转化为在线体验
汽车
提升创新和车内体验
所有行业
技术库
文档
官方用户手册和API参考
开发者工具
发布版本和问题跟踪器
路线图
查看即将推出的功能
术语表
技术术语库
洞察
案例分析
真实成功案例
最佳实践指南
专家提示和技巧
所有资源
新增功能
博客
更新、信息和技术提示
新闻
新闻、故事和新闻中心
社区中心
讨论
讨论、解决问题和连接
事件
全球和本地活动
社区故事
Made with Unity
展示Unity创作者
直播活动
加入开发者、创作者和内部人员
Unity奖项
庆祝全球的Unity创作者
适合每个级别
Unity Learn
免费掌握Unity技能
专业培训
通过Unity培训师提升您的团队
Unity新手
准备开始
开始您的学习
Unity基础路径
你是Unity 新手?开始您的旅程
使用指南
可操作的技巧和最佳实践
教育
对于学生
开启您的职业生涯
对于教育者
增强您的教学
教育资助许可证
将Unity的力量带入您的机构
认证
证明您的Unity精通
支持选项
获取帮助
帮助您在Unity中取得成功
成功计划
通过专家支持更快实现目标
常见问题解答
常见问题解答
联系我们
与我们的团队联系
计划和定价
语言
  • English
  • Deutsch
  • 日本語
  • Français
  • Português
  • 中文
  • Español
  • Русский
  • 한국어
社交
货币
采购
  • 产品
  • Unity Ads
  • 订阅
  • Unity Asset Store
  • 经销商
教育
  • 学生
  • 教师
  • 机构
  • 认证
  • 学习
  • 技能发展计划
下载
  • Unity Hub
  • 下载存档
  • Beta 版测试
Unity Labs
  • 实验室
  • 作品
资源
  • 学习平台
  • 社区
  • 文档
  • Unity QA
  • 常见问题解答
  • 服务状态
  • 案例分析
  • Made with Unity
Unity
  • 我们公司
  • 新闻简报
  • 博客
  • 事件
  • 工作机会
  • 帮助
  • 新闻
  • 合作伙伴
  • 投资人
  • 附属机构
  • 安防
  • 社会影响力
  • 包容性与多样性
  • 联系我们
版权所有 © 2025 Unity Technologies
  • 法律
  • 隐私政策
  • Cookie
  • 不要出售或分享我的个人信息

“Unity”、Unity 徽标及其他 Unity 商标是 Unity Technologies 或其分支机构在美国及其他地区的商标或注册商标(单击此处获取更多信息)。其他名称或品牌是其各自所有者的商标。

Hero background image

使用 ScriptableObjects 作为委托对象

本页解释如何使用 ScriptableObjects 作为逻辑容器。通过这样做,您可以将它们视为委托对象,或者在需要时可以调用的小动作包。

这是六个迷你指南系列中的第四个,旨在帮助 Unity 开发人员使用电子书附带的 演示 “ 使用 ScriptableObjects 在 Unity 中创建模块化游戏架构”。

该演示的灵感来自经典的球和桨街机游戏机制,并展示了 ScriptableObjects 如何帮助您创建可测试、可扩展且设计人员友好的组件。

电子书、演示项目和这些迷你指南共同提供了在 Unity 项目中使用 ScriptableObject 类的 编程设计模式 的最佳实践。这些技巧可以帮助您简化代码,减少内存使用,并提高代码的可重用性。

本系列包括以下文章:

  • 开始使用 Unity ScriptableObjects 演示
  • 使用 ScriptableObjects 分离游戏数据和逻辑
  • 在 Unity 项目中使用基于 ScriptableObject 的枚举
  • 在游戏代码中使用 ScriptableObjects 作为事件通道
  • 如何使用基于 ScriptableObject 的运行时集
  • 开始前的重要说明
  • 策略模式
  • 可插入行为
  • 示例:AudioDelegate
  • 模式演示
  • 示例:目标体系中的战略模式
  • 更多 ScriptableObject 资源

开始前的重要说明

在深入研究 ScriptableObject 演示项目和本系列迷你指南之前,请记住,设计模式本质上只是想法而已。它们并不适用于所有情况。这些技术可以帮助您学习使用 Unity 和 ScriptableObjects 的新方法。

每种模式都有优点和缺点。仅选择那些对您的特定项目有意义的内容。您的设计师是否严重依赖 Unity 编辑器?基于 ScriptableObject 的模式可能是帮助他们与开发人员合作的一个好选择。

最终,最好的代码架构是适合您的项目和团队的架构。

脚本对象
SCRIPTABLEOBJECT 包含 MONOBEHAVIOUR 内的“策略”。

策略模式

使用 策略模式,您可以定义一个接口或基 ScriptableObject 类,然后使这些委托对象在运行时可互换。

一种应用是将执行特定任务的算法封装到ScriptableObject中,然后在其他上下文中使用该ScriptableObject。

例如,如果您正在为 EnemyUnit 类编写 AI 或寻路系统,则您可能会创建具有路径搜索技术(如 A*、Dijkstra 等)的 ScriptableObject。

EnemyUnit 本身实际上并不包含任何寻路逻辑。相反,它会保留对单独的“策略”ScriptableObject 的引用。这种设计的结果是,您只需交换对象就可以切换到不同的算法。这是在运行时选择不同行为的一种方法。

当 MonoBehaviour 需要执行任务时,它会调用 ScriptableObject 上的外部方法而不是自己的方法。例如,ScriptableObject 可能包含 MoveUnit 或 SetTarget 的 公共方法,用于驱动敌方单位并指定目的地。

下载 PaddleBallSO

可插入行为

您可以使用抽象基类或接口来改进这种模式。这样做意味着任何实现该策略的 ScriptableObject 都可以与另一个进行交换。这个可热插拔的 ScriptableObject “插入”到引用它的 MonoBehaviour 中 – 即使在运行时也是如此。

如果需要 EnemyUnit 根据游戏条件改变行为,外部环境(MonoBehaviour)可以检查这些条件。然后,它可以插入不同的 ScriptableObject 作为响应。

通过将实施细节分离到 ScriptableObject 中,您还可以促进团队之间更好地划分责任。一位开发人员可以专注于 ScriptableObject 内部的算法,而另一位开发人员则致力于 MonoBehaviour 上下文。

要创建此可插入行为,请确保:

  • 为该策略定义一个基类或接口:该类或接口应该包括执行策略所需的方法和属性。
  • 创建 ScriptableObject 类:每个都可以提供该策略的不同实现。例如,您可以创建一个实现简单 AI 算法的类和另一个实现更复杂算法的类。
  • 创建一个实现该策略的 ScriptableObject:填写缺失的逻辑并使用任何必要的值填充 Inspector。
  • 在上下文中使用该策略:在MonoBehaviour中,调用ScriptableObject中实现的方法和属性。为了更容易地调用这些方法,将依赖项作为参数传入。

像这样组织代码可以更轻松地在同一策略的不同实现之间切换。这种可插入行为变得更容易调试和维护。

示例:AudioDelegate

算法或策略不必太复杂。例如,PaddleBallSO 项目演示了 SimpleAudioDelegate 中相当基本的音频播放系统。

抽象类 AudioDelegateSO定义了一个接受 AudioSource 参数的 Play 方法。然后具体实现会覆盖它。

SimpleAudioDelegateSO 子类定义了一个 AudioClips 数组。它选择一个随机剪辑并使用重写的 Play 方法实现播放它。这会在自定义范围内添加音调和音量的变化。

虽然只有几行,但您可以使用下面的代码片段制作许多不同的音频效果。

虽然这个特定的例子并不真正适合大量音频使用,但它在这里作为策略模式中 ScriptableObjects 的基本使用演示进行展示。

设计师可以创建许多不同的 ScriptableObject 来表现声音效果,而无需接触代码。再次,一旦基础 ScriptableObject 完成,这只需要开发人员提供最少的支持。

在 PaddleBallSO中,任何人现在都可以设置一组新的声音,当球击中关卡墙壁时播放这些声音。设计师获得了创作的独立性和灵活性,因为他们完全在编辑器中工作。这种方法释放了编程资源,因为开发人员不再需要协助做出每个设计决策。

下载 PaddleBallSO
委托对象
AUDIODELEGATES 演示场景展示了 SCRIPTABLEOBJECTS 如何保存逻辑。

模式演示

您还可以在 Patterns 演示中看到音频示例。每个声音都来自略有不同的 SimpleAudioDelegateSO 资源,实例之间有细微的差异。

在这个例子中,每个角落都包括一个 AudioSource。自定义 AudioModifier MonoBehaviour 使用基于 ScriptableObject 的委托来播放声音。

音调的差异仅源于每个 ScriptableObject 资源上的设置(BeepHighPitched_SO、BeepLo​​wPitched_SO 等)。

使用 ScriptableObject 来控制动作逻辑可以让您的设计团队更轻松地尝试各种想法。这使得设计师能够更加独立于开发人员工作。

目标经理
OBJECTIVEMANAGER MONOBEHAVIOUR 使用 SCRIPTABLEOBJECTS 测试胜利条件。

示例:目标体系中的战略模式

PaddleBallSO 项目也在其目标系统中使用了策略模式。虽然这不是需要在运行时改变的东西,但将每个对象封装在 ScriptableObject 中提供了一种灵活的方式来测试胜负条件。

抽象基类 ObjectiveSO 保存诸如目标名称和是否已完成之类的值。

然后,具体的子类(如 ScoreObjectiveSO)实现如何完成每个目标的实际逻辑。他们通过覆盖 ObjectiveSO 的 CompleteObjective 方法并添加胜利条件逻辑来实现这一点。

玩家是否需要达到特定的分数或击败一定数量的敌人?他们是否需要到达特定地点或领取特定物品?这些是可以成为基于 ScriptableObject 的目标的常见获胜条件。

ObjectiveManager 是 ScriptableObjects 的更大背景。它维护一个 ObjectiveSO 列表并依赖每个 ScriptableObject 来确定它是否完整。当每个ObjectiveSO显示完成状态时,游戏就结束。

例如,ScoreObjectiveSO 展示了实现评分目标的一种方法:

  • 自定义的 PlayerScore 结构与玩家 ID、界面中的 UI 元素和实际得分值相匹配。
  • 每次 ScoreManager 组件更新时,目标都会检查获胜条件。
  • 如果玩家的得分达到或超过 m_TargetScore,那么它会将获胜的 PlayerScore 对象作为事件发送。

ObjectiveManager 仅关心所有给定的目标是否完成。它并不知道每个目标本身的细节。

再次强调,这里的目标是模块化。这使您可以自定义每个 ObjectiveSO,而不会影响预先存在的 ObjectiveSO。

PaddleBallSO 游戏实际上只有一个目标。如果其中一名玩家达到了获胜分数目标,游戏就结束。

但是,您可以扩展它或组合目标来创建更复杂的目标系统。进行试验,看看是否可以构建新的游戏模式(例如,在时间耗尽之前获得最低数量的分数)。

由于逻辑被封装在 ScriptableObject 中,因此您可以将任何 ObjectiveSO 交换为另一个。制定新的胜利条件只需重新配置 ObjectiveManager 中的列表。从某种意义上来说,目标是可以“插入”到周围环境中的。

请注意,ObjectiveSO 的一个方便的方面是用于在 GameObjects 之间发送消息的事件。接下来,我们将探讨如何使用 ScriptableObjects 来实现这种事件驱动的架构。

下载 PaddleBallSO
可编写脚本的结局

更多 ScriptableObject 资源

在电子书 《使用 ScriptableObjects 在 Unity 中创建模块化游戏架构》中了解有关使用 ScriptableObjects 的设计模式的更多信息。您还可以在 使用游戏编程模式提升您的代码水平中了解有关常见 Unity 开发设计模式的更多信息。

您喜欢本文吗?

是的!

继续发送

还行。

有待改进