【unity】基于命令模式的剧情系统

前言

回想某次项目,我负责一个剧情模块的搭建。当时才疏学浅,只会用链式结构绑定每个UI对象,这种做法非常费事而且耦合过高。现在我的这个系统也算是给当年一个交代吧,以后有类似的需求也可以直接拿过来用。

系统简介

这是一个能够在Unity中运行的,基于命令模式的剧情系统,支持自定义命令,编辑剧情数据,查看历史对话等。

该系统旨在提高对于游戏剧情的开发效率,同时遵循开闭原则,以确保扩展性良好。

仓库地址->https://github.com/AshScops/Dialogue-style-plot-system

各个类的职责

CommandConfig:继承自ScriptableObject。它用于存储一系列命令对象。

CommandBase:一个抽象类。它作为所有命令的基类,声明了三种抽象方法:

  1. Execute :在该命令对象出队后立刻被调用,且只调用一次。
  2. OnUpdate :在Execute 后每帧被调用,直到返回true
  3. IsFinished:返回值类型为bool,在该命令对象执行完毕时返回true,未执行完则返回false

CommandSender:一个单例,包含一个命令队列。它将从外部传入的CommandConfig中获取一系列命令对象并入队,按队列顺序执行各个命令。

PlotUISettings:一个单例,负责在进入和退出剧情时,对某些参数进行设置和清理;同时对外暴露界面的像素大小、打字效果的速度等可供用户调整的参数。

PlotModule:一个单例,用于存放各个Event,并对外提供各类方法,专门负责来自模块外的交互。

以下是各个命令类,均继承自CommandBase

类名 可自定义的字段 该命令何时结束 注释
HEADER 章节名、该段剧情是否可跳过 立刻 负责进入剧情时的补间动画
Background 背景图片 立刻
Delay 需要等待的时间 等待自定义时间后
Dialogue 说话者的名字、说话的内容 打字效果结束且用户点击后
Character 说话者的图片 立刻 最多支持显示两个立绘
Decision 用户可选择的对话选项 用户选择一个对话选项后 最多支持五个剧情选项
Predicate 标志位,作为用户所选项对应的命令段的首位 立刻 最多支持五个剧情选项
END 标志位,作为整个剧情的出口 永不 负责退出剧情时的补间动画

如何使用

初始化、开始和结束

plot_module.PlotModule是专门供外部调用方法的类。

该系统初始化,仅需全局调用一次plot_command_executor.PlotModule.Instance.PlotInit(GameObject ui_prefab))即可,界面会持久存在。

该类还提供了两个UnityEvent

plot_module.PlotModule.Instance.plotBegin;
plot_module.PlotModule.Instance.plotEnd;

当你想进入某段剧情时,首先确保已经初始化了,并且通过SetPlotConfig设置好了剧情配置文件。然后调用plotBegin即可开始剧情。

当你想在剧情结束时执行某些回调,你可以向plotEnd注册它们,在剧情界面完全退出后会自动调用。

获取玩家的选择

PlotModule中提供了GetPlayerDecisions方法,返回一个List<int>,第i位上的数x意为玩家在第i次选择了第X个选项(均从0开始)。你可以在剧情结束后的任意时间获取它,它总是返回最近一次发生剧情的抉择。

配置剧情文件

HEADER,负责配置章节标题,同时在代码中负责进入剧情时的补间动画。

Background,负责配置剧情界面最底部的背景图片。注意:图片要放在Asset/Resource文件夹下,暂时不能自定义存放路径,这个以后改进。

Delay,等待自定义时间。由于补间动画的命令是立刻执行完的,而补间动画需要一定时间播放,由此产生的时间差就由它来填补。你也可以选择在合适的位置加入或不加入此命令,以实现对应效果。

Dialogue,没什么好说的。唯一要注意的是:人名和文本不要太长,人名在15个汉字以内,文本大概在70个汉字左右,不然会溢出屏幕。

Character,在两个立绘都不为空时,要使用focus字段来选择高亮显示哪个立绘。注意:图片要放在Asset/Resource文件夹下,暂时不能自定义存放路径,这个以后改进。

Decision,文本不要太长,在15个汉字以内即可,太长了后面的文字会被隐藏。

Predicate,拦截Decision的选择。一旦玩家选择了某选项,则会使命令队列不断出队,直至检测到出队的元素为对应选项的Predicate或是PredicateEnd。也正是这个原因,该系统暂时不支持循环式的选择。这一点可能以后改进。

END,意味着整个剧情的结束。一段剧情可以有多个END出口。

尾声

显然,这个系统还不够完善,比如:没有和镜头控制、屏幕效果、音频播放相关的命令,不支持循环式对话,没有对抉择进行细分等。但时间紧迫,短期内不会再对这个系统进行修改了。

posted @ 2023-02-01 21:23  AshScops  阅读(637)  评论(1编辑  收藏  举报