TwinStickShooter模板应该是比较好的了解UE基本Pawn和Projectile的一个C++例子。以下是一些问题。
一、这个模板以纯C++编写,没有蓝图,所以第一步,我想测试下如何引用蓝图,以修改子弹的外观为例。
- 从ATwinStickShooterProjectile派生蓝图类,称为BP_TwinStickShooterProjectile好了,然后在BP_TwinStickShooterProjectile中修改子弹的颜色(材质了),改为红色。那么纯粹的C++如何引用并产生蓝图的实例呢?
这样实现:在pawn类中添加 TSubclassOf<ATwinStickShooterProjectile> ProjectileTemplate 成员变量,加不加UPROPERTY均可,因为我们将引用资源,资源是客观存在的,不是我们动态产生的,不会GC。然后在对应的实现文件(.cpp)的构造函数中,添加如下代码:
//设置子弹蓝图的引用
ConstructorHelpers::FClassFinder<ATwinStickShooterProjectile> AssetProjectile(TEXT("Blueprint'/Game/Blueprints/BP_TwinStickShooterProjectile.BP_TwinStickShooterProjectile_C'"));
if (AssetProjectile.Succeeded())
{
ProjectileTemplate = AssetProjectile.Class;
}
特别注意字符串后面添加"_C",即:Blueprint'/Game/Blueprints/BP_TwinStickShooterProjectile.BP_TwinStickShooterProjectile_C。这个字符串直接在编辑器中点选子弹对应的蓝图,然后copy reference,粘贴到对应的位置,然后添加后缀_C。因为这是蓝图类,后面都应该有后缀,话说UE版本号都15.1了,怎么还这个德性?
在FireShot函数中,如下修改:
UWorld* const World = GetWorld(); if (World != NULL) { // spawn the projectile //World->SpawnActor<ATwinStickShooterProjectile>(SpawnLocation, FireRotation); // 产生蓝图子弹 World->SpawnActor<ATwinStickShooterProjectile>(ProjectileTemplate, SpawnLocation, FireRotation); }
桔色是原来模板的,注释掉,然后添加红色代码,编译,可以观察到的确生成了自定义的子弹。
其中pawn类的tick函数值得研究,例如在输入绑定时,如果BindAxis,无论是否有输入,系统就回调自己的函数,BindAction则不存在这个问题。这个例子给出了一个较好的解决方案,只绑定名称,不绑定回调函数,这样我们在需要的时候,自己调用GetInputAxis,这两种实现各有千秋,只是后一种是传统的方式,比较熟悉。
未完待续,卡壳了……
继续。
UProjectileMovementComponent有几个属性很好玩,如下:
如果设置bIsHomingProjectile = true; 生成子弹的Actor后,设置HomingTargetComponet,则子弹将以HomingTargetComponent为目标,实现跟踪效果。。。当然,还得设置UProjectileMovementComponent的HomingAccelerationMagnitude,这个值决定加速度,,犀利!
在子弹的构造函数中如下添加代码:
// 添加测试代码 ProjectileMovement->bIsHomingProjectile = true; ProjectileMovement->HomingAccelerationMagnitude = 2500;
在Pawn的开火函数中如下添加代码:
if (World != NULL)
{
// spawn the projectile
//World->SpawnActor<ATwinStickShooterProjectile>(SpawnLocation, FireRotation);
// 产生蓝图子弹
ATwinStickShooterProjectile* Projectile = World->SpawnActor<ATwinStickShooterProjectile>(ProjectileTemplate, SpawnLocation, FireRotation);
//添加HomingTargetComponent
if (TargetHome)
{
Projectile->GetProjectileMovement()->HomingTargetComponent = TargetHome->GetRootComponent();
}
}
红色的为添加的代码,当然在测试时,要在collision中把子弹与pawn和子弹之前的响应设置为ignore,要不然,子弹产生的太快,彼此会碰撞,并且开户追踪后,子弹会击中玩家自己,效果不好,选择ignore就ok了。效果图:
nice! 有空再扒扒UMovementComponent中的碰撞的实现。