在上一篇里,我们编辑完成了技能的UI面板。按照MVC的思路,我们还需要制作它的控制器,用于处理UI上面的交互。
到现在为止,我们控制器已经有了三种,首先是我们创建的控制器基类RPGWidgetController.h,为所有控制器需要继承的类,里面有一些公用的函数和属性。通过基类我们实现三种控制器:
- 用于显示在战斗场景界面的UI的控制器OverlayWidgetController.h,主要显示角色等级血量技能等的状态
- 用于展现角色属性面板的UI的控制器AttributeMenuWidgetController.h,主要用于显示角色属性值和属性加点功能
- 还有我们在这篇文章里要创建的技能面板的UI的控制器SpellMenuWidgetController.h,用于设置玩家的技能等级,技能键位等操作。
我们接下来,会先创建技能面板控制器,然后整理代码,讲通用的部分整理到基类里,并优化一些功能。
创建技能面板控制器
我们基于控制器基类创建一个新的控制器子类
然后在类里继承覆写基类的两个函数,它们分别为初始化广播数据,用于在创建时,显示角色当前的信息,另一个是在属性变动时的委托广播。
并且我们要设置标识,让其可以作为蓝图中转换的类和蓝图继承的类
Hud类里添加设置技能面板控制器
我们是在自定义的HUD里面设置UI的蓝图类,并有配置项去配置使用的控制器,我们接着讲技能面板的控制器添加进去。
按照之前,我们首先创建两个属性,一个用于设置使用的技能面板控制器类,一个用于存储类的实例,防止多次创建
然后我们增加一个用于获取技能面板控制器的函数
在实现时,首先判断当前是否被实例过,如果实例过直接返回,没有则实例一次
创建获取RPG类型的变量
随着子类增多,我们每次切换类型去获取自定义的ASC PS PC AS的次数增多,还影响代码阅读,所以,我们在控制器基类增加对自定义的类型的获取。
首先,我们增加四个变量,用于存储对应的类型
然后,我们增加四个函数,用于获取自定义的参数
然后就是函数实现,在实现函数里,我们首先判断当前的变量是否设置的值,如果没有,那么将类型转换,并返回
转换完成后,编译,发现子类使用的一些变量名称出现的冲突
我们在子类里面可以将转换类型的内容删除,并直接调用函数获取
将技能应用的广播修改到基类
由于技能的更新在UOverlayWidgetController里面和USpellMenuWidgetController里面都需要应用,所以我们将属性对应内容的委托函数移动到基类里
首先,我们将委托定义移动到基类
将技能表格数据定义也设置到基类
然后将委托变量移动到基类,并创建一个绑定委托的函数
然后将实现内容移动到函数中
在OverlayWidgetController.cpp里面,我们修改绑定函数
由于技能绑定我们函数不需要传入ASC,所以,我们在自定义ASC里,将返回一个参数取消,并修改对应参数
在蓝图函数库增加获取控制器函数
和获取其它函数一致,我们增加一个函数用于获取技能面板控制器
实现也和其它函数一致
在这里,你会发现这几个获取控制器的代码的重复度很高,基本都是为了获取到对应的数据以后,通过HUD函数来获取对应的控制器,接下来,我们将简化代码,将相同的部分修改为一个通用的函数。
通用函数需要获取到两项内容,HUD对象和创建控制器所需的FWidgetControllerParams 参数,所以,我们创建一个函数用于返回FWidgetControllerParams参数,并在参数里返回HUD。
这个函数,返回一个布尔类型,用于判断参数是否获取成功,并传入了所需值的地址引用,可以修改它的地址,将外部的值修改掉。
这里注意我们设置的元数据,meta=(DefaultToSelf = "WorldContextObject")
,这样即使我们不设置它,也会有默认值就是自身
在实现这里,我们还是同样的获取参数,去修改传入的参数
接着,我们将其它获取控制器的函数都修改掉
我们修改参数
创建蓝图
我们编译打开UE,在UE里创建一个基于技能面板的控制器蓝图,用于设置参数
将资产设置上去
打开HUD蓝图,设置使用的技能面板控制器类
在技能面板UI里面,我们获取一下控制器,发现不需要再设置世界空间了
我们技能面板UI的事件里面设置控制器,并打印名称,查看是否能够正确获取到
如果能正确打印名称,证明没有问题