공격 몽타주 중에 무기를 던지는 공격이 있다. 그거 제작하는데 좀 걸렸다.
이 공격이다.
EnemyWrathThrowWeapon.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "EnemyWrathThrowWeapon.generated.h"
UCLASS()
class ENEMYCODES_API AEnemyWrathThrowWeapon : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AEnemyWrathThrowWeapon();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
private:
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Mesh", meta = (AllowPrivateAccess = true))
class USkeletalMeshComponent* WeaponMesh;
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "HitBox", meta = (AllowPrivateAccess = true))
class UBoxComponent* HitBoxCollider;
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "EffectParticle", meta = (AllowPrivateAccess = true))
class UParticleSystem* EffectParticle;
private:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Attack", meta = (AllowprivateAccess = true))
FVector Destination;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attack", meta = (AllowPrivateAccess = true))
float RotationSpeed;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attack", meta = (AllowPrivateAccess = true))
float ThrowSpeed;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attack", meta = (AllowPrivateAccess = true))
float MaxDistance;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attack", meta = (AllowPrivateAccess = true))
float GroundHitRotation;
bool bIsRotate;
private:
void RotateToGround(const float& DeltaTime);
void HitGround();
public:
void SetActiveActor(bool bIsActive);
void SetTargetAndThrow(const FVector& ActorLocation);
};
EnemyWrathThrowWeapon.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "EnemyWrathThrowWeapon.h"
#include "EnemyWeaponBase.h"
#include "Components/SkeletalMeshComponent.h"
#include "Components/BoxComponent.h"
#include "Kismet/KismetMathLibrary.h"
// Sets default values
AEnemyWrathThrowWeapon::AEnemyWrathThrowWeapon()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
HitBoxCollider = CreateDefaultSubobject<UBoxComponent>(TEXT("HitBox"));
SetRootComponent(HitBoxCollider);
WeaponMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("WeaponMesh"));
//HitBoxCollider->AttachToComponent(WeaponMesh, FAttachmentTransformRules::SnapToTargetIncludingScale, "LeftWeaponSocket");
WeaponMesh->AttachToComponent(GetRootComponent(), FAttachmentTransformRules::SnapToTargetIncludingScale);
bIsRotate = false;
MaxDistance = 10.0f;
}
// Called when the game starts or when spawned
void AEnemyWrathThrowWeapon::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void AEnemyWrathThrowWeapon::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
RotateToGround(DeltaTime);
}
void AEnemyWrathThrowWeapon::SetActiveActor(bool bIsActive)
{
SetActorHiddenInGame(!bIsActive);
SetActorEnableCollision(bIsActive);
SetActorTickEnabled(bIsActive);
}
void AEnemyWrathThrowWeapon::RotateToGround(const float& DeltaTime)
{
if(bIsRotate == false)
{
return;
}
const float Distance = FVector::Distance(Destination, GetActorLocation());
if (Distance <= MaxDistance)
{
bIsRotate = false;
HitGround();
return;
}
FVector Direction = Destination - GetActorLocation();
Direction = Direction.GetSafeNormal();
SetActorLocation(GetActorLocation() + (Direction * ThrowSpeed));
const FRotator CurRotation = FRotator(DeltaTime * -RotationSpeed,0, 0);
const FQuat QuatRotation = FQuat(CurRotation);
AddActorLocalRotation(QuatRotation);
}
void AEnemyWrathThrowWeapon::HitGround()
{
const FRotator CurRotator = FRotator(GroundHitRotation, GetActorRotation().Yaw, GetActorRotation().Roll);
const FQuat QuatRotation = FQuat(CurRotator);
const FRotator LookAtRotator = UKismetMathLibrary::FindLookAtRotation(GetActorLocation(), Destination);
SetActorLocationAndRotation(Destination, LookAtRotator);
SetActorRotation(QuatRotation);
}
void AEnemyWrathThrowWeapon::SetTargetAndThrow(const FVector& ActorLocation)
{
Destination = ActorLocation;
bIsRotate = true;
const FRotator LookAtRotator = UKismetMathLibrary::FindLookAtRotation(GetActorLocation(), ActorLocation);
SetActiveActor(true);
SetActorRotation(LookAtRotator);
}
던지면 그 방향으로 회전하면서 날아가는 동작이다.
EnenyWrath.cpp
void AEnemyWrath::ThrowWeapon()
{
Weapon->SetActiveActor(false);
SetWeaponType(EEnemyWeaponType::EWT_Fist);
const ACharacter* Character = Cast<ACharacter>(TargetActor);
const FVector TargetLocation = TargetActor->GetActorLocation();
//const FVector TargetLocation = Character->GetMesh()->GetRelativeLocation();
const FVector ThrowableWeaponLocation = GetMesh()->GetSocketLocation(FName("LeftWeaponSocket"));
ThrowableWeapon->SetActiveActor(true);
ThrowableWeapon->SetActorLocation(ThrowableWeaponLocation);
ThrowableWeapon->SetTargetAndThrow(TargetLocation);
}
던졌을때 현재 공격 타입을 바꾸고 현재 무기 부분에서 던져준다.
(테스트 할때는 공격 타입을 바꾸진 않았다.)