书接上回,在上一篇博客里,我们实现了角色升级的基础的功能。给敌人增加的经验奖励配置,并且在敌人死亡时,能够将经验通过事件传递给击杀者,玩家定义了被动技能,在被动技能中接收传递的事件,通过SetByCaller的GE应用给自身。并在AttributeSet中打印出获得的经验。
我们还修改了PlayerState,在内部增加了对经验和等级添改查的,并创建对应的委托,在UI的Controller里面,实现了对委托的监听,并实现回调函数,通过经验获取等级和升级进度广播给UI表现出来。
创建玩家接口类
有了之前制作的内容,我们接下来,将实现玩家在AS里获取到经验后,设置的PlayerState上,这里防止耦合度太高,我们选择创建一个新的接口实现此功能。
新添加一个接口类
作为玩家专用的命名为PlayerInterface ,除了它我们还有CombateInterface(战斗接口)EnemyInterface(敌人接口)
在接口类里,我们增加一个增加经验的函数
在玩家角色类继承此接口
并覆写此函数
在实现这里,获取到PlayerState,并调用PlayerState身上的增加经验的函数
最后在AS里,我们通过调用此函数实现经验增长
在UI上实现对经验变动监听
现在,玩家角色可以获得经验,并通过接口设置给PlayerState,然后广播给UI的控制器了。我们要先将之前创建的升级数据设置给PlayerState
在WBP_Overlay里面,给经验条设置控制器
在经验条的事件中,设置控制器回调中,绑定对经验变动的监听,在变动时,获取经验条的百分比
接下来可以测试了,发现上一篇文章里面,在最后类型转换时,需要提前转换将一个数值转换为浮点数类型 ,浮点数/整型 结果就可以是浮点型,要不然,整型除以整型结果还是整型,获取的结果为0
接着,你就会发现经验条随着怪物死亡,增长了一丝
然后测试杀死两只,给的经验是否一致
重构战斗接口中的获取等级函数
我们想将之前书写的获取等级的函数修改成可以在蓝图定义的,达到结构统一,所以,需要额外修改一些内容
修改后编译会发现一些报错
按照之前方式,将其名称后续加上_Implementation即可
接下来编译,会发现还有一些额外报错,这是因为调用的地方没有修改
我们可以通过双击shift键,打开搜索,找到调用的地方依次修改。
找到需要修改的地方,将代码修改成以下类型。注意:Implements后面的类型是以U开头的接口,它是UE增加的,而调用的时候是I开头是c++内置的接口调用方式。
增加角色接口函数
为了实现接下来角色升级的功能,我们扩展角色接口的函数
接下来,我们在继承接口的玩家角色类里面覆写函数
除了已经实现的添加经验的函数,我们将其它函数依次实现。
首先是升级函数,这个函数主要用于提供角色升级时,播放一下升级表现效果,因为当前类是在服务器运行的,我们要实现一个在每个客户端都可以运行的效果,就需要增加一个可以在多端运行的函数,这个在稍微讲解。
接下来是获取当前角色经验值
通过经验值获取当前等级
获取当前等级奖级的属性点
获取当前等级奖励的技能点
设置当前角色升级,主要是修改角色的数值
还有在后续章节中添加的属性修改功能函数,为角色增加属性点和技能点
实现等级升级
接下来,我们在AS里面获得经验后,处理升级相关逻辑。
首先判断是否升级,逻辑是当前经验+获得的经验是否能够升级,获取到增加经验后的等级和原来的等级是否一致,如果增加了,意味着角色等级得到了提升。
在升级逻辑里面,我们首先获取当前等级提供的属性点和技能点的奖励
然后提升角色等级,并应用奖励
调用升级表现函数
升级时,将血量和蓝量填满
下面列出来完整代码
在ui上面显示等级
我们现在角色有了等级,需要在UI上面表现出来。
我们首先处理回调,之前实现了经验的表现,我们在PlayerState类里面设置和升级时,会调用委托广播
那么,我们在UI Controller里面添加一个委托,用于广播给UI监听,等级为整型参数
接着创建对应类型的变量
绑定一个匿名函数,用于监听PlayerState的等级回调
接下来,我们基于WBP_SpellGlobe复制一份,创建一个用于显示等级的ui
将使用图标设置的部分删除,我们不需要在等级显示UI里面设置图标
在设置控制器回调里面监听等级委托,回调触发修改等级显示文字
为了方便设置,我们可以修改对应怪物提供的经验值
将其拖入到WBP_Overlay上面,并设置对应控制器
接下来,我们就可以运行查看效果
创建角色图标
接下来,我们想在左上角显示对应角色的图标,这里使用WBP_GlobeProgressbar作为模版复制一份
命名为WBP_PictureFrame
移动到对应的文件夹中
删除一些无用的函数
增加一个用于显示头像的节点
设置对应头像
在WBP_Overlay里面应用,并设置好位置
设置升级效果
接下来,我们将上面略过的等级升级效果函数实现一下,我们需要增加一个粒子特效在升级时播放特效。由于特效是平面播放,它会跟随角色的角度,有时候看到是一个竖条的,所以我们还需要将相机在代码里创建,方便后续获取相机的旋转。
我们首先在代码里创建相机和弹簧臂
在初始化时创建它们
然后创建一个NiagaraComponent,用于设置使用的粒子特效,它需要在蓝图中设置使用的粒子资源
在构造函数中初始化,并将自动播放关闭,我们在角色升级的时候让其播放
我们还需要创建一个支持多客户端调用的函数,它将在每个客户端都实现调用,这样,在每个客户端都能看到同样的效果
在实现这里,我们将通过相机和粒子位置的朝向,注意,这个朝向是世界坐标系的,然后通过朝向获取旋转,设置给粒子
并在AS调用函数时,调用此函数,因为AS只在服务器运行,再调用此函数,实现了每个客户端的运行
接着编译打开UE,设置粒子特效
并将之前在蓝图中创建的相机和弹簧臂删除掉,将之前的碰撞盒移动到代码创建的弹簧臂上面
删除蓝图创建的相机和弹簧臂
运行查看效果。
创建升级消息提示
接下来,我们优化效果,在升级时提供消息提示UI,并播放音效。
父类选择我们自定义的RPGUserWidget
命名为WBP_LevelUpMessage 为升级提示
我们在里面添加一个覆层,作为全屏显示,并在覆层下面添加一个包裹框,文字超出范围后会自动换行
为了防止文字在最顶部显示,我们在上面添加一个间隔区,用来填充空间,宽度设置的尽量大一些,防止文字在间隔区后面显示。
增加一个文本,设置好样式,让其可以占用一整行
下面添加一个水平框,框内设置两个文本,显示等级和实际等级数字
水平框设置对其和填充空间以及强制换新行,文本向左向右对其,这样,就可以居中显示
实际效果如下
我们也可以用上下设置垂直框,这样更方便设置
接着,我们要在WBP_Overlay里面在设置了控制器后,监听等级的变动,在监听到等级变化后,将现存的等级提示删除,然后接着创建一个新的控件,并将目标等级设置,并添加到视口。这样可以防止连续升级时,多层覆盖的问题。
运行查看效果。
接下来,我们优化一下,制作一个动画
在事件开始后,播放音效和动画,并延迟三秒将UI销毁
接下来查看最终效果