Unreal - 스택형 스킬 구현하기

2025. 4. 24. 23:56·Unreal5 프로젝트 다이어리

총 6스택까지 사용할수있는 스킬을 구현해보겠습니다

일단 UI는 이렇습니다

중간에있는 원은 10초동안 회전할 원형프로그래스바 이며

회전이 끝나면 바깥쪽의 6개로 나누어진 프로그래스바가 한구역이 채워집니다

 

일단 ui를 수정해줍니다

(너무구려..)

제가 마나, 포스게이지를 위해 만들었던 움직이는 메테리얼입니다

해당 노드를 복사합니다

 

해당 프로그래스바에 제가 만든 메테리얼 노드들을 넣어주고 원래있던 3vector컬러 대신 넣어줍니다

원형의 프로그래스바도 회색과 흰색으로 수정해줬습니다

그냥 원형 프로그래스바 버전입니다

 

원형의 이미지테두리도 추가해줍니다

스킬칸 최종 UI디자인이 완성되었습니다

 

그럼 이제 프로그래스바 로직을 완성해보겠습니다

1. 중간에 있는 프로그래스바는 10초마다 1이됩니다

2. 중간에 있는 프로그래스바가 1이되면 바깥쪽의 프로그래스바 게이지가 한칸이 찹니다

3. 바깥쪽에있는 게이지가 꽉 차면 중간의 프로그래스바가 사라지고 더이상 움직이지않습니다

4. 스킬을 사용시 바깥쪽에 있는 게이지가 한칸이 줄어듭니다

 

저희가 세팅해야하는건 이미지안의 메테리얼 컬렉션값을 수정해서 프로그래스바를 조절해야합니다

위젯에서 세팅해주겠습니다

파라미터컬렉션 선언해줍니다

위젯에서 만든 파라미터컬렉션을 할당해줍니다

UMaterialParameterCollectionInstance* collectionInstance;

UMaterialParameterCollectionInstance* collectionInstanceOutter;

처음에 0으로 값을 초기화해줍니다

void USwordCharacterWidget::UpdateSInnerCountDown(float coolTime)
{
	if (innerSCollection)
	{
		if (collectionInstance)
		{
			currentSCoolTime = coolTime;
			GetWorld()->GetTimerManager().SetTimer(th_InnerProgressTimer,this,&USwordCharacterWidget::StartSInnerProgressBar,0.01f,true
			);
		}
	}
}
void USwordCharacterWidget::StartSInnerProgressBar()
{
	if (collectionInstance)
	{
		float deltaProgress = 1.0f / currentSCoolTime * 0.01f; 
		currentProgress += deltaProgress;
		currentProgress = FMath::Clamp(currentProgress, 0.0f, 1.0f); 
		collectionInstance->SetScalarParameterValue(FName("Progress"), currentProgress);
		if (currentProgress >= 1.0f)
		{
			GetWorld()->GetTimerManager().ClearTimer(th_InnerProgressTimer);
		}
	}
	
}

0.01초 주기로 Progressbar게이지를 0에서 1까지 currentSCoolTime초만큼 업데이트시켜주는 함수입니다

만약 호출할떄 5초로 호출을 한다면

5초동안 업데이트 되는걸 확인할수있습니다

그러면 이제 6스택이 되기전까지 inner프로그래스바가 계속 작동하고

바깥의 outter프로그래스바가 채워지도록 해보겠습니다

Outter선언

똑같이 초기화를 해줍니다

 

중간에 현재시간을 초기화해줍니다

inner프로그래스바가 1이되면 innerStack을 증가시키고 UpdateSOutterCountDown함수를 호출시켜 

Outter프로그래스바를 증가시킵니다

innerStack이 6이되기전까지 계속 업데이트를 시킵니다

스택이0부터 6까지만 작동하며

프로그래스바가 현재 6등분되어있는 프로그래스바이니

6등분을 해줘서 progressIncrement변수에 담아줍니다

currentOutterProgress은 0에서 1사이의 변수값입니다

 

  • innerStack == 1일 때 → 1 * (1/6) = 0.1667
  • innerStack == 2일 때 → 2 * (1/6) = 0.3333
  • innerStack == 6일 때 → 1.0

이런식으로 작동합니다

 

테스트를 위해 스택을 2초로 잠시 변경한뒤 확인해보겠습니다

 

 

 

스킬사용할때 스택을 깎는 함수도 만들어줍니다

UpdateSInnerCountDown함수는 BeginPlay에서 호출시킵니다

상시로 캐릭터가 풀스택이 아닐때를 체크해서 게이지를 계속 충전하게 만들어봅니다

만약 타이머가 작동중이 아니라면

(th_InnerProgressTimer가작동중이 아니라면)

다시 타이머를 돌리는 UpdateSOutterDownStack함수를 호출합니다

 

스택이 다 차면 hidden 다시 타이머가 돌아갈때 다시 visible로 변경해줬습니다

 

 

