Ue4C++编程------武器Actor与c++(二)

    在上一文中,我们讲述了如何创建一个武器,并将武器装备到人物的手上,接下来我们要讲述的就是如何为武器actor添加碰撞事件,使我们在挥刀的时候,能够产生伤害。

    首先在weaponactor类里添加成员,如下所示:

	UPROPERTY(EditAnywhere, Category = Collision)
	class UBoxComponent* WeaponCollision;
FORCEINLINE class UBoxComponent* GetWeaponCollision() { return WeaponCollision; }

    使用UPROPERTY,并置为EditAnywhere的原因,就是让我们能在编辑器中以可视化的方式调整碰撞体的大小,使之能刚好与我们的剑适配。接下来我们在构造函数中,使用CreateSubObject创建该碰撞体,并将其设置为NOCollision,关闭碰撞的原因是,我们想让我们的人物做出挥刀的动作时,再开启碰撞。如下所示:

	WeaponCollision = CreateDefaultSubobject<UBoxComponent>(TEXT("WeaponCollision"));
	if (WeaponCollision != nullptr)
	{
		WeaponCollision->SetCollisionEnabled(ECollisionEnabled::NoCollision);
	}

    接下来就要为我们的碰撞体绑定函数,使我们的碰撞体在碰撞到物体,比如敌人时,产生回调,通知我们砍到了敌人,然后再产生伤害。首先定义类成员函数,如下所示:

	UFUNCTION()
	void OnHit(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

    现在暂时不实现该函数,只是打印下日志,如下所示:

void AWeaponActor::OnHit(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	UE_LOG(LogTemp, Warning, TEXT("OnHit"));
}

    在beginplay函数中,绑定碰撞体的回调函数,如下所示:

void AWeaponActor::BeginPlay()
{
	Super::BeginPlay();
	if (WeaponCollision != nullptr)
	{
		WeaponCollision->OnComponentBeginOverlap.AddDynamic(this, &AWeaponActor::OnHit);
	}
}

    接着编译我们的代码,然后在编辑器中,调整碰撞体的大小及长款之类的,在weaponactor中,右键,选择创建蓝图,如下图所示:

    

    然后打开我们创建的武器蓝图,调整我们的boxcollison的大小,如下图所示:

    

    既然我们有了武器蓝图类,那我们在spawn武器的actor时,便可以使用这个蓝图类作为我们的模板来创建武器,当然,我们也可以查看boxcollision的transform,然后在代码中设置,这里我采用第一种方案,就是使用蓝图类模板来创建武器,因此需要修改我们的character类,首先在character类中添加成员TSubclassOf<AWeaponActor> WeaponM,如下:

TSubclassOf<class AWeaponActor> WeaponM;

    接着在character构造函数中,使用constructhelpers找到该类,如下:

	static ConstructorHelpers::FClassFinder<AWeaponActor> WeaponBP(TEXT("/Game/ThirdPersonCPP/Blueprints/WeaponActorBP"));
	if (WeaponBP.Succeeded())
	{
		WeaponM = WeaponBP.Class;
	}

    接着在beginplay中,修改我们的创建方式,如下所示:

void ABlogProjectCharacter::BeginPlay()
{
	Super::BeginPlay(); // 记得一定先调父类的函数
	//武器的添加
	//Weapon = GetWorld()->SpawnActor<AWeaponActor>(AWeaponActor::StaticClass()); // 之前的创建方式
	Weapon = GetWorld()->SpawnActor<AWeaponActor>(WeaponM->StaticClass());
	if (Weapon != nullptr)
	{
		// 附加武器,保持位置
		Weapon->GetWeaponMesh()->AttachToComponent(GetMesh(), FAttachmentTransformRules::KeepRelativeTransform, TEXT("weapon"));
	}
}

    测试如下:

    

     但是,我发现OnHit函数不是每次都触发,经谷歌,才知道,人物在跑动的时候,碰撞检测只会检测rootcomponnet,因此,attach是不行的。所以修改如下:

void ABlogProjectCharacter::BeginPlay()
{
	Super::BeginPlay(); // 记得一定先调父类的函数
	//武器的添加
	//Weapon = GetWorld()->SpawnActor<AWeaponActor>(AWeaponActor::StaticClass()); // 之前的创建方式
	Weapon = GetWorld()->SpawnActor<AWeaponActor>(WeaponM);
	//if (Weapon != nullptr)
	//{
	//	// 附加武器,保持位置
	//	Weapon->GetWeaponMesh()->AttachToComponent(GetMesh(), FAttachmentTransformRules::KeepRelativeTransform, TEXT("weapon"));
	//}
}
void ABlogProjectCharacter::Tick(float DeltaSeconds)
{
	Super::Tick(DeltaSeconds);
	if (Weapon != nullptr)
	{
		FVector Location;
		FQuat Rotation;
		GetMesh()->GetSocketWorldLocationAndRotation(TEXT("weapon"), Location, Rotation);
		Weapon->SetActorLocation(Location);
		Weapon->SetActorRotation(Rotation);
		Weapon->GetWeaponMesh()->SetWorldLocationAndRotation(Location, Rotation);
	}
}


    


猜你喜欢

转载自blog.csdn.net/li2818/article/details/80751996