Infinite Fighter 개발일지 (3)

유영준·2023년 3월 26일
0

UE5 UNSEEN

목록 보기
3/18
post-thumbnail

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로 블랜딩하는 과정을 거쳤다

현재까지의 진행상태이다

개선점

  • 애니메이션 그래프 깔끔하게 정리하기

다음주에 할 일

  • 공격모션 추가 (주먹, 도끼 모두)
profile
토비폭스가 되고픈 게임 개발자

0개의 댓글