속성 변경

* 퓨전 프로퍼티에 대한 테스트를 하던 도중 스크립트에 문제가 생겨 새로 만들었습니다.

Player 스크립트

Netwrked는 메서드의 오버로딩처럼 파라미터를 넣는 버전이 있는듯하다.

public class Player : NetworkBehaviour
{
    // Networked 속성의 파라미터로 OnChanged라는 string 프로퍼티가 있는데
    // OnChanged는 'static void OnChanged(Changed<MyClass> changed){}' 형식의 콜백이다.
    [Networked(OnChanged = nameof(OnBallSpawned))]
    // NetworkBool처럼 true false 값이 두 가지만 있는 경우 변경사항이 감지되지 않을 수가 있으므로
    // byte/int 로 대체하고 호출할 때마다 값을 변경하는 방식으로 할수도 있다. (시각적 효과와 대역폭의 소모 중요도 차이)
    public NetworkBool spawned { get; set; }

여기선 자식의 Meshrenderer에서 Material을 찾아 따로 Material프로퍼티를 만들어주는데 이 프로젝트의 경우 Player의 Cube 메시를 Player스크립트가 있는 부모와 구분해 자식으로 가게 했으므로 자식에서 찾는 GetComponentInChildren으로 찾아오는 것 같다. -> 매번 가져오지 않고 한 번만 세팅하기 위함

Material _material;
Material material
{
    get
    {
        if (!_material)
        {
            _material = GetComponentInChildren<MeshRenderer>().material;
        }
        return _material;
    }
}

위의 Networked속성의 파라미터 형식대로 함수를 만들었다.

여기서 spawned 값이 바뀐 Player의 material의 color를 흰색으로 바꿔준다.

// struct인 Changed<T>의 T는 NetworkBehaviour를 상속받는 컴포넌트이다.
public static void OnBallSpawned(Changed<Player> changed)
{
    // changed.Behaviour가 T이다. (여기선 Player)
    changed.Behaviour.material.color = Color.white;
}

이전에 가져온 material의 Color를 Color.Lerp를 통해 현재 컬러에서 목표 컬러까지 Time.deltaTime 비율만큼 부드럽게 변하게 만들었다.

// NetworkBehaviour를 상속하는 SimulationBehaviour에 있는 메서드이다.
// 색 변화 등을 Update가 아니라 Render에서 수행하는 이유는
// Render()가 퓨전의 FixedUpdateNetwork 이후에 호출되는 것이 보장되기 때문이다.
// 또한 Runner.DeltaTime이 아니라 Time.deltaTime을 사용하는 이유는
// 렌더링 자체는 Fusion 시뮬레이션 단위인 Runner.DeltaTime이 아니고
// 유니티의 render loop에서 실행되어서 그렇다.
public override void Render()
{
    material.color = Color.Lerp(material.color, Color.blue, Time.deltaTime);
}

이후에 FixedUpdateNetwork의 마지막 부분에 spawned = !spawned를 추가하여 토글로 공을 생성할 때마다 값이 바뀌게 했다.

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 );
                    });
            }
            spawned = !spawned;
        }
    }
}

+ Recent posts