Infinite Fighter 개발일지 (16)

유영준·2023년 7월 2일
0

UE5 UNSEEN

목록 보기
16/18
post-thumbnail

23.06.26 ~ 2023.07.02 개발일지

개선한 점

CineCamera Dynamic하게 불러오기

지금까지 처형 모션을 할때는 Possessable로 둔 시네카메라를 캐릭터의 자식으로 둠으로서

언제나 캐릭터의 위치에 관계된 위치에서 영상이 시작하는 구조로 되어 있었다

다만 문제점이 있었는데, 캐릭터를 먼저 맵에 두고 시네 카메라를 붙여주어야했으며, 코드적으로 묶어주는 것이 아니였기에

다른 맵으로 이동 시 시퀀서가 시네카메라를 찾을 수 없어 영상을 실행 할 수 없었다

이를 위해 시퀀서와 시네카메라를 코드적으로 연동시켜주는 작업을 하였다

처음으로 시네카메라를 캐릭터의 자식으로 선언해주었다

이때 시네카메라컴포넌트가 아닌 실제 액터 ACineCameraActor를 선언하였다

IFCharacter.cpp

	// Creating CineCamera and Attaching it to Character
	CineCamera = GetWorld()->SpawnActor<ACineCameraActor>(GetActorLocation() + FVector(-210.0f, 50.0f, 80.0f), GetActorRotation());
	
	CineCamera->GetCineCameraComponent()->SetCurrentFocalLength(25.0f);
	CineCamera->GetCineCameraComponent()->SetFilmbackPresetByName(FString::Printf(TEXT("16:9 Digital Film")));
	
	if (::IsValid(CineCamera))
	{
		CineCamera->AttachToActor(this, FAttachmentTransformRules::KeepWorldTransform);
	}

PostInitializeComponents에서 액터를 생성하고 기본적인 설정을 추가해주었다

다음으로 구현해둔 CreateSequencePlayer 함수에 액터 인자를 받도록 수정해 생성한 CineCamera 액터를 넣어주었다

IFCharacter.cpp

	for(const auto& ExecutionAssetData : ExecutionArray)
		ExecutionAssetData->CreateSequencePlayer(CineCamera);

다만 여기서부터 고난이 시작되었는데, 시퀀서가 실행되는데 필요한 것들은 크게

  1. 시퀀스 그 자체
  2. 시퀀스 플레이어
  3. 시퀀스 액터

이렇게 3가지가 존재했기 때문이다

공식 도큐먼트나 래딧, 포럼 어느곳을 봐도 이에 대해 명확히 설명해주고 어떻게 연동할 수 있을지 말해주는 곳이 없어

존재하는 바인딩과 관련된 여러가지 함수들의 코드를 모두 읽고 찾아보며 작업할 수 밖에 없었다

방식은 다양하게 존재하였는데, 가장 편한 방법은 태그를 이용하는 방법이었다

시퀀서의 트랙을 우 클릭 후 Tags -> OpenBindingTagManager

처음에는 태그가 없기 때문에, 우 클릭 후 태그 이름을 지정해준다

나는 CineCameraActor 태그로 지정해주었다

이렇게 해주었다면 시퀀서 액터에서 AddBindingByTag 함수를 사용해주면 된다

ExecutionAssetData.cpp

SequenceActor->AddBindingByTag(TEXT("CineCameraActor"), CineCamera);
    
// Same function
    
// FMovieSceneObjectBindingID BindindID = LevelSquence->FindBindingByTag(TEXT("CineCameraActor"));
// SequenceActor->AddBinding(BindindID, CineCamera);

추가한 부분

캐릭터 매쉬 추가

게임이 완성되어감에 따라 캐릭터를 기본 UE4 마네킹에서 크레토스로 바꿔주었다

모델은 이번에도 Sketchfab에서 구했다

다만 이 모델은 리깅이 되어 있지 않기 때문에 UE4 스켈레톤에 맞게 리깅을 해주어야했다

리깅에는 액터코어에서 만든 accuRIG을 사용했다

기본적으로 언리얼 엔진 마네킹으로 리깅이 가능하다

