This document is about: FUSION 1
SWITCH TO

수정중인 페이지 입니다.

3 - 이동 & 카메라

개요

Fusion 103 공유에서 기존 씬은 플레이어 입력에 기반한 플레이어 움직임과 올바른 플레이어 객체를 따르는 1인칭 카메라를 추가하여 확장됩니다.

플레이어 이동

Fusion의 경우 이동과 같은 모든 틱을 업데이트하는 게임 플레이 코드가 Update / FixedUpdate에서 실행되어서는 안 됩니다. 대신 FixedUpdateNetwork를 사용해야 합니다. 그러면 이동이 원활해지고 모든 클라이언트에 정확하게 보간 됩니다.

새 스크립트를 만들고 이름을 PlayerMovement로 지정합니다. MonoBehaviour가 아닌 NetworkBehaviour에서 상속되도록 하고 다음 코드를 스크립트에 추가합니다:

C#

private CharacterController _controller;

public float PlayerSpeed = 2f;

private void Awake() {
    _controller = GetComponent<CharacterController>();
}

public override void FixedUpdateNetwork()
{
    // Only move own player and not every other player. Each player controls its own player object.
    if (HasStateAuthority == false)
    {
        return;
    }

    Vector3 move = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")) * Runner.DeltaTime * PlayerSpeed;

    
    _controller.Move(move);

    if (move != Vector3.zero)
    {
        gameObject.transform.forward = move;
    }
}

HasStateAuthority는 클라이언트가 객체를 제어하는지를 확인하는 데 사용될 수 있으며, NetworkTransform은 변경 사항을 StateAuthority에서 다른 모든 클라이언트에게 동기화할 뿐입니다. 다른 클라이언트가 객체의 위치를 변경하면 해당 변경 사항은 로컬 변경 사항에 불과하며, 향후 네트워크의 데이터로 재정의됩니다.

FixedUpdateNetwork에서 수행할 때 항상 Runner.DeltaTime를 사용합니다!

플레이어 프리팹에 PlayerMovement 컴포넌트를 추가합니다.

카메라

카메라를 설정하는 방법은 여러 가지가 있으며(3인칭, 1인칭 등) 이를 구현하는 방법도 다릅니다. 멀티 플레이어 게임에서는 종종 로컬 플레이어 객체를 따르는 단일 카메라가 필요합니다. 이를 구현하는 일반적인 방법은 두 가지입니다.

  1. 로컬 플레이어 객체가 생성되면 카메라를 인스턴스화합니다.
  2. 카메라를 씬의 일부로 가지고 있습니다. 로컬 플레이어 객체가 생성되면 카메라를 찾고 카메라의 대상을 설정합니다.

이 단계에서는 두 번째 접근 방식이 사용됩니다.

새 스크립트를 만들고 FirstPersonCamera라는 이름으로 저장합니다. 여기에 다음 코드를 추가합니다:

C#

using UnityEngine;

public class FirstPersonCamera : MonoBehaviour
{
    public Transform Target;
    public float MouseSensitivity = 10f;

    private float vertialRotation;
    private float horizontalRotation;
    
    void LateUpdate()
    {
        if (Target == null)
        {
            return;
        }

        transform.position = Target.position;
        
        float mouseX = Input.GetAxis("Mouse X");
        float mouseY = Input.GetAxis("Mouse Y");

        vertialRotation -= mouseY * MouseSensitivity;
        vertialRotation = Mathf.Clamp(vertialRotation, -70f, 70f);

        horizontalRotation += mouseX * MouseSensitivity;

        transform.rotation = Quaternion.Euler(vertialRotation, horizontalRotation, 0);
    }
}

이것은 매우 간단한 1인칭 카메라 구현입니다. 코드에는 멀티플레이어 요소가 포함되어 있지 않습니다. 이 카메라를 Cinemachine을 포함한 대상 객체와 함께 작동하는 다른 카메라 설정으로 교체할 수 있습니다.

FirstPersonCameraMainCamera 게임 오브젝트에 올려놓습니다. 대상을 드래그할 필요가 없습니다. 대상은 런타임에 코드에 의해 설정됩니다.

Add Networking

대상을 지정하려면 PlayerMovement 스크립트를 엽니다. 카메라를 저장할 변수를 추가합니다:

