본문 바로가기
언리얼엔진 개발/VR

[UnrealEngine5] VR 나사 돌리기 만들기(4)

by yeni_0224 2023. 5. 14.
728x90
반응형
궁극의 나사돌리기 유사 시뮬레이션
Unreal VR Screw Simulation

https://yeni-0224.tistory.com/entry/UnrealEngine5-%EB%82%98%EC%82%AC-%EB%8F%8C%EB%A6%AC%EA%B8%B01

 

[UnrealEngine5] VR 나사 돌리기 만들기(1)

VR 게임 나사 돌리기 유사 시뮬레이션? VR Screw Simulation https://yeni-0224.tistory.com/entry/UnrealEngine%EB%B2%84%ED%8A%BC%EC%9D%84-%EB%88%84%EB%A5%B4%EB%A9%B4-%EB%AC%B8-%EC%97%B4%EA%B3%A0-%EB%8B%AB%EA%B8%B0-C-1 [UnrealEngine5]버튼을 누

yeni-0224.tistory.com

그래서 어떨 때 회전시킬 것인가

일단 손떨리는 것 때문에 회전 값이 발생하여 나사가 움직이는 것을 막아줄 것이다.

나사가 회전에는 조금 둔감하게 만들어주겠다는 것이다.

이것도 회전값을 제한하는데 어려움이 있었다. 회전값이 음수에서 양수로 갑자기 바뀌어버리는 현상을 막을 수는 없기 때문에 최대한 잘 막아야한다고 생각했다.

그리고 드라이버가 회전하는 동안에만 나사가 회전하면서 앞으로 나와야하기 때문에 이런 조건을 bool 변수로 만들어줄 것이다.

void AScrew::bRotating()
{	
	if (driver->deltaRot > -150 && driver->deltaRot < 150)
	{
		driver->deltaRot > -15 && driver->deltaRot < 15 ? isRotating = false : isRotating = true;
	}
}

쓰레기 값을 무시할 값은 15도 부터이고

150도, -150도가 넘어가버리면 회전하지 않는 것으로 간주할 것이다.

그렇다면 이전의 Tick 식에서 수정이 필요하다

void AScrew::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	//나사가 드라이버에 붙어있을 때만 회전값이 더해진다
	if(driver->isAttaching == true)
	{
		bRotating();
		if(isRotating == true)
		{	
			if (FMath::Abs(driver->deltaRot) > 15) //미세한 회전 방지를 위한 역치 값 
			{
				rotIntAngle = FMath::RoundHalfFromZero(driver->deltaRot);
				MoveScrew();		
			}
		}		
	}
	else
	{
		rotIntAngle = 0;
	}
}

driver->deltaRot은 반올림하여 변수로 받아두고, 이게 회전한 만큼 나사가 나오도록 할 것이다.

그 변수 : rotIntAngle

그렇다면 move screw 함수도 변경해줘야한다

void AScrew::MoveScrew()
{
	//회전
	SetActorRotation(GetActorRotation() + FRotator(0, 0, -1 * rotIntAngle * 값));
	//이동 : deltaRot 증가한만큼 나사가 forwardvector로 이동한다
	SetActorLocation(GetActorLocation() + GetActorForwardVector() * rotIntAngle * 값);
}

회전값이 깔끔하게 정수로 적용될 것이다 :)

그렇다면 이제 잘 나온다

 

이제 나사가 다 나왔을 때 바닥으로 툭 떨어지게 해주어야하는데, 그 타이밍을 잡아볼 것이다

나사가 다 나왔다고 할 수 있을만큼 이동했는지 체크해줄 것이다.

void AScrew::bEnoughCameOut()
{
	//나사가 다 나온 거리인지 확인 : 20 이동하면 다 나온 것
	auto screwDist = FVector::Dist(GetActorLocation(), startLoc);
	screwDist >= 20 ? isEnoughRotated = true : isEnoughRotated = false;
}

일단 20으로 잡아놨다. 나중에 여유가 된다면 저 20이라고 지정된 값도 수식으로 변경해볼까 한다.

물론 게임 개발 기간이 종료되기 전에 여유가 있다면..!

(나사 돌리기에 잡혀있지만 머리가 과부화 되었을 때 레벨 작업도 틈틈이 해주고있다. 하... 이것도 이야기할 것이 있다..)

 

충분히 다 돌았다면 바닥으로 툭 떨어지게 할 것이다.

void AScrew::CameOutScrew()
{
	//다 나왔다면 바닥에 떨어질 것
	if(isEnoughRotated == true)
	{
		boxComp->SetSimulatePhysics(true);
	}
}

일단은 크게 작업해주지는 않았다. 일단 나사 돌리는 모든 과정이 완성되는 것이 우선이기 때문이다.

void AScrew::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	//나사가 드라이버에 붙어있을 때만 회전값이 더해진다
	if(driver->isAttaching == true)
	{
		bRotating();
		if(isRotating == true)
		{	
			if (FMath::Abs(driver->deltaRot) > 15) //미세한 회전 방지를 위한 역치 값 
			{
				bEnoughCameOut();
				if(isEnoughRotated == false)
				{
					rotIntAngle = FMath::RoundHalfFromZero(driver->deltaRot);
					MoveScrew();					
				}
				else
				{
					CameOutScrew();
				}
			}
		}		
	}
	else
	{
		rotIntAngle = 0;
	}
}

이렇게 해서 최종적으로 일단은 드라이버로 나사를 돌렸을 때 돌아가고, 다 돌아가면 바닥으로 툭 떨어진다.

이제 세부적인  설정들을 더 잡아줘야하지만 일단은 나사 돌리기의 전과정이 일단은 완성되었다. 허허

Collision Box는 원하는대로 수정해줄 것

 그리고 드라이버를 월드에 배치하면

이미 90도 돌아가있는 상태이다.

월드에 배치되었을 때 기본적으로 x 방향으로 0도 회전되어있는 상태로 고정시켜줄 것이다.

meshComp->SetWorldRotation(FRotator(0, 90, 0));

screw driver의 생성자 부분에 이 한줄 추가해주면 된다.

WorldRotation값을 지정해주면 된다는 것

728x90
반응형