수정중인 페이지 입니다.

Fusion 104 - 물리

개요

Fusion 104는 서버 권위 있는 게임에서 Fusion이 PhysX와 어떻게 상호작용하는지 조사할 것입니다.

이 섹션의 끝부분에, 프로젝트는 플레이어가 물리적으로 제어되는 공을 생성하고 상호작용할 수 있도록 합니다.

이 주제의 상세한 설명의 지침서를 살펴보세요

메인 화면으로

설정

호스트 모드에서, Fusion은 호스트에서 물리 시뮬레이션을 수행하고 클라이언트는 이 결과를 따르지만 애플리케이션은 물리가 객체들을 제어할지라도 선택적으로 클라이언트들이 예측할 수 있도록 허용합니다.

이 기능을 켜려면 Fusion 메뉴로 이동하여 네트워크 프로젝트 구성을 선택하십시오. 이렇게 하면 Fusion 구성 파일이 인스펙터에서 열립니다. 서버 물리 모드에서 클라이언트 예측을 선택합니다.

클라이언트 예측을 활성화하면 계산 비용이 더 많이 들지만 보다 정확한 이동을 할 수 있습니다.

메인 화면으로

물리 객체

PhysX 제어 네트워크 개체(PhysX 제어되는)의 프리팹은 일반 유니티 PhysX 객체와 동일한 Rigidbody를 사용하지만 NetworkRigidbody라는 비주얼 하위 개체를 동기화하는 Fusion 컴포넌트가 다릅니다. 이것은 네트워킹에 관한 한 NetworkTransform을 대체합니다.

  1. 유니티 편집기에서 새로운 빈 GameObject를 생성합니다.
  2. GameObject에서 PhysxBall로 이름을 변경합니다.
  3. 새로운 NetworkRigidbody 컴포넌트를 추가합니다.
  4. Fusion이 누락된 NetworkObject 컴포넌트에 대해 경고를 하므로, Add Network Object를 누릅니다. PhysX 시뮬레이션에 필요하기 때문에 Fusion은 자동적으로 일반 유니티 RigidBody를 추가해 줍니다.
  5. Interpolation Data SourcePredicted로 변경하고 World Space로 설정합니다.
  6. PhysxBall에 구체 자식을 추가합니다.
  7. 모든 방향에서 자식의 스케일을 0.2로 낮춥니다.
  8. 부모 객체의 NetworkTransform 컴포넌트의 InterpolationTarget로 자식 객체를 드래그합니다.
  9. 구체에서 콜라이더를 제거합니다.
  10. 반지름이 0.1인 상위 객체에 새 구체 콜라이더를 만들어 하위 객체를 완전히 덮습니다.
  11. 게임 오브젝트에 새로운 스크립트를 추가하고 PhysxBall.cs로 이름을 변경합니다.
  12. 전체 객체를 프로젝트 폴더로 끌어 프리팹을 만듭니다.
  13. 네트워크 객체를 베이크 하기 위해 씬을 저장하고 씬에서 프리팹 인스턴스를 삭제합니다.

Ball Prefab
Ball Prefab

메인 화면으로

PhysxBall 스크립트

공이 PhysX에 의해 구동되고 NetworkRigidbody가 네트워크 데이터를 관리하기 때문에 키네마틱 형제에 비해 작업하는 데 특별한 코드가 덜 필요합니다. PhysxBall.cs에 추가가 필요한 것은 몇 초 뒤 공이 사라지는 타이머(키네마틱 공과 정확히 동일)와 초기 전진 속도를 설정하는 메소드입니다.

두 개 모두 다음과 같은 Init() 메소드에 의해 다루어집니다:

using UnityEngine;
using Fusion;

public class PhysxBall : NetworkBehaviour
{
  [Networked] private TickTimer life { get; set; }

  public void Init(Vector3 forward)
  {
    life = TickTimer.CreateFromSeconds(Runner, 5.0f);
    GetComponent<Rigidbody>().velocity = forward;
  }

  public override void FixedUpdateNetwork()
  {
    if(life.Expired(Runner))
      Runner.Despawn(Object);
  }
}

메인 화면으로

입력

볼을 스폰 하려면 키네마틱 공과 동일한 3단계에 따라 코드를 확장해야 하지만 대신 두 번째 마우스 버튼을 사용하도록 변경해야 합니다:

1. NetworkInputData

NetworkInputData.cs에서 새로운 버튼 플래그를 추가합니다:

using Fusion;
using UnityEngine;

public struct NetworkInputData : INetworkInput
{
  public const byte MOUSEBUTTON1 = 0x01;
  public const byte MOUSEBUTTON2 = 0x02;

  public byte buttons;
  public Vector3 direction;
}

메인 화면으로

2. BasicSpawner

BasicSpawner.cs에서 첫 번째와 같은 방식으로 두 번째 마우스 버튼을 폴링하고 이에 따라 플래그를 설정합니다:

  private bool _mouseButton0;
  private bool _mouseButton1;
  private void Update()
  {
    _mouseButton0 = _mouseButton0 || Input.GetMouseButton(0);
    _mouseButton1 = _mouseButton1 || Input.GetMouseButton(1);
  }

  public void OnInput(NetworkRunner runner, NetworkInput input)
  {
    var data = new NetworkInputData();

    ...

    if (_mouseButton1)
      data.buttons |= NetworkInputData.MOUSEBUTTON2;
    _mouseButton1 = false;

    input.Set(data);
  }

메인 화면으로

3. 플레이어

Player.cs는 실제 볼 프리팹을 생성하는 코드를 가지고 있기 때문에 이와 같은 프리팹 참조가 필요합니다.

[SerializeField] private PhysxBall _prefabPhysxBall;

Player는 스폰을 반드시 호출해야 하고, 이전에 생성된 Init()메소드를 사용해서 속도(상수에 최종 전진 방향을 곱하는)를 설정합니다.

public override void FixedUpdateNetwork()
{
  if (GetInput(out NetworkInputData data))
  {
    data.direction.Normalize();
    _cc.Move(5*data.direction*Runner.DeltaTime);

    if (data.direction.sqrMagnitude > 0)
      _forward = data.direction;

    if (delay.ExpiredOrNotRunning(Runner))
    {
      if ((data.buttons & NetworkInputData.MOUSEBUTTON1) != 0)
      {
        delay = TickTimer.CreateFromSeconds(Runner, 0.5f);
        Runner.Spawn(_prefabBall, 
          transform.position+_forward,
          Quaternion.LookRotation(_forward), 
          Object.InputAuthority, 
          (runner, o) =>
          {
            // Initialize the Ball before synchronizing it
            o.GetComponent<Ball>().Init();
          });
      }
      else if ((data.buttons & NetworkInputData.MOUSEBUTTON2) != 0)
      {
        delay = TickTimer.CreateFromSeconds(Runner, 0.5f);
        Runner.Spawn(_prefabPhysxBall, 
          transform.position+_forward, 
          Quaternion.LookRotation(_forward),           
          Object.InputAuthority, 
          (runner, o) =>
          {
            o.GetComponent<PhysxBall>().Init( 10*_forward );
          });
      }
    }
  }
}

마지막으로 새로운 공을 테스트하기 위해서는 생성된 프리팹을 Player 프리팹의 Prefab Physx Ball 필드에 할당하고 빌드 및 실행하세요.

기술문서 TOP으로 돌아가기