다음으로는 리깅한 fbx 파일을 ue4 마네킹으로 불러오고, 캐릭터 c++파일에서 크레토스 매쉬를 불러오도록 코드를 수정했다

리깅이 잘 되어있고 애니메이션도 다 어색함 없이 부드럽게 돌아가는 것을 확인할 수 있었다

게임 월드 추가

지금같은 빈 공간에서 게임을 진행 할 수는 없기에, 여러 애셋들을 찾아가며 마음에 드는 맵을 찾아보았다

결국 내 마음에 든 맵은 InfinityBlade: Ice Lands 이다

우중충한 겨울이며 중앙에 광장까지 아주 딱 마음에 들었다

맵을 추가하고 중간 광장부분의 오브젝트를 정리하고 네브 메쉬를 설정해주었다

이 곳에서 전투가 이루어질 예정이다


스테이지 클래스 추가

먼저 스테이지의 정보를 담을 csv 파일을 추가해주었다

IFStageTable.h


#pragma once

#include "CoreMinimal.h"
#include "Engine/DataTable.h"
#include "IFStageTable.generated.h"

USTRUCT(BlueprintType)
struct FIFStageTable : public FTableRowBase
{
    GENERATED_BODY()
    
public:
    FIFStageTable() : MaxHp(0.0f), Attack(0.0f), Count(0) {}

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Stage)
    float MaxHp;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Stage)
    float Attack;

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Stage)
    int32 Count;
};

이 데이터를 받아 스테이지 적을 불러오는 스테이지 클래스를 만들었다

IFStage.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "Stage/IFStage.h"
#include "AI/IFEnemy.h"
#include "Components/SceneComponent.h"
#include "Kismet/KismetMathLibrary.h"

// Sets default values
AIFStage::AIFStage()
{
	SceneComponent = CreateDefaultSubobject<USceneComponent>(TEXT("SceneComponent"));
	SetRootComponent(SceneComponent);

	static ConstructorHelpers::FObjectFinder<UDataTable> StageDataTable
	(TEXT("/Game/InFiniteFighter/Miscellaneous/DataTable/DT_StageTable.DT_StageTable"));
	if (StageDataTable.Succeeded())
	{
		const UDataTable* DataTable = StageDataTable.Object;

		TArray<uint8*> ValueArray;
		DataTable->GetRowMap().GenerateValueArray(ValueArray);
		Algo::Transform(ValueArray, StageTable, [](uint8* Value) { return *reinterpret_cast<FIFStageTable*>(Value); });
	}

	MaxLevel = StageTable.Num();

	CurrentLevel = 1;
}

void AIFStage::BeginPlay()
{
	SetStage();
}

void AIFStage::SetStage()
{ 
	int32 SpawnNumber = StageTable[CurrentLevel].Count;
	for (int i = 0; i < SpawnNumber; ++i)
	{
		float Radius = 750.0f;
		FVector RandomPoint = GetActorLocation() + UKismetMathLibrary::RandomUnitVector() * FMath::FRandRange(0.0f, Radius);
		// RandomPoint.Z = 0;
		AIFEnemy* Enemy = GetWorld()->SpawnActorAbsolute<AIFEnemy>(RandomPoint, FRotator::ZeroRotator);
	}
}

아직은 스테이지를 세팅하는 함수만 존재하지만, 앞으로 스테이지 클리어, 보상 획득 등의 함수들을 추가해주도록 하겠다


적 생성 연출

간단하게 이펙트와 생성시의 애니메이션 호출을 사용해 적이 나타나는 연출을 구현했다

이는 대쉬 이펙트와

이를 애니메이션에 추가하고,

dissolve 효과를 반대로 역재생함으로서 완성했다


이번주에 애셋 찾기와 시네카메라에 너무 많은 시간을 쏟으며 생각보다 많은 양을 개발하지 못했다

앞으로 약 3주정도 남았는데 최대한 빠르게 남은 요소들을 개발해야겠다

profile
토비폭스가 되고픈 게임 개발자

2개의 댓글

comment-user-thumbnail
2023년 7월 3일

github에 푸시하시겠습니까?

1개의 답글