Unreal Engine:装備変更(ライフルを持たせる)

現在まで武器として刀と手榴弾を作成しましたが、やはり銃がないと始まらないということで、キャラクターに銃を装備させたいと思います。銃を装備した後に刀や手榴弾と武器のスワップをできるようにもしています。ただ、このままだと単純に銃を持っているだけなので、今後の課題として、銃を持った時のポーズの設定をする必要があります。

スポンサーリンク

武器クラスを作成する

Itemクラスを親クラスにしてGunクラスを新たに作成します。

ファイル名はここではGunにしています。

Gun.hに幾つかの関数を宣言します。

public:

	AGun();

protected:

	virtual void BeginPlay() override;
	
	float ThrowGunTime;
	bool bFalling;
	void StopFalling();

public:

	virtual void Tick(float DeltaTime) override;

	virtual void OnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) override;

	virtual void OnOverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex) override;

	void ThrowGun();

Gun.cppにヘッダーファイルを追加します。

#include "MyCharacter.h"

変数のデフォルト値を設定して関数の定義を記述します。

AGun::AGun()
{
	ThrowGunTime = 1.0f;
	bFalling = false;
}

void AGun::BeginPlay()
{
	Super::BeginPlay();
}

void AGun::ThrowGun()
{
	FRotator MeshRotation{ GetItemMesh()->GetComponentRotation().Pitch, GetItemMesh()->GetComponentRotation().Yaw, GetItemMesh()->GetComponentRotation().Roll };
	GetItemMesh()->SetWorldRotation(MeshRotation, false, nullptr, ETeleportType::TeleportPhysics);

	const FVector MeshForward{ GetItemMesh()->GetForwardVector() };
	const FVector MeshRight{ GetItemMesh()->GetRightVector() };
	// Direction in which we throw the Weapon
	FVector ImpulseDirection = MeshRight.RotateAngleAxis(60.f, MeshForward);

	float RandomRotation{ 30.f };
	ImpulseDirection = ImpulseDirection.RotateAngleAxis(RandomRotation, FVector(0.f, 1.f, 1.f));
	ImpulseDirection *= 4000.f;
	GetItemMesh()->AddImpulse(ImpulseDirection);

	bFalling = true;
	FTimerHandle TimerHandle;
	GetWorldTimerManager().SetTimer(
		TimerHandle,
		this,
		&AGun::StopFalling,
		ThrowGunTime);
}

void AGun::StopFalling()
{
	bFalling = false;
	SetItemState(EItemState::EIS_Pickup);
}

void AGun::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
}

void AGun::OnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	Super::OnOverlapBegin(OverlappedComponent, OtherActor, OtherComp, OtherBodyIndex, bFromSweep, SweepResult);

	if (OtherActor && GetItemState() == EItemState::EIS_Pickup)
	{
		AMyCharacter* MyChar = Cast<AMyCharacter>(OtherActor);
		if (MyChar)
		{
			MyChar->SetOverlappingItem(this);
		}
	}
}

void AGun::OnOverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
	Super::OnOverlapEnd(OverlappedComponent, OtherActor, OtherComp, OtherBodyIndex);

	if (OtherActor)
	{
		AMyCharacter* MyChar = Cast<AMyCharacter>(OtherActor);
		if (MyChar)
		{
			MyChar->SetOverlappingItem(nullptr);
		}
	}
}

MyCharacter.hに関数と変数を幾つか宣言します。

void EquipGun(class AGun* GunToEquip);

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Weapon)
AGun* EquippedGun;

void SwapGun(AGun* GunToSwap);

MyCharacter.cppにヘッダーファイルを追加します。

#include "Gun.h"

関数の定義を記述します。

void AMyCharacter::EquipGun(AGun* GunToEquip)
{
	if (GunToEquip)
	{
		const USkeletalMeshSocket* HandSocket = GetMesh()->GetSocketByName(
			FName("RightHandSocket"));
		if (HandSocket)
		{
			HandSocket->AttachActor(GunToEquip, GetMesh());
		}
		EquippedGun = GunToEquip;
		EquippedGun->SetItemState(EItemState::EIS_Equipped);
	}
}

