[60. Finishing the Pickup Widget]

 

오버레이는 여러 자식을 가질 수 있지만 Z-order 조절이 불가능하다. 모든 자식들에게 레이어 ID를 1씩 증가시키기 때문에 같은 아틀라스를 사용하더라도 드로우콜이 분리되므로 유의해서 사용해야 한다.

 

참고 : https://blog.nullbus.net/94

 

[61. Add Widget to Weapon]

 

위젯 컴포넌트를 액터에 붙여서 제작한 위젯 블루프린트를 스크린에 띄운다.

스페이스가 Screen이 아닌 World라면 추가 설정이 필요하지만 메시처럼 렌더링 되어서 오브젝트에 의해 가려질 수도 있다.

 

[64. Widget Trace When Close]

 

일정 거리 내에서 라인트레이싱이 성공한 경우에만 UI를 띄우고 싶다면 Sphere 컴포넌트를 하나 더 추가해서 Sphere에 overlap 이벤트가 발생하고 액터가 플레이어인 경우에만 띄워주면 된다.

구현 방법은 여러가지가 있겠지만 플레이어에게 겹침 여부를 알려주고 겹친 경우에만 레이트레이싱을 처리하면 틱에서 리소스가 낭비되지 않는다.

 

[66. Bind Item Name]

 

하드코딩된 값을 객체가 가지고 있는 이름으로 바꿔주기 위해 바인딩을 해주어야 한다.

 

// Item.h
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Item, meta = (AllowPrivateAccess = "true"))
FString ItemName;

 

설정 자체는 직관적이지만 Item Reference를 어떻게 참조하느냐를 해결해야 한다.

해당 위젯 블루프린트는 Item 객체가 위젯 컴포넌트로써 가지고 있기 때문에 Item에서 접근해서 참조를 설정해주어야 한다.

 

위젯 컴포넌트를 이벤트 그래프에 끌고오면 된다

 

기본값으로 Default를 설정했다

 

[68. Bind Star Opacity]

 

희귀도 역시 바인딩을 하면 되지만 이미지가 개별로 5개이기 때문에 각각 설정해주어야 한다.

이미지의 표시 여부는 알파값만 바꿔주면 되기 때문에 opacity에 바인딩을 하면 된다.

 

 

해당 노드들을 함수로 접어서 연결하면 훨씬 더 편하게 할 수 있다.

함수 내부의 Return Alpha는 지역변수이다.

 

UENUM(BlueprintType)
enum class EItemRarity : uint8
{
	EIR_Damaged UMETA(DisplayName = "Damaged"),
	EIR_Common UMETA(DisplayName = "Common"),
	EIR_Uncommon UMETA(DisplayName = "Uncommon"),
	EIR_Rare UMETA(DisplayName = "Rare"),
	EIR_Legendary UMETA(DisplayName = "Legendary"),

	EIR_MAX UMETA(DisplayName = "DefaultMax")
};

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Item, meta = (AllowPrivateAccess = "true"))
TArray<bool> ActiveStars;

 

enum class와 TArray를 이용하면 에디터에서 쉽게 볼 수 있다.

'언리얼 엔진 > UE C++ Shooter Course' 카테고리의 다른 글

[UE C++ Shooter] Aiming and Crosshairs  (0) 2022.11.05
[UE C++ Shooter] Animations  (0) 2022.10.25

[44. Aim Look Sensitivity]

 

APawn::AddControllerYawInput(Value); // X축
APawn::AddControllerPitchInput(Value) // Y축

 

마우스 감도를 따로 설정할 필요가 없이 고정적이라면 별다른 입력 함수를 구현하지 않고도 기본으로 제공되는 함수를 바인딩 시키면 된다.

다만 감도 설정이 추가되는 경우에는 함수를 Value에 설정된 값을 계산해서 넘겨주면 된다.

 

 

추가로 해당 변수가 특정 값의 범위만을 가지길 원한다면 UPROPERTY에서 지정해주면 된다.

 

