在这一篇里,我们将制作一个范围魔法,释放魔法时,我们将在鼠标拾取位置绘制一个魔法光圈,用于显示技能释放时攻击的范围,然后再次点击可以释放技能。
创建贴花类
魔法范围标识的光圈,我们采用贴花实现,首先我们创建一个类,用于作为这种类型的贴花的基类,贴花是组件对象,我们需要创建一个基于Actor的类,用于挂载贴花组件。
命名
在类里增加一个贴花组件
UCLASS()
class RPG_API AMagicCircle : public AActor
{GENERATED_BODY()public: AMagicCircle();virtual void Tick(float DeltaTime) override;//魔法光环法阵贴花UPROPERTY(VisibleAnywhere, BlueprintReadOnly)TObjectPtr<UDecalComponent> MagicCircleDecal;
protected:virtual void BeginPlay() override;
};
在构造函数里,初始化贴花,并附加到根组件上
AMagicCircle::AMagicCircle()
{PrimaryActorTick.bCanEverTick = true;MagicCircleDecal = CreateDefaultSubobject<UDecalComponent>("MagicCircleDecal");MagicCircleDecal->SetupAttachment(GetRootComponent());
}
编译代码,创建一个基于贴花类的蓝图
在贴花组件上设置贴花材质
我们可以设置贴花组件范围缩放,来设置贴花的显示范围,注意,贴花会基于x轴的方向贴到表面,所以,如果想让贴花贴到地面,我们需要x轴垂直到地面。
将其放置到场景内查看效果。
实现贴花的显示隐藏以及跟随鼠标移动
接下来,我们要实现贴花的显示隐藏,由于贴花需要跟随鼠标移动,鼠标移动拾取是在PlayerController里实现的,我们将其实例放到PlayerController类里。
在PlayerController里,我们增加两个属性,用于设置贴花的类,并在需要显示时,设置保存贴花实例的属性,并增加一个更新贴花位置的函数,在帧回调里调用。
//创建奥数光圈使用的类UPROPERTY(EditDefaultsOnly)TSubclassOf<AMagicCircle> MagicCircleClass;//存储魔法光圈的属性,不需要暴露给蓝图UPROPERTY()TObjectPtr<AMagicCircle> MagicCircle;void UpdateMagicCircleLocation() const; //每一帧调用,更新魔法光圈的位置
增加两个public函数,用于玩家角色类调用显示和隐藏贴花
//显示魔法光圈 并设置光圈贴花材质UFUNCTION(BlueprintCallable)void ShowMagicCircle(UMaterialInterface* DecalMaterial);//隐藏魔法光圈UFUNCTION(BlueprintCallable)void HideMagicCircle() const;
在显示贴花时,我们将在实例不存在的情况下创建一个,并修改它的材质。
在隐藏时,我们将贴花销毁掉。
void ARPGPlayerController::ShowMagicCircle(UMaterialInterface* DecalMaterial)
{if(!IsValid(MagicCircle)) MagicCircle = GetWorld()->SpawnActor<AMagicCircle>(MagicCircleClass);//设置贴花材质if(DecalMaterial != nullptr){MagicCircle->MagicCircleDecal->SetMaterial(0, DecalMaterial);}
}void ARPGPlayerController::HideMagicCircle() const
{if(IsValid(MagicCircle)) MagicCircle->Destroy();
}
接着就是更新贴图的位置,如果贴花实例存在,我们将鼠标拾取的位置设置给贴花
void ARPGPlayerController::UpdateMagicCircleLocation() const
{if(IsValid(MagicCircle)){MagicCircle->SetActorLocation(CursorHit.ImpactPoint);}
}
并在每一帧更新里去调用更新贴花位置
接下来,我们在PlayerController里设置贴花的类
在playerController里编写一些测试节点,测试贴花是否能够正确显示隐藏
接着运行测试效果
我们想让贴花能够自动旋转,先在贴花里,将组件设置为蓝图可视
然后在贴花类里的帧回调设置基于x轴旋转,每一帧修改,贴花会自己旋转起来。
这个贴花的显示隐藏不应该是PlayerController的功能,所以,我们将在玩家角色类增加对应的函数。为了方便后续调用,我们将其作为角色接口的函数,后面只需要通过接口调用即可。
我们在player interface里增加两个函数,用于显示和隐藏贴花
//显示魔法光圈,并设置魔法光圈的贴花材质UFUNCTION(BlueprintNativeEvent, BlueprintCallable)void ShowMagicCircle(UMaterialInterface* DecalMaterial = nullptr);//隐藏魔法光圈UFUNCTION(BlueprintNativeEvent, BlueprintCallable)void HideMagicCircle();
玩家角色类继承PlayerInterface接口,我们直接覆写
virtual void ShowMagicCircle_Implementation(UMaterialInterface* DecalMaterial) override;virtual void HideMagicCircle_Implementation() override;
并实现对应的函数,函数内获取到PlayerController并调用对应的函数
void ARPGHero::ShowMagicCircle_Implementation(UMaterialInterface* DecalMaterial)
{if(ARPGPlayerController* RPGPlayerController = Cast<ARPGPlayerController>(GetController())){RPGPlayerController->ShowMagicCircle(DecalMaterial);}
}void ARPGHero::HideMagicCircle_Implementation()
{if(ARPGPlayerController* RPGPlayerController = Cast<ARPGPlayerController>(GetController())){RPGPlayerController->HideMagicCircle();}
}
将PlayerController里的测试节点删除,在玩家角色蓝图里增加使用接口函数调用,并修改一个贴花测试修改材质的函数。
我们设置一个新的贴花,并将颜色修改掉,运行查看效果即可。