void AMyCharacter::SwapGun(AGun* GunToSwap)
{
	if (GunToSwap)
	{
		DropWeapon();
		EquipGun(GunToSwap);
	}
}

Equipping関数を書き換えます。

void AMyCharacter::Equipping()
{	
	if (EquippedWeapon == nullptr && EquippedGrenade == nullptr && EquippedGun == nullptr)
	{
		if (OverlappingItem)
		{
			AWeapon* Weapon = Cast<AWeapon>(OverlappingItem);
			AGrenade* Grenade = Cast<AGrenade>(OverlappingItem);
			AGun* Gun = Cast<AGun>(OverlappingItem);
			if (Weapon)
			{
				EquipWeapon(Weapon);
				SetOverlappingItem(nullptr);
			}
			else if (Grenade)
			{
				EquipGrenade(Grenade);
				SetOverlappingItem(nullptr);
			}
			else if (Gun)
			{
				EquipGun(Gun);
				SetOverlappingItem(nullptr);
			}
		}
	}
	else if (EquippedWeapon != nullptr || EquippedGrenade != nullptr || EquippedGun != nullptr)
	{
		if (OverlappingItem)
		{
			AWeapon* Weapon = Cast<AWeapon>(OverlappingItem);
			AGrenade* Grenade = Cast<AGrenade>(OverlappingItem);
			AGun* Gun = Cast<AGun>(OverlappingItem);
			if (Weapon)
			{
				SwapWeapon(Weapon);				
				SetOverlappingItem(nullptr);
			}
			else if (Grenade)
			{
				SwapGrenade(Grenade);
				SetOverlappingItem(nullptr);
			}
			else if (Gun)
			{
				SwapGun(Gun);
				SetOverlappingItem(nullptr);
			}
		}
	}	
}

DropWeapon関数を書き換えます。

void AMyCharacter::DropWeapon()
{
	if (EquippedWeapon != nullptr && EquippedGun == nullptr && EquippedGrenade == nullptr) 
	{
		FDetachmentTransformRules DetachmentTransformRules(EDetachmentRule::KeepWorld, true);
		EquippedWeapon->GetItemMesh()->DetachFromComponent(DetachmentTransformRules);
		EquippedWeapon->SetWeaponState(EWeaponState::EWS_Falling);
		EquippedWeapon->ThrowWeapon();
		EquippedWeapon = nullptr;
	}
	else if (EquippedWeapon == nullptr && EquippedGun == nullptr && EquippedGrenade != nullptr)
	{
		FDetachmentTransformRules DetachmentTransformRules(EDetachmentRule::KeepWorld, true);
		EquippedGrenade->GetItemMesh()->DetachFromComponent(DetachmentTransformRules);
		EquippedGrenade->SetItemState(EItemState::EIS_Falling);
		EquippedGrenade->ThrowGrenade();
		EquippedGrenade = nullptr;
	}
	else if (EquippedWeapon == nullptr && EquippedGun != nullptr && EquippedGrenade == nullptr)
	{
		FDetachmentTransformRules DetachmentTransformRules(EDetachmentRule::KeepWorld, true);
		EquippedGun->GetItemMesh()->DetachFromComponent(DetachmentTransformRules);
		EquippedGun->SetItemState(EItemState::EIS_Falling);
		EquippedGun->ThrowGun();
		EquippedGun = nullptr;
	}
}

GPYPressed関数を書き換えます。

void AMyCharacter::GPYPressed()
{
	if (EquippedWeapon == nullptr && EquippedGrenade == nullptr && EquippedGun == nullptr) return;
	DropWeapon();
}
スポンサーリンク

銃ブループリントの作成

Gunクラスをベースにブループリントを作成します。

作成フォルダにBlueprintフォルダを指定します。名前はここではGnu_BPにしています。

スケルタルメッシュはここではSK_AR4_Xにしています。

Physics Asset Overrideにはこのアセットの物理を選択します。

これで銃の脱着・他の武器とのスワップができるようになります。

スポンサーリンク
スポンサーリンク

コメント

タイトルとURLをコピーしました