UPROPERTY(meta = (ClampMin="0.0", ClampMax="1.0", UIMin="0.0", UIMax="1.0"))
// 0~1 사이의 값만 가질 수 있고 에디터의 패널에서 0~1 사이의 값만 비율로써 표기된다

 

[48. Crosshair Spread Velocity]

 

FMath::GetMappedRangeValueClamped(const Vector2D &InputRange, const Vector2D &OutputRange, const float Value);

/* 예시 */
Vector2D Input(0.f, 600.f);
Vector2D Output(0.f, 1.f);
float Result = FMath::GetMappedRangeValueClamped(Input, Output, 150.f);
// Result : 0.25f

 

Value를 InputRange 범위에 대해서 OutputRange 백분율로 반환해준다.

 

 

CrosshairSpreadMultiplier = 0.5f + CrosshairVelocityFactor; // 0.5~1.5

 

[49. Spreading the Crosshairs]

 

캐릭터의 가속과 상태에 따라 조준점이 퍼지거나 좁혀지는것이 슈팅게임의 일반적인 매커니즘이다.

캐릭터의 현재 속력를 백분율로 구해서 조준점이 벌어지는 계수에 곱하면 된다.

조준점이 4방향으로 퍼져야하기 때문에 하나의 텍스처가 아닌 조준점 각 방향의 텍스쳐를 4개 사용해야 한다.

 

(조준점의 최대 퍼짐값 * 속력 비율) 값을 화면 중앙 기준으로 빼거나 더하면 된다.

조준점 상하좌우 각각 총 4개를 해주면 된다.

 

 

[50. Crosshair In Air Factor]

 

캐릭터가 점프 등으로 공중에 있는 경우 조준점이 더 벌어지는것도 일반적인 매커니즘이다.

 

위에서 사용한 계산식에 공중 상태일 때 보간한 값을 더해주면 된다.

 

if (GetCharacterMovement()->IsFalling())
{
    CrosshairInAirFactor = FMath::FInterpTo(CrosshairInAirFactor, 2.25f, DeltaTime, 2.25f);
}
else
{
    CrosshairInAirFactor = FMath::FInterpTo(CrosshairInAirFactor, 0.f, DeltaTime, 30.f);
}

CrosshairSpreadMultiplier = 0.5f + CrosshairVelocityFactor + CrosshairInAirFactor;

 

[54. Automatic Fire]

 

bool, 타이머 핸들을 이용해서 연사를 구현할 수 있다.

 

'언리얼 엔진 > UE C++ Shooter Course' 카테고리의 다른 글

[UE C++ Shooter] Weapons  (0) 2022.11.07
[UE C++ Shooter] Animations  (0) 2022.10.25

[23. Trimming Animations]

 

애니메이션의 길이를 원하는대로 자를 수 있다.

 

[29. Blending Shooting Animations]

 

별다른 블렌드 없이 이동과 사격 애니메이션을 연결하면 위와 같이 이동 사격시 매우 어색하다.

이동과 사격 애니메이션의 상하체를 블렌드시키면 자연스러워질 것이다.

 

 

그러면 상하체를 구분할 수 있는 기준점이 있어야 하는데, 척추의 시작점을 기준으로 잡으면 적당할 것이다.

해당 본을 기준으로 블렌드된다

 

이동, 사격을 캐시포즈로 만들어준다

 

인덱스를 추가하고 본 이름은 위에서 봤던 척추의 시작점인 spine_01으로 설정한다.

 

기본은 이동이 되므로 베이스 포즈로 이동 애니메이션 캐시포즈를 지정하고 블렌드 포즈로 사격 캐시포즈를 지정한다.

 

훨씬 자연스러워졌다

 

[32. Beam Particles]

 

ParticleSystemComponent로 파티클의 속성을 지정해줄 수 있다.

 

UParticleSystemComponent* Beam = UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), BeamParticles, SocketTransform);
if (Beam)
{
    Beam->SetVectorParameter(FName("Target"), BeamEndPoint);
}

 

[33. Socket Offset]

 

SpringArm의 SocketOffset값을 설정하면 카메라가 부착되는 소켓의 위치가 해당 로컬 좌표로 설정된다.

 

