斯坦福UE4 + C++课程学习记录 19:黑洞技能

目录

1. 代码结构更改

2. 实现黑洞粒子


        这节将会完成课程设置的第二次作业之一 —— 实现角色的黑洞技能,即发出一个特殊的黑洞粒子,该粒子会吸引周围的物体。

1. 代码结构更改

        随着课程内容的深入,我们将会添加的技能会越来越多,单纯在SurCharacter.cpp里不断添加新代码会使结构变得愈发臃肿。为了后续开发的可扩展性,需要重构技能部分的代码。

        因为Gideon这个角色的技能都是从右手发出不同的粒子,那从右手发出这个功能的代码是可以复用的。因此把这部分代码单独封装,只需要传入需要生成的类即可。于是,在SurCharacter中加入一个负责生成粒子的函数SpawnProjectile(记得在.h文件中声明):

void ASurCharacter::SpawnProjectile(TSubclassOf<AActor> ClassToSpawn)
{
	if (ensureAlways(ClassToSpawn)) {

        // 此前PrimaryAttack_TimeElapsed中的内容,省略。。。

		// 生成传入的类
		GetWorld()->SpawnActor<AActor>(ClassToSpawn, SpawnTM, SpawnParams);
	}

}

        相应的,此前PrimaryAttack_TimeElapsed函数就保留一行代码:

void ASurCharacter::PrimaryAttack_TimeElapsed() {
	SpawnProjectile(ProjectileClass);
}

        保存编译测试,运行正常后就可以继续进行黑洞技能的内容。


2. 实现黑洞粒子

        首先,复制一份之前PrimaryAttack的代码,把名字改成BlackHoleAttack和BlackHoleAttack_TimeElapsed。在SetupPlayerInputComponent添加后,再在UE里绑定任意按键。运行测试,若角色能正常发射之前的魔法粒子则可继续,接下来就需要将生成的粒子改更为黑洞粒子。

        参考我们第5节第一次实现发射粒子的做法,在SurCharacter.h中新建一个子类并暴露在蓝图中,然后在BlackHoleAttack_TimeElapsed传入我们创建的子类名字:

// SurCharacter.h
UPROPERTY(EditAnywhere, Category = "Attack")
TSubclassOf<AActor> BlackHoleProjectileClass;

// SurCharacter.cpp
void ASurCharacter::BlackHoleAttack_TimeElapsed() {
	SpawnProjectile(BlackHoleProjectileClass);
}

        随后就打开UE,在Player的蓝图编辑器中找到Attack属性下的BlackHoleProjectileClass,暂时把它设置为已有的普攻魔法粒子MagicProjectile,编译保存并运行测试。

图19-1 设置发射的粒子

        现在只要实现黑洞粒子的蓝图类,并替换掉上面的属性就大功告成了。

        课程中考虑到接下来还要实现几个不同的粒子,所以先创建一个基类来复用一些共有的代码内容。在UE中从Actor派生一个SurProjectileBase类,使用ABSTRACT宏将该类声明为"抽象基类",使其不显示在UE的下拉窗中,防止我们在关卡中添加此类的Actor(不理解这种做法的朋友,可以自行搜索编程中抽象类的作用,如C++的虚基类、python中的抽象类等等)。然后在构造函数中添加一些基本的组件(.h也需要声明相应内容,这一点在后续文章就不再提醒了),完整代码见第0节github的个人项目地址。

// ASurProjectileBase.cpp
ASurProjectileBase::ASurProjectileBase()
{
	SphereComp = CreateDefaultSubobject<USphereComponent>("SphereComp");
	SphereComp->SetCollisionProfileName("Projectile");
	RootComponent = SphereComp;

	MoveComp = CreateDefaultSubobject<UProjectileMovementComponent>("ProjectileMoveComp");
	MoveComp->bRotationFollowsVelocity = true;
	MoveComp->bInitialVelocityInLocalSpace = true;
	MoveComp->ProjectileGravityScale = 0.0f;
	MoveComp->InitialSpeed = 500;

	EffectComp = CreateDefaultSubobject<UParticleSystemComponent>("EffectComp");
	EffectComp->SetupAttachment(RootComponent);

}

        接下来换到UE中,由于黑洞的功能较为简单,所以仅使用UE就很容易实现。在UE中创建黑洞的蓝图类Proj_BlackHole,继承自SurProjectileBase。

        打开蓝图编辑器,再添加Physics中的径向力组件RadialForce,这个组件可以实现在一个范围内产生力。在属性“径向力组件”中设置“要影响的对象”,点击右边小三角形将Pawn删除,这样就不会把我们自己吸进去。然后,设置其半径为500,设置“力”属性为-2,000,000。

        另外,我们不希望这个黑洞在移动时会被物体阻挡,所以选择SphereComp,切换其碰撞预设为Custom,并设置如下:

图19-2 碰撞预设

        由于这是一个有时间限制的技能,因此我们选择Proj_Base(自身),设置Actor属性的“初始生命周期”为5秒,即要添加动画的时长。

        最后,选择EffectComp,为这个粒子选择一个模板。由于我实在没找到课程中的同款粒子模板,课程中老师也没有选中EffectComp展示,从老师github下载的项目文件又无法打开,现阶段对动画也不太熟悉,只好在Gideon的文件里选择了一个看起来比较接近的模板P_Portal_Entrance_Close_Undertow,并通过反复测试,设置其自定义时间膨胀为0.2以匹配动画时长。

        设置完成后,将Player的BlackHoleProjectileClass设置为Proj_BlackHole。最后运行的效果如下:

图19-3 运行效果

        此外,课程中还在Proj_BlackHole的蓝图中添加了销毁碰到的、启用了“模拟物理”的物体(没有启用“模拟物理”,一般是不与技能交互的静态物体),大家可以尝试添加查看效果:

图19-4 销毁物体

        最后,你可以任意调节黑洞的模型动画、发射速度、力场半径、力的大小等等属性,来实现任何你想要的技能效果。

猜你喜欢

转载自blog.csdn.net/surkea/article/details/127388715