🎮Unreal4/C++_TPS

[UE4] 총 발사(Fire), 탄착군(RandomUnitVectorInConeInDegrees ), 총알 충돌, Hit Decal&Hit Particle, 화염, 탄피, Sound, 반동(Camera Shake, AddControllerPitchInput)

공대 컴린이 2023. 3. 14. 22:14
728x90

💥 탄착군 형성

탄착군을 형성하기 위해 Random 함수로 direction을 초기화하였다.

 

Random 함수의 매개변수로 camera의 앞 방향direction으로 전달하고, 탄착군의 튕김 범위(RecoilAngle)0.75f 로 설정한 뒤 전달해주었다.

💡 RandomUnitVectorInConeInDegrees 함수

UFUNCTION(BlueprintPure, Category = "Math|Random", meta=(NotBlueprintThreadSafe))
static inline FVector RandomUnitVectorInConeInDegrees(FVector ConeDir, float ConeHalfAngleInDegrees)
{
	return RandomUnitVectorInConeInRadians(ConeDir, FMath::DegreesToRadians(ConeHalfAngleInDegrees));
}

Unit VectorNormalize 된 단위벡터를 말한다. 따라서 위 함수는 Cone(콘)모양으로 된 범위 내에서 랜덤 벡터값을 반환해주는 역할을 수행한다.

InConeInDegrees 함수 말고 다른 종류로는 InEllipticalConeInDegrees가 있는데 Elliptical이 붙은 함수는 Yaw 값과 Pitch 값을 각각 랜덤으로 입력할 수 있다. Cone In Degrees 함수는 쉽게 원 안에서 랜덤으로 나온다고 생각하면 좋다.

 

RandomUnitVectorInConeInDegrees 함수 안에서 VRandCone이라는 함수를 다시 호출하여 랜덤값을 불러오는데 Acos을 이용한다. cos이 인접변/빗변 이고 Acos인은 cos의 역함수이므로 빗변/인접변 이다. 이를 통해 회전행렬을 만들어서 사용하기 때문에 콘 모양의 랜덤값이 도출될 수 있다.


이렇게 카메라의 위치로부터 start 벡터와 end 벡터를 지정하고 DrawDebugLine으로 총알이 발사되는 Line을 그려본다면 Landom In Cone 함수로 인해 Line들이 콘 모양을 띄우게 된다.

💥 총알 충돌 - LineTraceSingle

이제 그려진 Line들을 기준으로 LineTrace를 수행하여 충돌되는 지점에 총알자국이 남도록 하였다.

 

카메라의 위치(transform)부터 카메라의 Forward 방향으로 start 지점이 시작되고, 설정해둔 HitDistance(3000) 만큼의 길이End 지점으로 끝마쳤다.

 

LineTraceSingle 함수를 수행하며 충돌된 결과를 HitResult에 저장하였고 충돌된 객체가 존재한다면(bBlockingHit = true) 총알이 박힌듯한 데칼과 파티클을 출력해주었다.

💥 Hit Decal & Hit Particle 출력

 

데칼(Decal)Material Instance에 속한다. 총알 자국의 Decal 인스턴스를 불러와 SpawnDecalAtLocation 함수로 출력해주었다. 이에 대한 Hit Decal 변수와 Hit Particle 변수는 Weapon의 생성자에서 초기화 해 주었다.

 

데칼이 출력될 위치는 충돌된 hitResult.Location이고, 출력될 방향충돌된 벽의 Impact Normal을 사용해야 한다. 그냥 Normal을 사용하면 대각선에 충돌됐을 때 대각선에 데칼이 출력될 수 있기때문에 벽에 출력되도록 Impact Normal을 사용하였다.

Spawn 함수는 항상 Spawn되는 객체를 반환해주기 때문에 Spawn 결과를 Decal Component 변수에 저장해두었다.

 

이후 데칼의 SetFadeScreenSize 값을 0으로 설정하여 LOD(Level Of Detail) 기능이 최대한 꺼져서 멀리에서도 잘 보이도록 설정하였다.

LOD플레이어의 거리에 따라 메시의 디테일한 부분들이 출력될 것인지 레벨 퍼포먼스를 조절할 수 있게 해준다.

 

