기록

231002 Batch파일 경로 문제 오류 , Animation의 Start Event Function

hayo_su 2023. 10. 2. 14:31

1. 배치파일 오류

용량이 큰 파일들이 많아 Github에 올리기 어렵기 때문에 압축해서 올린 후 batch파일을 통해 한번에 풀어 사용하고 있다.

 

문제상황)

언제부터인가 배치파일에 빨간글씨가..

원인파악)

내용을 파악해보니 해당 경로에 Cube14.fbx와 Map_Offce.fbx가 이미 존재하기 때문에 덮어쓴다는 오류였다.

파일 존재 여부를 체크하는 함수를 사용했는데 왜?? 싶었다.

 

내용을 확인해 보니

IF NOT EXIST "%~dp0%ContentResources\Mesh\Map\UIBackGroundMap.fbx" (
    powershell expand-archive ContentResources\Zip\UIBackGroundMap.zip ContentResources\Mesh\Map\Office
)

IF NOT EXIST "%~dp0%ContentResources\Mesh\Map\Cube14.fbx" (
    powershell expand-archive ContentResources\Zip\Cube14.zip ContentResources\Mesh\Map\Office
)

IF NOT EXIST "%~dp0%ContentResources\Mesh\Map\Map_Office.fbx" (
    powershell expand-archive ContentResources\Zip\Map_Office.zip ContentResources\Mesh\Map\Office
)

"ContentResources\Mesh\Map\Office"경로에 생성을 하지만 "ContentResources\Mesh\Map" 경로에서 파일 존재여부를 체크해서 발생하는 문제였다.

 

문제해결)

IF NOT EXIST "%~dp0%ContentResources\Mesh\Map\Office\UIBackGroundMap.fbx" (
    powershell expand-archive ContentResources\Zip\UIBackGroundMap.zip ContentResources\Mesh\Map\Office
)

IF NOT EXIST "%~dp0%ContentResources\Mesh\Map\Office\Cube14.fbx" (
    powershell expand-archive ContentResources\Zip\Cube14.zip ContentResources\Mesh\Map\Office
)

IF NOT EXIST "%~dp0%ContentResources\Mesh\Map\Office\Map_Office.fbx" (
    powershell expand-archive ContentResources\Zip\Map_Office.zip ContentResources\Mesh\Map\Office
)

확인 경로를 변경하여 문제 해결~

 

++++++++) 오류 내용을 확인하고 싶은데 스크립트가 사라진다면

"Pause"를 마지막줄에 추가하여 내용을 확인할 수 있다.


2. Animation의 StartEvent Function

애니메이션 중 원하는 인덱스프레임에 함수를 실행하는 기능

 

하나의 애니메이션을 가지고 있는 GameEngineFBXAnimationInfo 클래스에

std::map<UINT, AnimStartFunc> StartFunc;

이를 추가한다.

 

AnimStartFunc의 내용은 다음과 같다.

struct AnimStartFunc
{
	bool bStart = false; \\ 실행했는지 체크
	std::function<void()> pFunc = nullptr; \\ functional 함수
};

StartFunction을 설정하는 함수를 추가한다

void GameEngineFBXRenderer::SetAnimationStartFunc(const std::string_view& _Name, UINT _Index, std::function<void()> _Func)
{	
	std::string sUpperName = GameEngineString::ToUpper(_Name); \\지정한 애니메이션 이름
	if (Animations.end() == Animations.find(sUpperName))
	{
		MsgAssert("해당 이름의 애니메이션이 없습니다." + sUpperName);
		return;
	}
	std::shared_ptr< GameEngineFBXAnimationInfo> Info = Animations[sUpperName];
	//std::weak_ptr<GameEngineFBXAnimationInfo> AnimInfo = Animations[sUpperName];
	if ((Info->Start > _Index) || (_Index >= Info->End))
	{
		MsgAssert("설정하려는 인덱스가 " + sUpperName + "의 최대 프레임인 " + std::to_string(Info->Start)+","+ std::to_string(Info->End) + " 을(를) 넘었습니다");
		return;
	}
	Info->StartFunc[_Index].pFunc = _Func;
	Info->StartFunc[_Index].bStart = false;

}

 

