Playerの作成
射撃:弾丸を発射する
ヒット処理とダメージ通知の実装です。
ダメージを通知するコンポーネントとそれを受け取るコンポーネントを作成します。
AttakDamageBase.hの追加
全文。
/**
* @file AttakDamageBase.h
* @brief 攻撃とダメージ
* - UDamageComponent ダメージを受信するコンポーネントるコンポーネント
* - UHitComponent ダメージを通知す
* @author inuvatico
* @date 2020/11/21
* @version 1.0
* @copyright 2020 inuvatico
* Released under the MIT license.
* see https://opensource.org/licenses/MIT
* @par (new/Add/Change : 2020/10/17)
*
*/
#pragma once
#include "CoreMinimal.h"
#include "Components/SphereComponent.h"
#include "AttakDamageBase.generated.h"
//---------------------------------------------------------------------
//! グループ
//---------------------------------------------------------------------
UENUM(BlueprintType)
enum class UAttackGroup : uint8 {
GP_Non UMETA(DisplayName = "GP_Non"),
GP_A UMETA(DisplayName = "GP_A"),
GP_B UMETA(DisplayName = "GP_B"),
GP_C UMETA(DisplayName = "GP_C"),
GP_D UMETA(DisplayName = "GP_D"),
};
//---------------------------------------------------------------------
//! ダメージを受信するコンポーネント
//---------------------------------------------------------------------
UCLASS(ClassGroup = "Collision", editinlinenew, hidecategories = (Object, LOD, Lighting, TextureStreaming), meta = (DisplayName = "UDamageComponent", BlueprintSpawnableComponent))
class UDamageComponent : public UActorComponent {
GENERATED_BODY()
public:
//-------------------------------------------
//! コンストラクタ
//-------------------------------------------
UDamageComponent() {
RcvDamage = 0;
Group = 0;
}
//-------------------------------------------
//! ダメージの設定
//-------------------------------------------
virtual int SetDamage(
const AActor* Sender, //!< 攻撃するActor
AActor* Receiver, //!< 攻撃を受けるActor
int AttackType, //!< 攻撃種別
int Dmg, //!< ダメージ量
const FHitResult* SweepResult //! ヒット情報
) {
RcvDamage += Dmg;
return 0;
}
public:
int RcvDamage;
uint32 Group;
protected:
private:
};
//---------------------------------------------------------------------
//! ヒット属性
//---------------------------------------------------------------------
enum {
HITATB_NON = 0x0000, //!< 当たってない
HITATB_HIT = 0x0001, //!< ぶつかった
HITATB_OVR = 0x0002, //!< オーバーラップした(HITATB_HITもOnになる)
HITATB_DMG = 0x0004, //!< ダメージ入った
};
//----------------------------------------------------------------------
//! 衝突通知を受け取りダメージを通知します
//----------------------------------------------------------------------
UCLASS(ClassGroup = "Hit", editinlinenew, hidecategories = (Object, LOD, Lighting, TextureStreaming), meta = (DisplayName = "UHitComponent", BlueprintSpawnableComponent))
class UHitComponent : public UActorComponent
{
GENERATED_BODY()
public:
//-------------------------------------------
//! コンストラクタ
//-------------------------------------------
UHitComponent() {
Attacker = nullptr;
SetGroup((int)UAttackGroup::GP_Non);
}
void BeginPlay() {
Super::BeginPlay();
HitAtb = 0;
//------------------------------------------------------------------------
// Tagから衝突通知用のコンポーネントを探して通知用のコールバックを設定する
//------------------------------------------------------------------------
auto cmps = GetOwner()->GetComponents();
for (auto cmp : cmps) {
if (cmp->ComponentHasTag("NotifiyCollision")) {
auto obj = Cast<UPrimitiveComponent>(cmp);
if (obj) {
//オーバーラップのコールバックを設定
obj->OnComponentBeginOverlap.AddDynamic(this, &UHitComponent::OnOverlapBegin);
obj->OnComponentHit.AddDynamic(this, &UHitComponent::OnHit);
}
}
}
}
//! 攻撃するアクター
void SetAttacker(AActor* act) {
Attacker = act;
}
//! オーバーラップのコールバック
void SetGroup(int32 gp) {
Group = gp;
}
UFUNCTION()
void OnHit(
UPrimitiveComponent* HitComp,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
FVector NormalImpulse,
const FHitResult& Hit
){
Rcv(false, HitComp, OtherActor, OtherComp, Hit);
}
//-------------------------------------------
//! オーバーラップのコールバック
//-------------------------------------------
UFUNCTION()
void OnOverlapBegin(
UPrimitiveComponent* OverlappedComp,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
int32 OtherBodyIndex,
bool bFromSweep,
const FHitResult& SweepResult)
{
Rcv(true, OverlappedComp, OtherActor, OtherComp, SweepResult);
}
protected:
int Rcv(
bool IsOverlap,
UPrimitiveComponent* OverlappedComp,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
const FHitResult& Hit)
{
if (Attacker) {
if (!IsValid(Attacker)) {
Attacker = nullptr; //攻撃側Actorはいなくなった
}
}
if (Attacker == OtherActor) {
return 0; //自分の攻撃は当たらない
}
{
FString str;
if (IsOverlap) str = "OnOverlapBegin :" + OtherActor->GetName();
else str = "OnHitBegin : " + OtherActor->GetName();
GEngine->AddOnScreenDebugMessage(-1, 3, FColor::Orange, str);
}
HitAtb = HITATB_HIT;
if (IsOverlap) HitAtb |= HITATB_OVR;
auto DamageComponent = OtherActor->FindComponentByClass<UDamageComponent>();
if (DamageComponent) {
HitAtb |= HITATB_OVR;
if ((DamageComponent->Group == 0) || (DamageComponent->Group != Group)) {// 仲間以外に攻撃を充てる
DamageComponent->SetDamage(
Attacker,
OtherActor, //!< 攻撃を受けるActor
0, //!< 攻撃種別
100, //!< ダメージ量
&Hit //! ヒット情報
);
}
}
return 0;
}
public:
uint32 HitAtb;
protected:
uint32 Group;
UPROPERTY()
const AActor* Attacker;
};
cpp:
// Fill out your copyright notice in the Description page of Project Settings.
#include "AttakDamageBase.h"
定義されているクラスは2つです。
- UDamageComponent : ダメージを受信
- UHitSphereComponent : ダメージを送信
ダメージの受信 : UDamageComponent
UDamageComponentはSetDamage()
を通してダメージを受信します。
ダメージの通知 : UHitComponent
UHitComponentは衝突イベントを受け取りダメージを通知します。
衝突イベントの設定 OnComponentBeginOverlap/OnComponentBeginHit
衝突イベントのコールバック設定をBeginPlay()で行っています。
オーナーのアクターからTag"NotifiyCollision"
を持つコンポーネントを見つけコールバックを設定します。
ダメージの通知:Rcv()
UHitComponentは衝突イベントを受けとると衝突したActorからUDamageComponent
を見つけダメージを通知します。