Проблемы с синхронизацией через UNET в Unity3d

Я пытаюсь синхронизировать положение и вращение игрока по сети. У меня частично работает.

У меня есть 2 игрока Host и Remote. Глядя на экран хоста, я вижу правильное расположение локального и сетевого плеера. На пульте дистанционного управления я вижу правильное местоположение локального, но не сетевого проигрывателя.

Это мой скрипт синхронизации:

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;

[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(NetworkIdentity))]
public class SyncRigidbody : NetworkBehaviour {

    public float positionLerpSpeed = 10f;
    public float positionThreshold = 0.0025f;
    public float rotationLerpSpeed = 10f;
    public float rotationThreshold = 2f;

    private Rigidbody _rigidbody;
    private Vector3 _requestedPos;
    private Vector3 _lastPos;
    private Quaternion _requstedRot;
    private Quaternion _lastRot;

    void Start () {
        _rigidbody = gameObject.GetComponent<Rigidbody> ();
        if (!isLocalPlayer) {
            _rigidbody.isKinematic = true;
        }
    }

    void Update () {
        TransmitPosition ();
        TransmitRotation ();
        LerpPosition ();
        LerpQuaternion ();
    }

    void LerpPosition () {
        if (!isLocalPlayer) {
            _rigidbody.MovePosition (_requestedPos);
        }
    }

    void LerpQuaternion () {
        if (!isLocalPlayer && _requstedRot.w != 0) {
            _rigidbody.MoveRotation (_requstedRot);
        }
    }

    [Command]
    void CmdUpdateTransformPosition (Vector3 pos) {
        Debug.Log ("CmdUpdateTransformPosition: For " + gameObject.name + " to " + pos);
        _requestedPos = pos;
    }

    [Command]
    void CmdUpdateTransformRotation (Quaternion rot) {
        Debug.Log ("CmdUpdateTransformRotation: For " + gameObject.name + " to " + rot);
        _requstedRot = rot;
    }

    [Client]
    void TransmitPosition () {
        if (isLocalPlayer && Vector3.Distance (_rigidbody.position, _lastPos) > positionThreshold) {
            Debug.Log ("TransmitPosition: For " + gameObject.name + " to " + _rigidbody.position);
            CmdUpdateTransformPosition (_rigidbody.position);
            _lastPos = _rigidbody.position;
        }
    }

    [Client]
    void TransmitRotation () {
        if (isLocalPlayer && Quaternion.Angle (_rigidbody.rotation, _lastRot) > rotationThreshold) {
            Debug.Log ("TransmitRotation: For " + gameObject.name + " to " + _rigidbody.rotation);
            CmdUpdateTransformRotation (_rigidbody.rotation);
            _lastRot = _rigidbody.rotation;
        }
    }
}

Идея состоит в том, что я должен иметь возможность применить этот скрипт к любому объекту с Rigidbody, и он должен автоматически синхронизироваться по сети с локальным проигрывателем в качестве источника.

Почему на удаленных подключениях я не вижу синхронизированный объект на хосте, я вижу их все правильно?


person Justin808    schedule 07.03.2016    source источник
comment
Почему вы не используете NetworkTransform? Также обратите внимание на это.   -  person Barış Çırıka    schedule 07.03.2016


Ответы (1)


Я не знаю, поможет ли это вам, но вот два скрипта для синхронизации положения и вращения, которые я использую, которые работают для меня. Возможно, не самые оптимизированные, но они работают:

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class Player_SyncPosition : NetworkBehaviour {

private Transform myTransform;
[SerializeField] float lerpRate = 15;
[SyncVar] private Vector3 syncPos;

private Vector3 lastPos;
private float threshold = 0.5f;

void Start () {
    myTransform = GetComponent<Transform> ();
}


void FixedUpdate () {
    TransmitPosition ();
    LerpPosition ();
}

void LerpPosition () {
    if (!isLocalPlayer) {
        myTransform.position = Vector3.Lerp (myTransform.position, syncPos, Time.deltaTime * lerpRate);
    }
}

[Command]
void Cmd_ProvidePositionToServer (Vector3 pos) {
    syncPos = pos;
}

[ClientCallback]
void TransmitPosition () {
    if (isLocalPlayer && Vector3.Distance(myTransform.position, lastPos) > threshold) {
        Cmd_ProvidePositionToServer (myTransform.position);
        lastPos = myTransform.position;
    }
}
}

Вращение:

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class Player_SyncRotation : NetworkBehaviour {

private Transform myTransform;

// Object rotation vars
[SyncVar] private Quaternion syncObjectRotation;
public float rotationLerpRate = 15;

private Quaternion lastRot;
private float threshold = 5f;


private void Start() {
    myTransform = GetComponent<Transform> ();
}

private void FixedUpdate () {
    LerpRotation ();
    TransmitRotation (); 
}

private void LerpRotation() {

    if (!isLocalPlayer) {
        myTransform.rotation = Quaternion.Lerp (myTransform.rotation, syncObjectRotation, Time.deltaTime * rotationLerpRate);
    }

}

[Command]
private void Cmd_ProvideRotationToServer (Quaternion objectRotation) {
    syncObjectRotation = objectRotation;
}

[ClientCallback]
private void TransmitRotation() { // Send rotation to server
    if (isLocalPlayer && Quaternion.Angle(myTransform.rotation, lastRot) > threshold) {
        Cmd_ProvideRotationToServer (myTransform.rotation);
        lastRot = myTransform.rotation;
    }
}

}
person PeterK    schedule 20.03.2016