UE4

[UE4] 공격 시 조금씩 앞으로 가는 기능 구현하기

Honey Badger 2022. 10. 22. 22:49

구현방법

  구글링과 유튜브를 찾아보다가 아주 쉬운 방법을 발견했다. 바로 AddImpulse함수를 사용하는 것이다. 이 함수에 관한 설명은 https://coding-hell.tistory.com/73 에 있으니 참고하자. 원리는 캐릭터에 충격을 가하는 것이다. 이렇게 되면 선형보간을 할 필요도 없어지고 CharacterMovementComponent에서 제공하는 함수이므로 물리가 적용된다. 더이상 다른 물체를 뚫고 나가거나 언덕을 못오를 일이 없다. 

 

1. Character헤더에 가할 힘을 변수로 선언한다. 물론 생성자에서 원하는 값으로 초기화해주도록 한다. 

UPROPERTY(VisibleInstanceOnly, BlueprintReadOnly, Category = Attack, Meta = (AllowPrivateAccess = true))
float AttackMoveImpulse;//미세전진에 가할 힘

 

2. Attack이 시작될때마다 호출되는 함수에 다음과 같이 넣어주면 완성이다!

void AMyCharacter::AttackStartComboState()
{
	this->GetCharacterMovement()->AddImpulse(GetActorForwardVector() * AttackMoveImpulse, true); //공격 시 미세전진
}

 

 

 

 

Warning! 밑에 있는 코드는 예전에 구현한 것인데 물리도 적용안되고 버그가 아주 난리나게 많은 코드니 안보는 걸 추천.. 물리 적용 안받고 단순 위치 이동만 하고싶다면 밑의 코드가 도움이 될지도모름.

삽질 & 구현 방법

   간단히 생각해보면 공격을 구현한 함수에 캐릭터를 앞으로 조금 이동시키는 함수만 넣어주면 해결될 것 같았다. 그래서 Axis입력값으로 캐릭터 이동시킬때 사용하던 AddMovementInput()를 사용하여 이동시켜보려 하였다. 그러나 어떤 인자 값을 넣던 캐릭터는 꿈쩍도 하지 않았고 믿고 있던 언리얼 Document마저 이러한 내용은 설명해주지 않았다. 그러던 중 찾은 단비같은 블로그..!  https://midason.tistory.com/423 1,2번째 인자 값이 어떠한 큰 값을 적용해도 결국 나중에 크기 1의 단위 벡터로 변해버리기에 캐릭터는 움직이지 않았던 것이었다!

 

  그래서 CharacterMovement 컴포넌트에 MoveSmooth라는 함수가 있기에 써보았는데 이름과 달리 전혀 Smooth하지 않았고, 이를 부드러워보이게 하려고 카메라 렉도 설정해보고 인자값도 공부해봤지만.. 내 지식으론 선형보간 없이 부드럽게 조금씩 움직이는 캐릭터 움직임을 구현할 수 없었다.

 

  그래서!!! SetActorLocation으로 위치를 설정하고 선형보간으로 부드러운 움직임을 직접 만들어주었다. 이 과정에서 캐릭터가 갑자기 무빙워크를 타지않나.. 제자리 달리기를 하지않나.. 수많은 오류가 존재했지만 언제나 그랬듯 결국 해냈다..!  그런데 위의 블로그에 따르면 물리가 적용되지 않고 단순 좌표에 따라 움직이는 것이라 언덕을 오르는데 무리가 있다고 한다. 일단 공격하는 중에 조금 움직이는 것이라 큰 문제가 발생할 것 같진 않다. 구현 방법을 알아보자..

 

1. 변수 설정

UPROPERTY(VisibleInstanceOnly, BlueprintReadOnly, Category = Attack, Meta = (AllowPrivateAccess = true))
bool bCanAttackSmallMove; //공격미세이동여부.

UPROPERTY(VisibleInstanceOnly, BlueprintReadOnly, Category = Attack, Meta = (AllowPrivateAccess = true))
FVector ExpectedAttackLocation; //공격미세이동목표값.

 

2. 공격을 구현한 함수에 미세이동을 true로 해주고 목표벡터를 지정해줌. 난 50.0f 만큼 전진했다.

bCanAttackSmallMove = true; //미세전진 가능
ExpectedAttackLocation = GetActorLocation() + GetActorForwardVector() * 50.0f;//전진시킬 목표위치 지정.

 

3. Tick함수에서 매프레임마다 현재위치에서 위에서 설정한 목표위치까지 선형보간 시켜줌. 어느정도 목표값에 근접하면 미세이동여부를 false처리함으로 이동 종료. (완전한 목표값에 도달하지 않는 이유는 계속된 보간으로 인한 성능 저하 방지도 있고, 공격이 끝나도 보간이 끝나지 않아 이동하려던 플레이어가 목표위치로 무한 이동하는 오류때문이다. 0.1정도로 설정하니 해결됨.)

if (bCanAttackSmallMove)
{			
	if (FMath::Abs(ExpectedAttackLocation.X - GetActorLocation().X) > 0.1)
	{
		FVector temp = FMath::Lerp(GetActorLocation(), ExpectedAttackLocation, 0.05f);
		SetActorLocation(temp);			
	}
	else
	{
		bCanAttackSmallMove = false;
		ExpectedAttackLocation = FVector::ZeroVector;
	}
}

 

 

정말 중간에 포기하고싶었지만 포기하지 않고 끝까지 해낸 과거의 나에게 박수를 보낸다... 여전히 끝나고 보면 코드 몇줄이고 별거 없어보이지만 내 힘으로 구현한 코드라는 점에 의의를 두자...!