무기 & 발사

개요

Weapons 컴포넌트는 플레이어 무기를 취급하는 역할을 합니다. 현재 무기 목록을 유지하고 무기 전환을 처리합니다. 또한 발사재장전과 같은 일반적인 무기 동작을 위한 인터페이스를 제공합니다. 무기를 집거나 땅에 떨어뜨릴 수 있습니다. 자세한 내용은 무기 떨구기 섹션을 참조하십시오.

무기에는 WeaponWeaponFirearm 두 가지 기본 종류가 있습니다. Weapon는 기본적인 무기를 최소로 유지하고 WeaponFirearm는 발사 로직, 탄창 처리, 분산, 반동 등 기본적인 발사 기능을 캡슐화한 것입니다.

Fusion BR의 무기와 발사체는 이 프로젝트에서 편리하기 때문에 대부분 히트 스캔 기능을 기반으로 합니다. 무기 및 발사체에 대한 보다 정교한 접근법과 다양한 발사체 접근법에 대한 보다 정교한 문서는 Fusion 발사체 샘플을 확인하십시오.

메인 화면으로

히트 스캔 무기

히트 스캔 무기는 게임의 주요 무기입니다. 발사 시 히트 스캔 무기는 레이캐스트를 사용하여 적중을 평가합니다. 모든 발사체에 대해 생성된 네트워크 객체는 없으며, 피어에 대한 시각적 효과를 계산하기 위해 원형 버퍼에 작은 ProjectileData 구조체만 저장됩니다. 히트 스캔 무기는 목표물을 향해 날아가는 더미 비주얼 전용 발사체를 만들 수 있는 옵션이 있습니다(DummyProjectile 스크립트 확인).

public struct ProjectileData : INetworkStruct
{
    public Vector3 Destination;
    [Networked, Accuracy(0.01f)]
    public Vector3 ImpactNormal { get; set; }
    public int     ImpactTagHash;
}

[Networked, Capacity(25)]
private NetworkArray<ProjectileData> _projectileData { get; }

메인 화면으로

발사체 무기

발사체 무기 (ProjectileWeapon, ThrowableWeapon)는 시간이 지남에 따라 이동하는 독립형 발사체 물체를 스폰 합니다. 발사체는 시뮬레이션 틱마다 이전 위치와 새 위치 사이에 짧은 레이캐스트를 투사합니다. 발사체 무기는 이 프로젝트에서 수류탄에만 사용됩니다. 보다 자세한 구현은 Fusion 발사체 샘플을 확인하세요.

메인 화면으로

반동

무기 반동은 연속 발사 중에 무기가 조준하는 경향이 있는 실제 무기를 기반으로 하는 일반적인 게임 행동입니다. 보통 게임에서 무기는 플레이어가 광범위한 플레이를 통해 학습하고 느낌을 학습할 수 있는 고정 또는 반 무작위 경로를 따르며, 플레이어는 입력으로 반동 효과에 대항할 수 있습니다.

Fusion BR은 반동 시스템과 함께 제공됩니다. 모든 무기는 반동 패턴(스프레이 패턴이라고도 함)을 할당할 수 있습니다. 반동 패턴은 연속 발사 동안 무기의 경로를 정의하는 스크립팅 가능한 객체입니다. 반동은 플레이어 외모의 회전에 직접적인 영향을 미치며, 플레이어들은 반동에 대항할 수 있습니다. 대응 프로세스는 반동 감소라고 하며, Agent 스크립트의 SetLookRotation 메소드에서 찾을 수 있습니다. 발사가 중지되면 모양 회전이 자동으로 초깃값으로 돌아갑니다.

Recoil pattern
분산 없이 발사할 때 반동 패턴 및 실제 탄환 구멍

반동 패턴은 연속적으로 있는 모든 총알의 정확한 위치를 정의합니다. 초기 반동 시퀀스(반동 시작 값)가 완료된 후 반동은 끝없는 루프(반동 끝없는 값)를 따르게 됩니다.

