2023.03.20 ~ 2023.03.26 개발일지
먼저 저번주에 이동의 값이 확 바뀔때 부자연스러운 부분들이 있었는데 블랜드 스페이스의 Sample smoothing 기능을 통해 개선 할 수 있었다
이때 Weight Speed 는 1일때 블랜딩에 1초, 2일때 0.5초가 걸리는 방식이다 (다만 0은 블랜딩을 하지 않는다)
훨씬 부드럽게 움직이는 것을 볼 수 있다
먼저 납도하는 모션과 발도하는 모션을 구해주었다
이는 모두 mixamo에서 구했다 그리고 이들을 몽타주로 만들어주었다
몽타주에는 그룹을 오른손으로 새롭게 만들어 넣어주었고, 모션 중간에 노티파이를 넣어 상태를 변경할 수 있도록 하였다
DrawStart
노티파이에서 DrawEnd
까지는 다른 액션을 막고, 그 이후에는 자연스럽게 캔슬되며 움직이도록 구현하고자 한다
움직임에 관한 부분은 locomotion cache에 저장하였고, 발도, 납도 모션 전체가 아닌
오른손만 섞일 수 있도록 Layered blend per bone 함수를 통해 엮었다
오른쪽 어깨를 기준점으로 잡아 이 부분만 움직이도록 설정
현재까지 완성된 모습이다
다만 여기에는 문제가 있었는데, 블랜딩 한 이후 오른손이 과하게 움직일때면
무기가 신체를 뚫고 나간다는 것이었다
ex) 달릴 때의 모습 얼굴을 무기가 정통으로 뚫고 지나간다
이 문제를 해결하기 위해, 무기를 들고 있을때는 오른팔을 얌전하게 고정시켜줄 필요가 있었다
팔이 움직이지 않는 기본 자세를 다시 한번 블랜딩하여 납도 상태와 발도 상태를 구분해주었다
먼저 정리한 코드를 보자
IFCharacterAnimInstance.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Animation/AnimInstance.h"
#include "IFCharacterAnimInstance.generated.h"
/**
*
*/
UCLASS()
class INFINITEFIGHTER_API UIFCharacterAnimInstance : public UAnimInstance
{
GENERATED_BODY()
public:
...
const bool GetAxeHolding() const;
void SetAxeHolding(bool bAxeHolding);
void PlayDrawSheatheMontage();
private:
...
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Pawn, Meta = (AllowPrivateAccess = true))
bool bIsAxeHolding;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Pawn, Meta = (AllowPrivateAccess = true))
bool bCanDoNextAction;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Pawn, Meta = (AllowPrivateAccess = true))
bool bIsDrawState;
UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Category = Attack, Meta = (AllowPrivateAccess = true))
UAnimMontage* DrawMontage;
UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Category = Attack, Meta = (AllowPrivateAccess = true))
UAnimMontage* SheatheMontage;
UFUNCTION()
void AnimNotify_SheatheStart();
UFUNCTION()
void AnimNotify_SheatheEnd();
UFUNCTION()
void AnimNotify_DrawStart();
UFUNCTION()
void AnimNotify_DrawEnd();
UFUNCTION()
void AnimNotify_DrawStateChange();
};
IFCharacterAnimInstance.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "IFCharacterAnimInstance.h"
UIFCharacterAnimInstance::UIFCharacterAnimInstance()
{
CharacterDirection = 0.0f;
CharacterSpeed = 0.0f;
bIsAxeHolding = false;
bCanDoNextAction = true;
bIsDrawState = false;
// setting montages
static ConstructorHelpers::FObjectFinder<UAnimMontage> DRAW_MONTAGE
(TEXT("/Game/InFiniteFighter/Characters/Animation/Combat/Draw_Montage.Draw_Montage"));
if (DRAW_MONTAGE.Succeeded())
DrawMontage = DRAW_MONTAGE.Object;
static ConstructorHelpers::FObjectFinder<UAnimMontage> SHEATHE_MONTAGE
(TEXT("/Game/InFiniteFighter/Characters/Animation/Combat/Sheathe_Montage.Sheathe_Montage"));
if (SHEATHE_MONTAGE.Succeeded())
SheatheMontage = SHEATHE_MONTAGE.Object;
}
...
// get bIsAxeHolding
const bool UIFCharacterAnimInstance::GetAxeHolding() const
{
return bIsAxeHolding;
}
// set bIsAxeHolding
void UIFCharacterAnimInstance::SetAxeHolding(bool bAxeHolding)
{
bIsAxeHolding = bAxeHolding;
}
// play sheathe if equiped, play draw if unequiped
void UIFCharacterAnimInstance::PlayDrawSheatheMontage()
{
if (bIsAxeHolding)
{
if (bCanDoNextAction)
{
Montage_Play(SheatheMontage);
SetAxeHolding(false);
}
}
else
{
if (bCanDoNextAction)
{
Montage_Play(DrawMontage);
SetAxeHolding(true);
}
}
}
void UIFCharacterAnimInstance::AnimNotify_SheatheStart()
{
// set 2 bool variables for smoother motion blending
// bCanDoNextAction for motion canceling, bIsDrawState for blend by bool
bCanDoNextAction = false;
bIsDrawState = false;
}
void UIFCharacterAnimInstance::AnimNotify_SheatheEnd()
{
bCanDoNextAction = true;
}
void UIFCharacterAnimInstance::AnimNotify_DrawStart()
{
bCanDoNextAction = false;
}
void UIFCharacterAnimInstance::AnimNotify_DrawEnd()
{
bCanDoNextAction = true;
}
void UIFCharacterAnimInstance::AnimNotify_DrawStateChange()
{
bIsDrawState = true;
}
비슷한 형태의 변수들이 있기때문에 이들에 대한 설명을 하고자 한다
bIsAxeHolding
은 무기를 들고 있는지 아닌지에 대한 변수이다
무기는 던지는 것 또한 가능하게 할 예정이기 때문에 모든 상황에 대처할 수 있는 변수로서 설정해주었다
bCanDoNextAction
은 모션의 7~80퍼센트 가량에 넣어줄 노티파이에서 사용할 변수이다
이를 통해 다음 모션이 더 부드럽게 넘어갈 수 있도록 구현하였다
bIsDrawState
는 오로지 발도 모션을 취할때를 위한 모션이다
발도모션이 끝난 이후 블랜딩을 하기 위해 명시적으로 추가해주었다
아까전까지의 모션을 RightHand cache에 넣어주었고, 이를 다시 bool로 블랜딩하는 과정을 거쳤다
현재까지의 진행상태이다