Dev6 카메라 확대/축소, Enemy 공격 Anim, 플레이어 무기 장착
카메라(정확히는 TargetArmLength)의 최소 길이(확대 제한)와 최대 길이(축소 제한),
기본값과 카메라휠을 돌려서 확대/축소할 때 얼만큼씩 길이를 조절할 지..
Main.h
// About CameraZoom
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "CameraZoom")
float MinZoomLength = 100.f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "CameraZoom")
float MaxZoomLength = 800.f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "CameraZoom")
float DefaultArmLength = 500.f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "CameraZoom")
float ZoomStep = 30.f;
카메라줌 함수 - 마우스 휠 값을 매개변수로 받을 것임
void CameraZoom(const float Value);
FORCEINLINE class USpringArmComponent* GetCameraBoom() const { return CameraBoom; }
FORCEINLINE class UCameraComponent* GetFollowCamera() const { return FollowCamera; }
따라서 축 매핑에 추가
스케일값이 -1인 이유는 1로 했었을 때, 마우스휠을 위로 굴리면 축소되고 아래로 굴리면 확대되었음
하지만 난 그 반대로 하고 싶었기 때문에 -1로 바꿈
Main.cpp
#include "Camera/PlayerCameraManager.h"
void AMain::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
PlayerInputComponent->BindAxis("CameraZoom", this, &AMain::CameraZoom);
void AMain::CameraZoom(const float Value)
{
if (Value == 0.f || !Controller) return;
const float NewTargetArmLength = CameraBoom->TargetArmLength + Value * ZoomStep;
CameraBoom->TargetArmLength = FMath::Clamp(NewTargetArmLength, MinZoomLength, MaxZoomLength);
}
Enemy.h
UENUM(BlueprintType)
enum class EEnemyMovementStatus :uint8
{
EMS_Idle UMETA(DeplayName = "Idle"),
EMS_MoveToTarget UMETA(DeplayName = "MoveToTarget"),
EMS_Attacking UMETA(DeplayName = "Attacking"),
EMS_MAX UMETA(DeplayName = "DefaultMAX")
};
enum클래스 아직 공부 안 함, 이전 포스트에 이 코드 빠뜨린듯?
그리고 전투범위오버랩 불 변수 추가됨, 당연히 기본값은 false(생성자에서 기본값 지정)
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "AI")
bool bOverlappingCombatSphere;
인식범위에서 오버랩 해제됐을 때
유휴 상태로 변하고 이동 멈춤
void AEnemy::AgroSphereOnOverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
if (OtherActor)
{
AMain* Main = Cast<AMain>(OtherActor);
if (Main)
{
SetEnemyMovementStatus(EEnemyMovementStatus::EMS_Idle);
if (AIController)
{
AIController->StopMovement();
}
}
}
}
전투범위에 오버랩됐을 때
불 변수 true, 공격 상태로 변경
void AEnemy::CombatSphereOnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
if (OtherActor)
{
AMain* Main = Cast<AMain>(OtherActor);
if (Main)
{
bOverlappingCombatSphere = true;
SetEnemyMovementStatus(EEnemyMovementStatus::EMS_Attacking);
}
}
}
전투범위 오버랩 해제됐을 때
불 변수 false, 현재 공격 상태면 플레이어 쫓아가기
void AEnemy::CombatSphereOnOverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
if (OtherActor)
{
AMain* Main = Cast<AMain>(OtherActor);
if (Main)
{
bOverlappingCombatSphere = false;
if (EnemyMovementStatus == EEnemyMovementStatus::EMS_Attacking)
{
MoveToTarget(Main);
}
}
}
}
+그리고 MoveToTarget()에선 당연히
SetEnemyMovementStatus(EEnemyMovementStatus::EMS_MoveToTarget);
상태를 바꿔줍니다.
무기 장착은 일단… (플레이어는 문제 없는데 npc가 문제)
사용자 클래스 Item 상속받음
Weapon.h
UENUM(BlueprintType)
enum class EWeaponState :uint8
{
EWS_Pickup UMETA(DisplayName = "Pickup"),
EWS_Equipped UMETA(DisplayName = "Equipped"),
EWS_Max UMETA(DisplayName = "DefaultMax"),
};
/**
*
*/
UCLASS()
class YARO_API AWeapon : public AItem
{
GENERATED_BODY()
protected:
// Called when the game starts or when spawned
//virtual void BeginPlay() override;
public:
AWeapon();
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Item")
EWeaponState WeaponState;
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "SkeletalMesh")
class USkeletalMeshComponent* SkeletalMesh;
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 Equip(class AMain* Char);
void Equip_NPC(class AYaroCharacter* Char, class AWeapon* Wand);
FORCEINLINE void SetWeaponState(EWeaponState State) { WeaponState = State; }
FORCEINLINE EWeaponState GetWeaponState() { return WeaponState; }
};
Weapon.cpp
AWeapon::AWeapon()
{
SkeletalMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("SkeletalMesh"));
SkeletalMesh->SetupAttachment(GetRootComponent());
WeaponState = EWeaponState::EWS_Pickup;
}
플레이어가 무기 자신에게 오버랩됐을 때 Main에 있는 ActiveOverlappingItem에 할당
void AWeapon::OnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
//UE_LOG(LogTemp, Log, TEXT("%s"), *(this->GetName()));
Super::OnOverlapBegin(OverlappedComponent, OtherActor, OtherComp, OtherBodyIndex, bFromSweep, SweepResult);
if ((WeaponState == EWeaponState::EWS_Pickup) && OtherActor)
{
AMain* Main = Cast<AMain>(OtherActor);
if (Main)
{
Main->SetActiveOverlappingItem(this);
}
}
}
오버랩 해제되면 null로 바꿔줌
void AWeapon::OnOverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
Super::OnOverlapEnd(OverlappedComponent, OtherActor, OtherComp, OtherBodyIndex);
if (OtherActor)
{
AMain* Main = Cast<AMain>(OtherActor);
if (Main)
{
Main->SetActiveOverlappingItem(nullptr);
}
}
}
무기 장착 함수, 매개변수로 플레이어를 받음
플레이어 메쉬에서 RigntHandSocket이라는 소켓을 가져온 뒤 무기 본인(액터, Item클래스가 액터 상속받음) 부착
void AWeapon::Equip(AMain* Char)
{
if (Char)
{
SkeletalMesh->SetCollisionResponseToChannel(ECollisionChannel::ECC_Camera, ECollisionResponse::ECR_Ignore);
SkeletalMesh->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECollisionResponse::ECR_Ignore);
SkeletalMesh->SetSimulatePhysics(false);
const USkeletalMeshSocket* RightHandSocket = Char->GetMesh()->GetSocketByName("RightHandSocket");
if (RightHandSocket)
{
RightHandSocket->AttachActor(this, Char->GetMesh());
bRotate = false;
Char->SetEquippedWeapon(this);
Char->SetActiveOverlappingItem(nullptr);
}
}
}
이것이 RightHandSocket
그리고 무기를 장착하기 위해선 무기의 (오버랩)범위 안에 들어간 뒤 왼쪽 마우스를 클릭해야함!
액션 매핑에 왼쪽 마우스 추가
왼쪽 마우스 버튼 클릭에 관련된 변수 및 함수들 + 무기 장착 관련
Main.h
bool bLMBDown;
void LMBDown();
void LMBUp();
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Items)
class AWeapon* EquippedWeapon;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Items)
class AItem* ActiveOverlappingItem;
FORCEINLINE void SetEquippedWeapon(AWeapon* WeaponToSet) { EquippedWeapon = WeaponToSet; }
FORCEINLINE void SetActiveOverlappingItem(AItem* Item) { ActiveOverlappingItem = Item; }
void AMain::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) 에서 바인딩
PlayerInputComponent->BindAction("LMB", IE_Pressed, this, &AMain::LMBDown);
PlayerInputComponent->BindAction("LMB", IE_Released, this, &AMain::LMBUp);
void AMain::LMBDown()
{
bLMBDown = true;
if (ActiveOverlappingItem)
{
AWeapon* Weapon = Cast<AWeapon>(ActiveOverlappingItem);
if (Weapon)
{
Weapon->Equip(this);
SetActiveOverlappingItem(nullptr);
}
}
}
void AMain::LMBUp()
{
bLMBDown = false;
}
카메라 확대/축소, 무기장착, Enemy 상태변환 등 영상으로 확인
무기를 장착해야해서 기존 애니메이션들 손 모양도 좀 바꿔주고,
공격 애니메이션을 만드려고 했는데 쉽지 않음… ㅠ
시간이 엄청 오래 걸림…….. 아직 완성도 못 함
다음 할 것 : npc 무기 장착 방법 연구… 공격 애니메이션 만들기? 적의 공격 시스템도..