드래곤의 w스킬은 바라보는 위치로 에너지볼트를 쏘는 스킬입니다
w키를 홀딩할때 해당 위치를 고개를 바라보며 입에서 구체가 나가도록 해보겠습니다
먼저 시퀀스를 원하는위치에서 프레임을 짤라 1프레임짜리 시퀀스를 준비해줍니다
시퀀스에서 FK컨트롤 릭으로 편집을 눌러줍니다
오른쪽으로 90도 릭을 이동하여 키를 찍어준뒤 시퀀스를 Baked해줍니다
이렇게 고개가 90도 돌아간 왼쪽 오른쪽 애니메이션을 만들어줍니다
블렌드스페이스를 만든뒤 가로축을 Angle로 설정 최소를 -90 최대를 90을 설정해준뒤
중앙은 1프레임짜리 원래 애니메이션 우측 90은 오른쪽으로 돌아간 애니메이션
왼쪽 -90은 왼쪽으로 돌아간 애니메이션을 넣어줍니다
w공격 조준하는 용도의 블렌드스페이스를 만들어줍니다
마우스의 방향을 구해 위치를 구하는 함수를 만들어줍니다
void ADragonCharacter::UpdateLookAngleToMouse()
{
APlayerController* pc = Cast<APlayerController>(UGameplayStatics::GetPlayerController(this, 0));
if (!pc) return;
FHitResult HitResult;
if (!pc->GetHitResultUnderCursor(ECC_Visibility, false, HitResult)) return;
FVector forward = GetActorForwardVector().GetSafeNormal2D();
FVector toMouse = (HitResult.ImpactPoint - GetActorLocation()).GetSafeNormal2D();
float angle = FMath::Acos(FVector::DotProduct(forward, toMouse));
angle = FMath::RadiansToDegrees(angle);
float CrossZ = FVector::CrossProduct(forward, toMouse).Z;
float signedAngle = angle * (CrossZ > 0.f ? 1.f : -1.f);
signedAngle = FMath::Clamp(signedAngle, -180.f, 180.f);
lookAngle = signedAngle;
dragonAnimInstance->bWAiming = true;
}
구한 lookAngle을 리턴하는 Gettet함수를 만들어줍니다
float ADragonCharacter::GetLookAngle() const
{
return lookAngle;
}
해당 bWaiming 변수로 블렌드스페이스를 바꿀껀지 말껀지 조건을 제한합니다
dragonAnimInstance->bWAiming = true;
애님인스턴스에서 각도와 블렌드스페이스 변화트리거 bool변수를 선언
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MySettings")
float angle = 0.f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MySettings")
bool bWAiming = false;
스테이트머신 글로벌에일리어스를 추가후 w에이밍 전용 블렌드스페이스를 넣어줍니다
컨트롤러에서 w키를 누르고있거나 뗏을때 함수를 호출할수있도록 합니다
InputWPressed은 IE_Pressed
InputWUnPressed는 IE_Released입니다
void ADragonController::InputWPressed()
{
if (dragonCharacter)
{
dragonCharacter->UpdateLookAngleToMouse();
}
}
void ADragonController::InputWUnPressed()
{
if (dragonCharacter)
{
dragonCharacter->UpdateCancleLookAngleToMouse();
}
}
이제 w키를 누르면 고개가 해당 마우스 근처부분으로 돌아가게됩니다
고개만 돌아가고 하체는 원래 idle상태로 유지시키고싶습니다
목을 기준으로 목만 애니메이션을 적용시켜주겠습니다
Neck01기준으로 목만 움직이게 하도록 하겠습니다
해당 블렌드스페이스에서 Layered Blend Per Bone노드와 DefaultSlot노드를 Output전에 배치
본 Neck01을 할당하여 목을 기준으로 애니메이션을 나눠줍니다
w를 눌렀을때 사용할 구체를 만들어주겠습니다
c++ 액터를 상속받고 ProjectTileMovement를 사용하겠습니다
ADragonWOrb::ADragonWOrb()
{
PrimaryActorTick.bCanEverTick = true;
//Scene
sceneComp = CreateDefaultSubobject<USceneComponent>(TEXT("sceneComp"));
RootComponent = sceneComp;
//Collision
collisionComp = CreateDefaultSubobject<UCapsuleComponent>(TEXT("SphereComponent"));
collisionComp->SetCollisionProfileName(TEXT("BlockAll"));
collisionComp->SetupAttachment(RootComponent);
//SkeletalMeshComp
niagaraComp = CreateDefaultSubobject<UNiagaraComponent>(TEXT("niagaraComp"));
niagaraComp->SetupAttachment(RootComponent);
niagaraComp->SetWorldScale3D(FVector(0.2f));
//ProjectTile
projectileMovement = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("projectTileMevement"));
projectileMovement->InitialSpeed = 0.f;
projectileMovement->MaxSpeed = 0.f;
projectileMovement->bRotationFollowsVelocity = true;
projectileMovement->ProjectileGravityScale = 0.0f;
bFire = false;
}
발사될 Socket을 만들어줍니다 이름은 FireSocket
UPROPERTY(EditAnywhere, Category = "MySettings")
UProjectileMovementComponent* projectileMovement;
float currentScale = 1.f;
float targetScale = 3.f;
float grownDuration = 0.5f;
float elaspedTime = 0.f;
bFire이 true가 될떄까지 FireSocket에 붙어있다가 targetScale이 될떄까지 커지고
bFire이 true가 되는 순간 3000의 속도로 움직입니다
또한 pitch yaw roll방향으로 각각 회전합니다
void ADragonWOrb::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (!bFire)
{
if (AActor* ownerActor = GetOwner())
{
USkeletalMeshComponent* ownerMesh = ownerActor->FindComponentByClass<USkeletalMeshComponent>();
if (ownerMesh)
{
FVector fireSocketLoc = ownerMesh->GetSocketLocation(TEXT("FireSocket"));
FRotator fireSocketRot = ownerMesh->GetSocketRotation(TEXT("FireSocket"));
SetActorLocationAndRotation(fireSocketLoc, fireSocketRot);
}
}
if (currentScale < targetScale)
{
elaspedTime += DeltaTime;
float growOrb = FMath::Clamp(elaspedTime / grownDuration, 0.f, 1.f);
currentScale = FMath::Lerp(1.f, targetScale, growOrb);
FVector newScale(currentScale);
sceneComp->SetWorldScale3D(newScale);
}
}
else
{
projectileMovement->InitialSpeed = 3000.f;
projectileMovement->MaxSpeed = 3000.f;
FVector fireDir = GetActorForwardVector();
projectileMovement->Velocity = fireDir * projectileMovement->InitialSpeed;
}
FRotator RotationDelta;
RotationDelta.Pitch = 90.f * DeltaTime;
RotationDelta.Yaw = 120.f * DeltaTime;
RotationDelta.Roll = 60.f * DeltaTime;
niagaraComp->AddLocalRotation(RotationDelta);
}
또한 오버랩이벤트도 적용시켜주었습니다
컨셉이 파란계열이니 이니 용도 파랗게 메테리얼도 변경
w스킬을 홀딩하면 구체가 커지며 차징되고 w키를 누르면 마우스 위치로 발사됩니다
각각 스킬에 쿨타임을 주었으며 ui와 연동시켜주었습니다
bool bQToggleCooldown = false;
void ADragonController::InputQPressed()
{
if (dragonCharacter && !bQToggleCooldown)
{
bQToggleCooldown = true;
dragonCharacter->DragonQAttack();
dragonCharacter->dragonWidget->updateQCountDown(1.5f);
GetWorld()->GetTimerManager().SetTimerForNextTick([this]()
{
FTimerHandle th_QHandle;
GetWorld()->GetTimerManager().SetTimer(th_QHandle, FTimerDelegate::CreateLambda([this]()
{
bQToggleCooldown = false;
}), 1.0f, false);
});
}
}
Fly중일떄 밑을보면서 w스킬을 사용하도록 왼쪽밑 오른쪽 밑을 바라보는 시퀀스를 컨트롤 릭을 사용하여 만들어줍니다
스테이트머신 에 날고있을때 고개를 회전시키는 블렌드스페이스 또한 적용시켜줍니다
'Unreal5 프로젝트 다이어리' 카테고리의 다른 글
Unreal - BGM, 사운드 관리법 (0) | 2025.06.21 |
---|---|
Unreal - Material Parameter Collection 사용하기 (0) | 2025.06.21 |
Unreal - 드래곤 캐릭터 만들기 (1) (0) | 2025.06.12 |
Unreal - 데미지 오버레이 만들기 (0) | 2025.06.08 |
Unreal - 딜레이 프로그래스바 (0) | 2025.06.07 |