(총알이 벽에 박힐 때 살짝 연기가 나고 불빛이 터지는) 파티클은 SpawnEmitterAtLocation 함수를 통해 출력하였는데, 파티클의 Play 방향(impactorRotation)플레이어 쪽으로 향하게 하였다.

방향을 구하기 위해 FindLookAtRotation 함수를 사용했고, 매개변수로 시작지점파티클이 출력될 충돌 지점으로 설정, 바라볼 방향충돌 검사가 시작된 TraceStart 지점으로 설정하여 벽에서 플레이어방향으로 파티클이 출력되어 플레이어가 파티클을 볼 수 있게 하였다.

💥 화염, 탄피 Particle 출력

총알 발사 시 총구에서 연기가 뿜어져 나오는 효과와, 발사된 총알의 탄피가 바닥으로 떨어지는 효과를 구현하기 위해 각각의 파티클 출력 위치에 소켓을 만들어주었다.

 

이후 SpawnEmitterAttached 함수를 통해 파티클을 각각 붙여주었다.

이미 소켓의 위치를 회전하거나 이동하여 파티클의 출력 위치로 맞춰놓았기 때문에 Spawn 함수에서의 상대간격은 Zero Vector와 Zero Rotator를 전달하였다.

💥 Sound, 총의 반동(Camera Shake) 구현

이후 총소리도 붙이고, Camera Shake를 이용한 총의 반동을 구현하였다.

 

C++에서 직접 Blueprint 함수를 불러오려면 Message를 이용하면 되긴 하지만, Message는 주소로 바로 Call하는 것이 아니라 Messaging Map(Key-Value)이라는 String Type(Key Name)의 델리게이트를 거쳐서 불러와야 하므로 불러오는 속도가 느리다.

그래서 보통 C++에서 Blueprint에 있는 함수를 Call해야 할 때 C++에서 미리 정의해 둔 함수를 Blueprint에서 오버라이드한 것을 가져다 쓰는 방식을 사용한다.

 

다시 정리하자면,

1. C++ 클래스에서 Blueprint에 있는 함수를 사용하려면 Messaging System을 사용해야 한다.

 

2. 아니면 Blueprint도 C++ 부모 클래스를 상속받기 때문에 해당 C++ 부모 클래스에서 사용하려는 함수를 만들고 Blueprint 클래스에서 해당 함수를 재정의하여 사용할 수있다.

 

3. 혹은 C++에서는 Spawn만 시키는 경우 Blueprint의 함수같은것을 Call할 필요도 없기 때문에 굳이 상속받지 않고 그냥 Blueprint 클래스에 함수를 만들어 사용해도 된다.


나는 Camera Shake를 Spawn만 시킬 것이기 때문에 세번째 방식대로 Camera Shake를 구현하였다.

먼저, Matinee Camera Shake로 블루프린트를 만들어 Oscillation 값을 흔들만큼 설정해주고, 

 

Weapon의 C++ 클래스에서 해당 카메라 쉐이크를 가져왔다.

 

총의 반동은 총의 종류마다 다르기 때문에 AR4 클래스에서 초기화해주었다.

 

이렇게 가져온 Camera Shake를 이용하여 PlayerControllerPlayerCameraManager에 접근한 뒤, StartCameraShake 함수를 통해 반동을 실행하였다.

 

마지막으로 총을 연사로 발사할 때마다 반동에 의해 총구가 조금씩 위로 올라가는 것을 구현하기 위해 AddControllerPitchInput 함수로 일정 수치(0.75)만큼 위로 움직여주었다. 이때 Controller에는 음수의 Pitch 값을 전달해야 화면이 위로 올라가는 듯한 느낌을 줄 수 있으므로 - 를 곱해주었고, 살짝의 랜덤값을 곱해 일정하게 올라가지 않도록 구현하였다.

 

결과적으로 총을 발사하면 벽에 데칼과 파티클이 출력되면서 정말 총을 쏜 듯한 느낌을 구현했다.

또한 총 아래로 탄피가 떨어지는 파티클도 리얼하게 구현되었다.

 


참조

https://docs.unrealengine.com/4.27/ko/WorkingWithContent/Types/StaticMeshes/HowTo/LODs/

 

LOD 생성 및 사용

LOD 생성 및 사용 하우투입니다.

docs.unrealengine.com

728x90