// CombatComponent.h
UFUNCTION(Server, Reliable, "WithValidation <= 이게 안티치트용")
void ServerFire(const FVector_NetQuantize& TraceHitTarget, float FireDelay);
// CombatComponent.cpp
void UCombatComponent::ServerFire_Implementation(const FVector_NetQuantize& TraceHitTarget, float FireDelay)
{
// 여기엔 원하는 동작
}
// 안티 치트용 동작
// FireDelay는 클라이언트가 보낸 매개변수
bool UCombatComponent::ServerFire_Validate(const FVector_NetQuantize& TraceHitTarget, float FireDelay)
{
if (EquippedWeapon)
{
// 클라이언트가 착용 중인 무기의 FireDelay와 클라이언트가 보낸 패킷의 FireDelay를 비교
bool bNearlyEqual = FMath::IsNearlyEqual(EquippedWeapon->FireDelay, FireDelay, 0.001f);
// false를 반환할 경우 클라이언트는 즉시 메인 화면으로 돌아간다
return bNearlyEqual;
}
return true;
}
안티치트를 구현하는 걸 막연하게 상상해본 적이 있다.
로그를 확인해 비정상적인 플레이가 실재했을 경우 밴하는 것 이외엔 '개발자로서' 뭘 할 수 있는지 감이 잘 안 왔다.
마침 강의가 이 궁금증을 해소해주었다.(꽤 전에 보긴 했는데 글 적는 걸 까먹었다.)
세상에 맙소사 이렇게 간단해도 되나? 싶을 정도로 언리얼이 미리 구현해뒀다고 한다.
원리는 간단한데, FireDelay처럼 해커가 자주 건드는 변수를 클라이언트에서 보내도록 하고 서버가 이를 확인해 비정상적인 경우 게임에서 추방한다.
Damage는 무조건 서버에서 관리하지만, 총기 연사 속도 같은 경우 클라이언트도 알아야 정상적인 게임 플레이가 가능하므로 이런 변수를 건드는 경우가 많다.
UFUNCTION 매크로에 WithValidation을 추가하면 정의 가능한 함수에 Validate가 생긴다.
일단 기본적으로 false를 반환하게 되면 해당 플레이어는 메인 메뉴로 추방된다.
추가적으로 킬로그에 이름을 띄우는 등 원하는 로직도 구현해볼 수 있다.