斯坦福UE4C++课程P59-P62控制台变量,游戏模式规则
首先我们在SGameModeBase添加OnActorKilled函数,加上virtual关键字以便子类能重写。
在attribute组件类ApplyHealthChange函数添加判断属性组件拥有者死亡的逻辑:
OnActorKilled函数:
我们以函数名RespawnPlayerElapsed设置定时器,函数RespawnPlayerElapsed:
仅仅是解除了controller和玩家角色的绑定,并且让controller和从playerstart重生的玩家绑定。
现在有UI上的bug,玩家死亡后重生,血条将不再更新,因为在beginplay时我们在角色类蓝图创建了血条控件,而血条控件的事件图表中,我们是用控件的construct来对血条百分比进行控制,在血条首次被创建时正常,但玩家重生时并不会重新创建血条。这时新玩家用的仍是上一个死亡玩家的血条控件。这个问题后面再解决。

下面我们学习用于调试和游戏平衡的控制台变量
我们在SGameModeBase.cpp添加
ECVF_Cheat表示在游戏打包时,该控制台变量将被忽略。
在SpawnBotTimerElapsed函数开头判断
表示如果该控制台变量被禁用,将不能够执行剩下的函数体,即不能生成Bot。
接着在属性组件类添加第二个控制台变量,表示给伤害乘以倍数(默认为1.0f):
在ApplyHealthChange函数添加:
表示只要拥有属性组件类的Actor受到伤害时都会乘上该值。这比较粗糙,但是一个好的开始,可以用来测试游戏中的伤害值是否合适。
最后一个控制台变量添加在SInteractionComponent,之前我们在这里添加了交互时的drawdebug的线和球(绿色表示交互成功,红色失败),这个功能之前必须在代码里通过注释掉drawdebug的语句才能开关。我们把它设置为控制台变量,在控制台开关,就方便多了:
现在打开控制台,输入su,会出现上面的三个控制台变量。
现在我们给伤害乘5,输入su.DamageMultiplier空格5,如果后面不加上伤害倍数值,将显示当前伤害倍数。

下面我们新建我们的第一个Blueprint Function Library,添加两个静态函数
tip:在C++中,如果ufunction函数的形参是引用(不是常引用),在蓝图中该函数节点将多出该形参的输入引脚。
SGameplayFunctionLibrary.h
SGameplayFunctionLibrary.cpp
在魔法球C++类,把之前OnActorOverlap添加伤害的语句换为:
现在编译,仍有一定问题,魔法球打到AI身上,实际上是和胶囊体组件发生重叠,进而触发伤害,但是胶囊体组件是没有办法模拟物理的,所以我们必须要让魔法球忽略掉胶囊体组件,和mesh进行重叠(mesh可以模拟物理,可以被ApplyDirectionDamage作用)。
在AI角色C++类构造函数添加
表示我们把胶囊体组件对WorldDynamic通道设置为忽略,把网格体组件设置为可以触发重叠事件。
现在,我们攻击AI,只要AI开启了模拟物理(我们设置了AI死亡时会开,活着没开),就会被魔法球施加冲量作用:

现在,AI死亡时,其身体(胶囊体)仍会阻挡玩家,我们设置当它死亡时,胶囊体设置为无碰撞。但这意味着地板不能与其碰撞了,所以同时我们设置AI不能动了:
在SAICharacterC++类NewHealth<=0死亡时:
另外,我们和宝箱、生命药水interact时,是以角色眼睛是否看向目标为标准的,这在第一人称视角游戏是很好的方法,但第三人称游戏以我们的十字准星方向看去为标准会好一点。所以我们在SCharacter类添加:
表示我们使用相机为视线出发点,而不是角色眼睛。
剩下的工作,我们把上帝模式时改成只能回血、不能掉血,所以在属性组件类ApplyHealthChange函数开头换成
最后,我们修复玩家死亡重生时,血条不被重新创建的问题。
新建playercontroller蓝图类PlayerControllerBP,把玩家角色蓝图beginplay时创建显示主HUD的节点移到PlayerControllerBP的beginplay节点后。在GameModeBP中选择Player Controller Class为PlayerControllerBP。
这没有解决掉问题,但比原来好一点。

最后是作业5:

首先新建继承自PlayerState的credits类,命名为SPlayerState:
这里需要了解Gameplay架构(GameMode、GameState、PlayerController等),其中可以了解到PlayerState可以根据玩家Controller获得。我们根据这一点来获取SPlayerState中的Credits。
SPlayerState.h
SPlayerState.cpp
在SGameModeBase类的OnActorKilled函数加上:
当玩家杀死AI时,才会给编号为0的玩家加上10分。
我们让Credits在UI实时更新,给分数绑定函数:

现在玩家杀死AI就会涨10分,玩家死亡、AI被AI杀死都不会涨分。
下面我们给Health Potion、Coins新建一个基类SPowerupBase,继承自AActor和ISGameplayInterface:
SPowerupBase.h
SPowerupBase.cpp
改写的Health Potion类:
新建SCoinPickUp类,与其交互可加Credits:
给coin新建蓝图类,分配mesh,放入场景中。现在与其交互,会增加20分(默认),且其被销毁。
最后我们用EQS让Coin和Health Potion在场景里随机生成。
这里可以借鉴之前随机生成AI的方法,即新建EQS找随机生成点,然后新建继承自EQSTestingPawn的蓝图类,EQS选择前者(纯粹方便查看随机生成点),然后在SGameModeBase中生成AI。
所以我们在SGameModeBase头文件添加:
在StartPlay函数中写生成逻辑:
OnCoinQueryCompleted函数和OnHealthPotionQueryCompleted函数分别生成硬币和生命药水:
现在存在问题,就是多个硬币/药水可能重叠在一个生成位置,后续找解决办法。