반동 위치 위에 분산이 적용되므로 분산 값에 따라 발사 무작위성이 여전히 있습니다.

메인 화면으로

동적 분산

모든 화기 무기는 분산 동작 설정이 되어 있습니다.

Weapon Dispersion

연속 발사 시 분산이 증가하며 발사 중지 후 자동으로 기본값으로 돌아갑니다. 무기 분산은 캐릭터의 상태(달리기, 공중, 조준)에 따라 더욱 배가됩니다.

Weapon Dispersion
분산과 반동 설정

메인 화면으로

관통

투사체 피어싱(투사체 관통이라고도 함)은 게임 세계의 특정 물체를 관통하는 능력입니다. 이 경우 일반적으로 피해 패널티를 받게 됩니다.

관통은 히트 스캔 무기에서 히트 처리 시 직접 계산됩니다. 모든 투사체에는 서로 다른 물질에 대한 손상 승수를 지정하는 피어싱 설정이 할당될 수 있습니다. 발사체는 데미지 배율이 0인 물체를 관통하지 않습니다. 게임 오브젝트에 할당된 유니티 Tag를 기반으로 물질을 구분하고 태그의 해시를 기반으로 런타임에 체크인합니다.

Piercing Setup

메인 화면으로

피해 감소

발사체 피해는 발사 발생지로부터 멀어질수록 떨어집니다. 피해 감소는 DummyProjectile 컴포넌트에 정의된 설정에 의해 제어됩니다.

Dummy Projectile

메인 화면으로

3인칭 발사

3인칭 발사는 플레이어가 카메라를 통해 보는 것과 플레이어 캐릭터가 게임 세계에서 자신의 위치에서 실제로 히트할 수 있는 것 사이의 차이를 다룰 필요가 있습니다.

적중률을 계산할 때는 먼저 목표 지점을 알아야 합니다. 목표 지점은 플레이어가 겨냥하는 위치를 지정하며 FixedUpdateNetwork마다 무기 스크립트에서 카메라에서 직접 레이캐스트를 발사하여 계산합니다. 발사 입력이 처리되면 무기는 목표 지점을 취하여 캐릭터 발사 위치에서 목표 지점까지 다른 광선을 발사하여 실제 히트를 얻습니다.

Third Person Shooting
3인칭 발사 다이어그램

노트: 발사 위치는 총의 총열 끝에 있지 않습니다. 원래는 총열 위치를 사용했지만, 무기 위치가 애니메이션의 영향을 받기 때문에 스트래핑과 같은 빠른 이동 시 발사 경험이 불안정했습니다. 그래서 우리는 캐릭터의 어깨 근처에 있는 고정된 발사 위치로 변경했습니다.

이러한 기본 계산 외에도 더 나은 발사 경험을 위한 몇 가지 추가 개선 사항은 다음과 같습니다:

  • 플레이어의 캐릭터에서 목표 지점에 도달할 수 없을 경우 빨간색 십자가가 표시되어 실제 목표 지점을 나타냅니다.

Red Cross
목표 지점에 도달할 수 없는 경우 빨간색 십자가가 표시됩니다

  • 발사 위치에서 대상 지점까지의 레이캐스트는 발사 위치 또는 대상 지점에 가깝지 않은 환경 적중을 무시하여 코너 문제라고 부르는 문제 행동을 완화합니다. 이렇게 하면 코너, 나무 및 기타 물체 주변의 사격 동작이 크게 개선됩니다. 플레이어는 실제로 십자선이 가리키는 곳을 쏘지만 코너 바로 옆을 겨냥할 경우 코너 뒤에서 플레이어를 쏘기 위해 약간의 여백을 도입합니다. 이러한 무시 동작은 모든 발사체 계산에 사용되는 ProjectileUtility에서 찾을 수 있습니다.