void USwordCharacterWidget::UpdateSInnerCountDown(float coolTime)
{
	if (innerSCollection)
	{
		if (collectionInstance)
		{
			currentSCoolTime = coolTime;
			currentProgress = 0.0f; 


			if (innerProgressBar)  
			{
				innerProgressBar->SetVisibility(ESlateVisibility::Visible);  
				collectionInstance->SetScalarParameterValue(FName("Progress"), currentProgress);  
			}
			GetWorld()->GetTimerManager().SetTimer(th_InnerProgressTimer,this,&USwordCharacterWidget::StartSInnerProgressBar,0.01f,true);
		}
	}
}
void USwordCharacterWidget::StartSInnerProgressBar()
{
	if (collectionInstance)
	{
		float deltaProgress = 1.0f / currentSCoolTime * 0.01f; 
		currentProgress += deltaProgress;
		currentProgress = FMath::Clamp(currentProgress, 0.0f, 1.0f); 
		collectionInstance->SetScalarParameterValue(FName("Progress"), currentProgress);
		if (currentProgress >= 1.0f)
		{
			GetWorld()->GetTimerManager().ClearTimer(th_InnerProgressTimer);
			innerStack++;
			UpdateSOutterCountDown();

			if (innerStack >= 6)
			{
				if (collectionInstanceOutter)
				{
					innerProgressBar->SetVisibility(ESlateVisibility::Hidden);
				}
			}
			else
			{
				UpdateSInnerCountDown(currentSCoolTime);
				

			}
		}
	}
}
void USwordCharacterWidget::UpdateSOutterCountDown()
{
	if (collectionInstanceOutter)
	{
		if (innerStack >= 0 && innerStack <= 6)
		{
			float progressIncrement = 1.0f / 6.0f;  // 6등분
			float currentOutterProgress = 0.0f;
			currentOutterProgress = innerStack * progressIncrement;
			currentOutterProgress = FMath::Clamp(currentOutterProgress, 0.0f, 1.0f);
			collectionInstanceOutter->SetScalarParameterValue(FName("Progress"), currentOutterProgress);
		}
	}
	
}

void USwordCharacterWidget::UpdateSOutterDownStack()
{
	if (innerStack > 0)
	{
		innerStack--;  
		UpdateSOutterCountDown();
		if (!GetWorld()->GetTimerManager().IsTimerActive(th_InnerProgressTimer))
		{
			UpdateSInnerCountDown(currentSCoolTime);  
			
		}
	}	
}

 

그리고 스택이 있을때만 공격 가능하게 설정해줬습니다

innerprogressbar가 쿨타임마다 한바퀴돌고 1이되면 outterprogressbar가 1씩 채워지며

기술을 사용하면 스택이 깎입니다

또한 스택이 다 차면 잠시 ui가 숨겨집니다

테스트용 1초ver

 

 

최종쿨타임은 6초로 설정해줬습니다

 

 

 

 

'Unreal5 프로젝트 다이어리' 카테고리의 다른 글

Unreal - 미니맵 만들기  (0) 2025.04.25
Unreal - 마우스 커서 바꾸기  (0) 2025.04.25
Unreal - 원형 프로그래스바(ProgressBar) 만들기  (0) 2025.04.24
Unreal - Ghost Trail(고스트 트레일) 잔상  (0) 2025.04.23
Unreal - Radial Blur 기법 (신속 블러)  (0) 2025.04.22
'Unreal5 프로젝트 다이어리' 카테고리의 다른 글
  • Unreal - 미니맵 만들기
  • Unreal - 마우스 커서 바꾸기
  • Unreal - 원형 프로그래스바(ProgressBar) 만들기
  • Unreal - Ghost Trail(고스트 트레일) 잔상
lucodev
lucodev
커피와 노트북 그리고 개발
  • lucodev
    루코 개발테이블
    lucodev
  • 전체
    오늘
    어제
    • 분류 전체보기 (125) N
      • Unreal5 프로젝트 다이어리 (73)
      • Unreal5 프로젝트 다이어리2 (5) N
      • Unreal 팁 (8)
      • Unreal 디버깅 (8)
      • C++ 프로그래머스 다이어리 (23) N
        • Stack (3)
        • Hash (4)
        • Heap (2)
        • Sort (3) N
      • 코드 개인보관함 (8) N
  • 인기 글

  • 최근 글

  • 최근 댓글

  • 링크

  • 공지사항

  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 태그

    언리얼 behaviortree
    언리얼 비헤이비어트리
    언리얼 컷씬
    unreal 모션매칭
    언리얼 모션매칭
    언리얼
    unreal look at
    unreal sequence
    언리얼 behavior tree
    언리얼 시퀀스
    unreal loading
    언리얼 로딩
    언리얼 페이드 아웃
    unreal 시퀀스
    unreal 로딩
    unreal 컷씬
    언리얼 look at
    언리얼 motionmatching
    언리얼 foot step
    언리얼 로딩창
  • hELLO· Designed By정상우.v4.10.3
lucodev
Unreal - 스택형 스킬 구현하기
상단으로

티스토리툴바