[34. HUD Class and Crosshairs]

 

UI를 그리는 방법은 몇 가지가 있다.

 

그중 하나인 HUD 클래스를 만들어서 출력하는 방법을 사용한다.

HUD 블루프린트 클래스를 만들어서 게임모드의 기본 HUD로 설정해주면 된다.

Size X,Y는 해상도를 반환해준다.

 

[35. Directing Rifle Shots]

 

 

TPS 게임에서는 보통 크로스헤어에 정확하게 발사되길 기대한다. 또한 원활한 시야 확보를 위해서 캐릭터가 화면의 정중앙이 아닌 왼쪽이나 오른쪽으로 치우치게 된다.

이 때문에 레이캐스트를 한 번만 사용한다면 총알의 타격 이펙트가 의도하지 위치에 생성되므로 두 번의 레이캐스트를 통해 값을 보정하여 사용해야 한다.

위와 같이 캐릭터가 벽에 근접한 경우 에임은 벽이 아닌 옆을 가리키게 되지만 총구는 벽을 가리키고 있으므로 발사 시 총알이 벽에 가로막혀야 정상일 것이다.

하지만 총구가 아닌 카메라를 기준으로 레이캐스트가 되어있기 때문에 벽을 뚫고 발사가 된다.

 

첫 레이캐스트로 에임과 오브젝트의 충돌 여부를 판단해서 끝점을 조정하고 두번째 레이캐스트로 실제 착탄 위치를 판별한다.

연산이 모두 끝난다면 궤적을 알려주는 트레일이나 착탄 이펙트를 재생시켜주면 된다.

 

 

레이캐스트 연산을 두번해야 하는 이유는 위 그림으로 설명이 될 것이다.

 

[38. Movement Offset Yaw]

 

블렌드 스페이스를 적용하기에 앞서서 캐릭터가 이동하는 방향에 대한 각도를 구해야 한다.

캐릭터는 월드좌표에 상대적이기 때문에 속도나 방향은 캐릭터의 회전에 따라 값이 변하게된다.

그래서 기준점을 항상 0˚로 유지할 수 없다.

하지만 플레이어의 시야와 속도 회전값 두개를 연산하면 두 값의 차이에 의해 원하는 값을 구할 수 있다.

다만 기준점을 0˚로 유지하는것은 아니고 단순히 두 값을 연산한 결과에 의해 나오는 값이다.

 

FRotator AimRotation = ShooterCharacter->GetBaseAimRotation();
FRotator MovementRotation = UKismetMathLibrary::MakeRotFromX(ShooterCharacter->GetVelocity());
MovementOffsetYaw = UKismetMathLibrary::NormalizedDeltaRotator(MovementRotation, AimRotation).Yaw;

AimRotation은 월드 좌표에 상대적이고 MovementRotation은 AimRotation에 상대적이기 때문에 두 값의 차이는 캐릭터의 회전과 관계없이 언제나 일정하게 나온다. 다만 속도가 0이라면 AimRotation을 빼고있기 때문에 마우스의 회전만으로도 각이 변하게 된다.

 

이때는 캐릭터 트랜스폼의 역행렬로 속도를 변환시켜주면 된다.

언제나 0˚의 기준으로 속도의 방향을 구하기때문에 속도가 0이라면 항상 0˚가 된다.

 

[41. Jog Stop Blendspace]

 

이동 시작, 이동 중에는 애니메이션 재생에 문제가 없지만 정지 애니메이션에는 문제가 생긴다.

이유는 정지하는 순간 속도가 0이 되면서 OffsetYaw값이 AimRotation값으로 변해버리기 때문이다.

속도가 0이 아닐때 마지막 Yaw값을 저장해서 그걸 사용하면 문제를 해결할 수 있다.

'언리얼 엔진 > UE C++ Shooter Course' 카테고리의 다른 글

[UE C++ Shooter] Weapons  (0) 2022.11.07
[UE C++ Shooter] Aiming and Crosshairs  (0) 2022.11.05

+ Recent posts