前回は、装備している武器を取り外すと、デタッチした武器は落下せずにそのまま空中に浮いている状態でしたが、今回は、デタッチした武器が地面に落下するようにしたいと思います。それを達成するためには、武器ステータスと武器プロパティの設定をして、落下時の武器の物理と重力を有効にする必要があります。
enumで武器の状態を設定
武器のステータス、装着中、未装備(装備待ち)、あるいは落下中を設定しておくと後々何かと便利なので、今回はenumを使って武器のステータスの設定を行いたいと思います。ここでは、武器の未装備状態をpick-up(拾える状態)とし、装備済みをequipped、落下中をfallingとしています。Weapon.hにenumを使って武器の状態を定義します。ここでは装備前の状態をPickUp、装備後をEquippedとしています。
#include "Weapon.generated.h" UENUM(BlueprintType) enum class EWeaponState : uint8 { EWS_PickUp UMETA(DisplayName = 'Pick_up'), EWS_Equipped UMETA(DisplayName = 'Equipped'), EWS_Falling UMETA(DisplayName = 'Falling'), EWS_MAX UMETA(DisplayName = 'DefaultMax') };
Weapon.hにWeaponStateのゲッターとセッターを記述します。
EWeaponState WeaponState; FORCEINLINE void SetWeaponState(EWeaponState State) { WeaponState = State; } FORCEINLINE EWeaponState GetWeaponState()const { return WeaponState; }
Weapon.cppにWeaponStateのデフォルト値を設定します。
AWeapon::AWeapon() : WeaponState(EWeaponState::EWS_PickUp),
これでenumを使った武器ステートの設定は終わりです。
武器に物理アセットを追加する
武器をデタッチした時に落下するようにメッシュに物理アセットを追加します。先ず、Weapon_BPを開いてItem Meshを選択します。
スケルタルメッシュの虫眼鏡マークを押してメッシュのあるフォルダーに移動します。
武器のメッシュを右クリックして作成する→物理アセット→作成を選択します。
Primitive TypeにBoxを選択します。
武器に物理アセットを追加することで武器を落下させることができるようになりました。
武器ステートのプロパティを設定する
武器ステートのプロパティを設定しておかないと、例えば、武器が落下中なのに落下しないといった不具合が生じてしまいます。ですので、以下のように記述して、武器のステート毎にプロパティを設定しておく必要があります。先ず、Item.hにAreaSpaceのgetterを追加します。
FORCEINLINE USphereComponent* GetAreaSpace() const { return AreaSpace; }
次に、Weapon.cppにヘッダーファイルを追加します。
#include "Components/SphereComponent.h"
Weapon.hのprotectedセクションに関数を宣言します。
virtual void SetWeaponProperties(EWeaponState State);
この時、宣言した関数の横に出現するペンマークを押すと関数定義のひな型を自動作成してくれます。覚えておくと非常に便利です。
作成されたら閉じるを押してWeapon.cppに移ります。
Weapon.cppにSetWeaponProperties関数の定義を記述します。
void AWeapon::SetWeaponProperties(EWeaponState State) { switch (State) { case EWeaponState::EWS_PickUp: GetItemMesh()->SetSimulatePhysics(false); GetItemMesh()->SetEnableGravity(false); GetItemMesh()->SetVisibility(true); GetItemMesh()->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore); GetItemMesh()->SetCollisionEnabled(ECollisionEnabled::NoCollision); GetAreaSphere()->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Overlap); GetAreaSphere()->SetCollisionEnabled(ECollisionEnabled::QueryOnly); break; case EWeaponState::EWS_Equipped: GetItemMesh()->SetSimulatePhysics(false); GetItemMesh()->SetEnableGravity(false); GetItemMesh()->SetVisibility(true); GetItemMesh()->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore); GetItemMesh()->SetCollisionEnabled(ECollisionEnabled::NoCollision); GetAreaSphere()->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore); GetAreaSphere()->SetCollisionEnabled(ECollisionEnabled::NoCollision); break; case EWeaponState::EWS_Falling: GetItemMesh()->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics); GetItemMesh()->SetSimulatePhysics(true); GetItemMesh()->SetEnableGravity(true); GetItemMesh()->SetVisibility(true); GetItemMesh()->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore); GetItemMesh()->SetCollisionResponseToChannel( ECollisionChannel::ECC_WorldStatic, ECollisionResponse::ECR_Block); GetAreaSphere()->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore); GetAreaSphere()->SetCollisionEnabled(ECollisionEnabled::NoCollision); break; } }
武器ステートの設定
Weapon.hのSetWeaponStateをsetterから関数に変更します。
void SetWeaponState(EWeaponState State);
Weapon.cppにSetWeaponState関数を定義します。
WeaponState = State; SetWeaponProperties(State);
Weapon.cppのBeginPlay関数にSetWeaponPropertiesを追加します。
SetWeaponProperties(WeaponState);
MyCharacter.cppのEquip関数を以下のように書き換えます。
void AMyCharacter::EquipWeapon(AWeapon* WeaponToEquip) { if (WeaponToEquip) { const USkeletalMeshSocket* HandSocket = GetMesh()->GetSocketByName( FName("RightHandSocket")); if (HandSocket) { HandSocket->AttachActor(WeaponToEquip, GetMesh()); } EquippedWeapon = WeaponToEquip; EquippedWeapon->SetWeaponState(EWeaponState::EWS_Equipped); EquippedWeapon->ParticleEffects(); } }
MyCharacter.cppのDropWeapon関数に武器ステートの落下を追加します。
void AMyCharacter::DropWeapon() { if (EquippedWeapon) { FDetachmentTransformRules DetachmentTransformRules(EDetachmentRule::KeepWorld, true); EquippedWeapon->GetItemMesh()->DetachFromComponent(DetachmentTransformRules); EquippedWeapon->SetWeaponmState(EWeaponState::EWS_Falling); } }
コンポーネントのItem meshを選択、詳細の検索窓にPhysics Asset Overrideと入力します。
Physics Asset Overrideで先程追加した物理アセットを選択します。
これで、Xボタンで武器を装備して、Yボタンでデタッチすると、武器が地面に落下します。
コメント