AnimationInfo가 업데이트할 때 마다 이를 실행할 수 있도록 한다.

void GameEngineFBXAnimationInfo::Update(float _DeltaTime)
{
	if (true == ParentRenderer->Pause) \\ 퍼즈상태이면 애니메이션을 돌리지 않는다.
	{
		return;
	}

	CurFrameTime += _DeltaTime;
	PlayTime += _DeltaTime;
	float CurInter = Inter; \\ 프레임마다 다른 inter을 둘 수 있기 때문에
	if (FrameTime.size() > CurFrame)
	{
		CurInter = FrameTime[CurFrame];
	}
	while (CurFrameTime >= CurInter)
	{
		CurFrameTime -= CurInter;
		++CurFrame;

		if (CurFrame >= End) \\ 마지막 프레임 경우
		{
			if (true == Loop)
			{
				CurFrame = Start;	
			}
			else
			{
				CurFrame = End - 1;
				EndValue = true;
			}

			for (std::pair<const UINT, AnimStartFunc>& PairStartFunc : StartFunc) \\ startfunction 실행여부 초기화
			{
				PairStartFunc.second.bStart = false;
			}
		}
	}
	if (StartFunc.end() != StartFunc.find(CurFrame)) \\ 현재 애니메이션 프레임에서 startfunction이 존재하고 실행하지 않았다면?
	{
		if (StartFunc[CurFrame].bStart == false && StartFunc[CurFrame].pFunc != nullptr)
		{
			StartFunc[CurFrame].pFunc();
			StartFunc[CurFrame].bStart = true;
		}
	}
}

여기서 문제가 발생하는데!!

문제 상황)

프레임이 겁나 낮은 경우 해당 프레임이 씹혀서 넘어가는 상황이 발생하고 그 때 startfunction이 실행되지 않는 문제가 발생한다는 점!

 

원인파악)

	while (CurFrameTime >= CurInter)
	{
		CurFrameTime -= CurInter;
		++CurFrame;

		if (CurFrame >= End) \\ 마지막 프레임 경우
		{
			if (true == Loop)
			{
				CurFrame = Start;	
			}
			else
			{
				CurFrame = End - 1;
				EndValue = true;
			}

			for (std::pair<const UINT, AnimStartFunc>& PairStartFunc : StartFunc) \\ startfunction 실행여부 초기화
			{
				PairStartFunc.second.bStart = false;
			}
		}
	}

이 부분에서 밀린 프레임을 모두 처리하고 startfunction을 체크하기 때문이다.

 

문제 해결)

void GameEngineFBXAnimationInfo::Update(float _DeltaTime)
{
	if (true == ParentRenderer->Pause) \\ 퍼즈상태이면 애니메이션을 돌리지 않는다.
	{
		return;
	}

	CurFrameTime += _DeltaTime;
	PlayTime += _DeltaTime;
	float CurInter = Inter; \\ 프레임마다 다른 inter을 둘 수 있기 때문에
	if (FrameTime.size() > CurFrame)
	{
		CurInter = FrameTime[CurFrame];
	}
	while (CurFrameTime >= CurInter)
	{
		CurFrameTime -= CurInter;
		++CurFrame;
		if (StartFunc.end() != StartFunc.find(CurFrame)) \\ 현재 애니메이션 프레임에서 startfunction이 존재하고 실행하지 않았다면?
		{
			if (StartFunc[CurFrame].bStart == false && StartFunc[CurFrame].pFunc != nullptr)
			{
				StartFunc[CurFrame].pFunc();
				StartFunc[CurFrame].bStart = true;
			}
		}
		if (CurFrame >= End) \\ 마지막 프레임 경우
		{
			if (true == Loop)
			{
				CurFrame = Start;	
                for (std::pair<const UINT, AnimStartFunc>& PairStartFunc : StartFunc) \\ startfunction 실행여부 초기화
				{
					PairStartFunc.second.bStart = false;
				}
			}
			else
			{
				CurFrame = End - 1;
				EndValue = true;
			}
		}
	}
	
}

CurFrame을 바꿀 때 StartFunction을 실행하도록 하였고

애니메이션 설정이 Loop로 실행하는 경우만 StartFucntion을 초기화 하도록 하였다.

 

해결~