1. MonsterBase 클래스를 만들어보자
1) Actors폴더/pawn 상속 / MonsterBase 클래스 생성
2) 초기화시 캡슐, 메시 컬리전 설정 등 초기화
header
#include "EngineMinimal.h"
...
protected:
UPROPERTY( EditAnywhere, BlueprintReadWrite )
USkeletalMeshComponent* mMesh;
UPROPERTY( EditAnywhere, BlueprintReadWrite )
UCapsuleComponent* mCapsule;
생성자
AMonsterBase::AMonsterBase()
{
// Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
mMesh = CreateDefaultSubobject<USkeletalMeshComponent>(L"Mesh");
mCapsule = CreateDefaultSubobject<UCapsuleComponent>(L"Collision");
SetRootComponent( mCapsule );
mMesh->AttachToComponent( mCapsule, FAttachmentTransformRules::KeepRelativeTransform );
mMesh->SetCollisionEnabled( ECollisionEnabled::NoCollision );
}
2) 블프/Actors 폴더에 블루프린트 추가, MonsterBase 상속 -> BP_Orc
메시 설정, 캡슐 크기 설정, 회전
3가지 보기좋게 설정해주기.
3) 무기 추가해보기
(1) Maul_Sm복사 후 추가 후 스태틱 메시 컴포넌트(Maul_SM)추가, 이름 Weapon으로 변경
(2) 매쉬 자식으로 이동
(3) 무기 쥐어줄 위치 찾기. 메쉬의 스켈레톤 에디터 가서 소켓 위치 찾기
(4) Weapon 선택 후 디테일창에서 부모소켓에 폴더모양 눌러서 무기소켓 이름 넣기
ㄴ 매시에서 소켓 아이콘 가진 애 이름 찾아서 넣어주기
웨폰이 매시 아래있어야 적용됨.. 캡슐 바로 아래 있을 경우 적용이 안된다..
4) 애니메이션 추가하기
애니메이션 블루프린트 추가 - 스켈레톤 선택 - 부모클래스로 AnimBase 선택 - BPA_AnimOrc 추가
5) BPA_AnimOrc에디터에 애니메이션 연결
- idle, run 애니 추가 후 루프 선택
6) BP_Orc에디터에서 디테일창 - 애님클래스에 BPA_AnimOrc 연결
여기까지 진행하면 오크 몬스터가 무기를 들게된다.
2. 몬스터에 애니메이션을 적용시키자
1) Define.h EAnimType에
hit와 die 추가
UENUM( BlueprintType )
enum class EAnimType : uint8
{
ANIMTYPE_IDLE UMETA( DisplayName = "Idle" ),
ANIMTYPE_WALK UMETA( DisplayName = "Walk" ),
ANIMTYPE_HIT UMETA( DisplayName = "Hit" ),
ANIMTYPE_DIE UMETA( DisplayName = "Die" ),
ANIMTYPE_END UMETA( DisplayName = "End" ),
};
2) BPA_AnimOrc 에디터와서 Blend Pose에 Hit, Die추가 및 애니 연결
(1) 오크 애님에 해당 애니 추가 및 연결
(2) 애니메이션 추가시, Blend Poses 추가 후 활성 열거형값을 mAnimType으로 설정해주기
3. 몬스터가 맞을 때 데미지를 입도록 변경해보자
▶️ApplyDamage()
: 데미지 주는 함수
- AActor* DamagedActor : 데미지 받을 액터
- float BaseDamage : 데미지 양
- AController* EventInstigator : 데미지 주는 컨트롤러
- AActor* DamageCauser: 데미지 주는 액터
- TSubclassOf<UDamageType> DamageTypeClass) : 적용할 데미지 타입
uint32 bCausedByWorld:1; // 지형에 의한 ex) 용암뎀
ex)
UGameplayStatics::ApplyDamage( hit.GetActor(), 1, GetController(), this, UDamageType::StaticClass());
▶️TakeDamage()
: 데미지 받는 함수
- Damage : 받은 데미지 양
- DamageEvent : 데미지 종류. 방사형인지 일점사인지 등등
- EventInstigator : 데미지를 준 컨트롤러
- DamageCauser : 데미지를 준 액터
ex)
virtual float TakeDamage( float Damage, struct FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser );
1) playerKnight에서 공격할 때 데미지 주는 함수 추가
void APlayerKnight::AttackCollision_Server_Implementation()
{
...
// 충돌된 물체가 있다면
if ( collision )
{
// Ranged For
for ( const FHitResult& hit : result )
{
UGameplayStatics::ApplyDamage( hit.GetActor(), 1, GetController(), this, UDamageType::StaticClass() );
// 서버에 연결된 모든 클라이언트들에게 이펙트 출력
SpawnEffect_MultiCast( hit.Location );
}
}
}
2) 몬스터 타격 당하는 함수 추가
▶️ApplyDamage() 내부를 보면
float UGameplayStatics::ApplyDamage(AActor* DamagedActor, float BaseDamage, AController* EventInstigator, AActor* DamageCauser, TSubclassOf<UDamageType> DamageTypeClass)
{
if ( DamagedActor && (BaseDamage != 0.f) )
{
// make sure we have a good damage type
TSubclassOf<UDamageType> const ValidDamageTypeClass = DamageTypeClass ? DamageTypeClass : TSubclassOf<UDamageType>(UDamageType::StaticClass());
FDamageEvent DamageEvent(ValidDamageTypeClass);
return DamagedActor->TakeDamage(BaseDamage, DamageEvent, EventInstigator, DamageCauser);
}
return 0.f;
}
ㄴ> 데미지 입은 액터에 TakeDamage를 호출하니까
몬스터 클래스에서 TakeDamage 함수를 재정의해서 데미지를 먹도록 처리해주자.
MonsterBase.h
TakeDamage는 APawn에있는 TakeDamage()에서 인자 보고 가져와서 오버라이드해주기
protected:
..
UPROPERTY()
int32 mHP;
..
public:
virtual float TakeDamage ( float Damage, struct FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser ) override;
AMonsterBase::AMonsterBase()
{
..
mHP = 5;
}
float AMonsterBase::TakeDamage( float Damage, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser )
{
Super::TakeDamage( Damage, DamageEvent, EventInstigator, DamageCauser );
if ( mHP > 0 )
mHP -= Damage;
return Damage;
}
=> 브레이크포인트 걸고 실행하면 데미지 함수들 잘 들어옴
4. 몬스터 타격 애니메이션 실행 서버 함수 호출 추가
MonsterBase.h
public :
..
UFUNCTION(BlueprintCallable, Server, Reliable )
void ChangeAnimMonster_Server(EAnimType AnimType);
void ChangeAnimMonster_Server_Implementation(EAnimType AnimType);
UFUNCTION( BlueprintCallable, NetMulticast, Reliable )
void ChangeAnimMonster_NetMulticast( EAnimType AnimType );
void ChangeAnimMonster_NetMulticast_Implementation( EAnimType AnimType );
float AMonsterBase::TakeDamage( float Damage, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser )
{
Super::TakeDamage( Damage, DamageEvent, EventInstigator, DamageCauser );
if ( mHP > 0 )
{
mHP -= Damage;
if ( mHP > 0 )
ChangeAnimMonster_Server( EAnimType::ANIMTYPE_HIT );
else
ChangeAnimMonster_Server( EAnimType::ANIMTYPE_DIE );
}
return Damage;
}
void AMonsterBase::ChangeAnimMonster_Server_Implementation( EAnimType AnimType )
{
ChangeAnimMonster_NetMulticast( AnimType );
}
void AMonsterBase::ChangeAnimMonster_NetMulticast_Implementation( EAnimType AnimType )
{
UAnimBase* anim = Cast<UAnimBase>( mMesh->GetAnimInstance() );
if ( !IsValid( anim ) )
return;
anim->SetAnimType( AnimType );
}
CreateDefaultSubobject 생성시 뒤에 text안붙여도 된다. 지금은 룰이다 생각하고 넣는중이다.
'Unreal Engine5 > KDT 2024' 카테고리의 다른 글
[UE5 KDT2024] 29. 애님 노티파이 클래스 (0) | 2025.03.13 |
---|---|
[UE5 KDT2024] 28. 몬스터 폰 데미지 적용 (0) | 2025.03.12 |
[UE5 KDT2024] 26. 서버에서 충돌처리 2 (0) | 2025.03.10 |
[UE5 KDT2024] 25. 서버에서 충돌처리 1 (0) | 2025.03.09 |
[UE5 KDT2024] 24. 충돌 2 (0) | 2025.03.08 |
댓글