Corner Issue
발사체는 목표 지점에 도달하기 위해 코너를 무시합니다

  • 목표 지점이 플레이어 캐릭터에 가깝고 목표 지점과 캐릭터 전방 사이의 각도가 너무 클 경우 목표 지점이 전방 방향으로 일정 거리를 계산합니다.
    Angle Ignore
    십자선에 대한 각도가 너무 크면 무기가 앞으로 발사됩니다.

메인 화면으로

발사체

시간이 지남에 따라 게임 세계를 이동하는 발사체는 수류탄을 제외하고 Fusion BR에서 실제로 사용되지 않습니다. 보다 정교한 발사체 예제는 Fusion 발사체를 확인하십시오.

수류탄

수류탄은 아이템 상자에서 찾을 수 있습니다. 수류탄이 무장되어 있을 때, 작은 카운트다운은 일정 최솟값까지 수류탄 폭발 시간을 줄여줍니다(ThrowableWeapon 참조). 수류탄 발사체는 마치 보이지 않는 유탄 발사기에서 발사된 것처럼 특수 무기로 처리됩니다.

노트: 플레이어는 영숫자 키 4로 수류탄을 순환할 수 있습니다.

메인 화면으로

폭발 수류탄

폭발 객체를 스폰 하는 수류탄.

Explosive Grenade

메인 화면으로

섬광탄

수류탄이 터졌을 때 수류탄이 있는 방향을 보면 일정 거리 내에 있는 플레이어의 눈이 머는 수류탄입니다. 단순한 플레이어 장님 효과는 AgentSenses 컴포넌트에서 계산됩니다.

Flash Grenade

메인 화면으로

연막탄

연기 효과를 나타내는 수류탄.

Smoke Grenade

메인 화면으로

체력 & 피해 시스템

모든 히트는 HitData 구조체가 생성되는 HitUtility에서 처리되며 피해는 가능한 바디 부위 승수를 곱합니다. BodyPart는 피해 승수를 추가한 기본 지연 보상 Hitbox의 하위 클래스입니다(예: 머리는 1보다 큰 승수를 가지고 팔 다리는 1보다 낮은 승수를 가집니다). 그런 다음 HitData는 대상의 Health 컴포넌트에 의해 처리됩니다.

체력 컴포넌트는 모든 클라이언트에 히트를 동기화하는 데 필요한 정보만 포함하는 BodyHitData 구조체를 만듭니다. 히트는 BodyHitData 구조체의 작은 네트워크 원형 버퍼에 저장됩니다.

public struct BodyHitData : INetworkStruct
{
    public EHitAction Action;
    public float      Damage;
    [Networked, Accuracy(0.01f)]
    public Vector3    RelativePosition { get; set; }
    [Networked, Accuracy(0.01f)]
    public Vector3    Direction { get; set; }
    public PlayerRef  Instigator;
}

[Networked, Capacity(8)]
private NetworkArray<BodyHitData> _hitData { get; }
노트: 히트의 RelativePositionBodyHitData에 어떻게 저장되는지 주목하십시오. 프록시의 위치는 서버로부터 받은 마지막 두 개의 틱 사이에 보간 되므로, 피가 몸에 튀는 것과 같은 히트 효과를 올바르게 배치하는 것이 더 좋습니다.

히트 버퍼의 변화에 따라 적절한 히트 반응이 트리거 됩니다 - UI에서 히트 방향, 히트 확인 및 피해 손상 수치, 피가 퍼지는 효과.

플레이어가 다른 플레이어를 칠 때 총알의 충격과 타격 효과(피)가 즉시 나타납니다. 그러나 적중 확인(UI의 빨간색 십자 및 적중 번호)은 적중이 새 서버 상태의 일부로 수신된 후 플레이어에게 표시됩니다(적중 확인은 서버에 의해 “확인됨”). 이로 인해 네트워크 상태에 따라 약간의 지연이 발생하지만 유효한 적중 횟수만 플레이어에 표시됩니다.


기술문서 TOP으로 돌아가기