今天來製作第二個魔法攻擊:追蹤彈,使用UE5的 Projectile Movement Component 來製作
Blueprint 或 C++ 都可以加 Porjectile Component,但我這裡用 C++ 來做投射物的 Base。
ProjectileBase.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/ProjectileMovementComponent.h"
#include "ProjectileBase.generated.h"
UCLASS()
class ITHOME30DAYS_API AProjectileBase : public AActor
{
GENERATED_BODY()
public:
AProjectileBase();
virtual void BeginPlay() override;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Movement")
UProjectileMovementComponent* ProjectileComp;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Projectile Settings")
float InitialSpeed = 300.f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Projectile Settings")
float MaxSpeed = 800.f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Projectile Settings")
float ProjectileGravityScale = 0.f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Projectile Settings")
bool bIsHoming = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Projectile Settings")
bool bRotationFollowVelocity = bIsHoming;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Projectile Settings")
float HomingAccelerationMagnitude = 2000.f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Projectile Settings")
USceneComponent* HomingTarget = nullptr;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Projectile Settings")
float Damage = 5.f;
};
ProjectileBase.cpp
#include "ProjectileBase.h"
AProjectileBase::AProjectileBase()
{
PrimaryActorTick.bCanEverTick = true;
// 預先創建 Projectile Component
ProjectileComp = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("ProjectileComp"));
}
void AProjectileBase::BeginPlay()
{
Super::BeginPlay();
ProjectileComp->InitialSpeed = InitialSpeed;
ProjectileComp->MaxSpeed = MaxSpeed;
ProjectileComp->ProjectileGravityScale = ProjectileGravityScale;
ProjectileComp->bIsHomingProjectile = bIsHoming;
ProjectileComp->bRotationFollowsVelocity = bRotationFollowVelocity;
ProjectileComp->HomingAccelerationMagnitude = HomingAccelerationMagnitude;
}
在敵人身上 加一個 Scene Component (HomingTarget)作為導彈目標,因為 Projectile Component 的 Homing Target 只接收 "Component" 而非 FVector Location
跟之前創建武器一樣,創建 Blueprint 時選擇 ProjectileBase 作為 Parent。
MagicWeapon.h
UPROPERTY(EditAnywhere, Category = "Weapon")
TArray<TSubclassOf<AActor>> Magics = {};
// 還有加一個攻擊函式
UFUNCTION()
virtual void BookMagicProj();
MagicWeapon.cpp
void AMagicWeapon::BookMagicProj()
{
if (!Magics[1]) return;
// 從魔法書發射
const FVector Loc = OwnerChar->GetMesh()->GetSocketLocation(AttachSocketName);
AActor* ProjActor = GetWorld()->SpawnActor<AActor>(Magics[1], Loc, (OwnerChar->TargetActor != nullptr) ? FRotator(90,0,0) : OwnerChar->GetActorRotation());
if (AProjectileBase* Projectile = Cast<AProjectileBase>(ProjActor))
{
Projectile->Damage = Damage*1.5;
if (OwnerChar->TargetActor != nullptr)
{
Projectile->bIsHoming = true;
USceneComponent* HomingPoint = Cast<USceneComponent>(OwnerChar->TargetActor->GetDefaultSubobjectByName(TEXT("HomingTarget")));
Projectile->ProjectileComp->HomingTargetComponent = HomingPoint ? HomingPoint : OwnerChar->TargetActor->GetRootComponent();
}
else
{
Projectile->bIsHoming = false;
}
}
}
然後就