C#

public Camera Camera;

그런 다음 플레이어 객체가 생성되면 로컬 플레이어인 경우 카메라를 찾아 설정합니다.

C#

public override void Spawned()
{
    if (HasStateAuthority)
    {
        Camera = Camera.main;
        Camera.GetComponent<FirstPersonCamera>().Target = GetComponent<NetworkTransform>().InterpolationTarget;
    }
}

NetworkObjects를 초기화할 때는 항상 Awake/Start가 아닌 Spawned를 사용해야 합니다. Awake/Start에서는 아직 NetworkObject를 사용할 준비가 되지 않았을 수 있습니다.

HasStateAuthority 플레이어가 제어하는 객체에 대해서만 true이므로 다른 플레이어 객체가 아닌 로컬 플레이어 개체만 true입니다.

마지막으로, 1인칭 게임에서 플레이어 캐릭터가 보는 방향으로 움직이므로 움직임을 조금 조정합니다. Vector3 이동이 계산되는 선을 다음과 같이 대체합니다:

C#

var cameraRotationY = Quaternion.Euler(0, Camera.transform.rotation.eulerAngles.y, 0);
Vector3 move = cameraRotationY * new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")) * Runner.DeltaTime * PlayerSpeed;

버튼 눌림 처리

Update 시 유니티에서 GetButtonDown, up 등의 입력이 1회 발생합니다. Fusion에서는 FixedUpdateNetwork에서 이동 등의 게임 코드를 실행해야 합니다. 이는 버튼 상태를 정확하게 추적하기 위해서는 특별한 처리가 필요하다는 것을 의미합니다.

FixedUpdate에 버튼을 누르면 동일한 문제가 발생합니다..

FixedUpdateNetwork와 같은 입력을 캡처하는 데는 여러 가지 방법이 있습니다:

  1. Update에서 버튼 다운을 쿼리 합니다. 결과를 부울 변수에 저장하고 게임 로직에 사용하십시오. FixedUpdateNetwork의 끝에서 삭제합니다.
  2. Fusion의 NetworkInputNetworkButtons과 함께 사용합니다.
  3. 새 유니티 입력 시스템을 사용하여 업데이트 모드수동 업데이트로 설정하고 FixedUpdateNetwork()에서 InputSystem.Update를 호출합니다.
위의 옵션은 공유 모드에만 적용됩니다. Fusion을 서버/호스트 모드에서 실행할 때는 항상 NetworkInput을 사용합니다.

점프

플레이어에 대한 점프 액션을 구현하여 버튼 누르기를 처리하는 예를 구현합니다. 이 경우 이전 장에 나열된 옵션 중 옵션 1이 사용됩니다.

먼저 PlayerMovement에 다음 변수를 추가합니다:

C#

    public float JumpForce = 5f;
    public float GravityValue = -9.81f;

    private Vector3 velocity;
    private bool _jumpPressed;

_jumpPressed 변수는 버튼 상태를 추적하기 위해 사용됩니다. velocity는 공중에 떠있는 동안 KCC에 인공 중력을 더해주기 위한 것입니다.

버튼 다운 상태를 폴링 하기 위해 각 Update는 다음 코드를 추가합니다:

C#

void Update()
{
    if (Input.GetButtonDown("Jump"))
    {
        _jumpPressed = true;
    }
}

FixedUpdateNetwork의 끝에서 점프 상태를 지웁니다:

C#

_jumpPressed = false;

_controller.Move호출하는 줄을 다음으로 바꿔줍니다:

C#

_velocity.y += GravityValue * Runner.DeltaTime;
if (_jumpPressed && _controller.isGrounded)
{
    _velocity.y += JumpForce;
}
_controller.Move(move + _velocity * Runner.DeltaTime);

마지막으로 HasStateAuthority 체크 직후 다음을 추가하여 지상에서 속도를 재설정합니다:

C#

if (_controller.isGrounded)
{
    velocity = new Vector3(0, -1, 0);
}

유니티로 돌아가서 게임을 시작하고 공유 클라이언트 시작을 누릅니다. 스페이스 버튼을 누르면 캐릭터가 점프하는 모습이 나타납니다.

다음 공유 모드 기본 4 - 네트워크 속성

Back to top