Unity:专用服务器上的网络旋转同步

时间:2018-12-06 08:58:22

标签: unity3d networking rotation synchronization dedicated-server

这可能被问了十遍,但我似乎找不到任何答案。

我有专用的用C#控制台应用程序编写的太空游戏服务器。我面临的问题是GameObject旋转的同步。我怀疑问题与万向节锁定有关,但我不确定。

这里有我的播放器移动/旋转控制器:

public class PlayerMovement : MonoBehaviour {
    [SerializeField] float maxSpeed = 40f;
    [SerializeField] float shipRotationSpeed = 60f;

    Transform characterTransform;

    void Awake()
    {
        characterTransform = transform;
    }

    void Update()
    {
        Turn();
        Thrust();
    }

    float Speed() {
        return maxSpeed;
    }

    void Turn() {
        float rotX = shipRotationSpeed * Time.deltaTime * CrossPlatformInputManager.GetAxis("Vertical");
        float rotY = shipRotationSpeed * Time.deltaTime * CrossPlatformInputManager.GetAxis("Horizontal");

        characterTransform.Rotate(-rotX, rotY, 0);
    }

    void Thrust() {
        if (CrossPlatformInputManager.GetAxis("Move") > 0) {
            characterTransform.position += shipTransform.forward * Speed() * Time.deltaTime * CrossPlatformInputManager.GetAxis("Move");
        }
    }
}

此脚本适用于我的角色对象,即船。请注意,角色对象具有子对象,该子对象本身就是飞船,并且具有固定的旋转和不变的位置。角色移动/旋转后,我将以下内容发送到服务器:position(x,y,z)and rotation(x,y,z,w)。

现在这是接收网络数据包信息并更新游戏中其他玩家的实际脚本:

public class CharacterObject : MonoBehaviour {
    [SerializeField] GameObject shipModel;

    public int guid;
    public int characterId;
    public string name;
    public int shipId;

    Vector3 realPosition;
    Quaternion realRotation;

    public void Awake() {
    }

    public int Guid { get { return guid; } }
    public int CharacterId { get { return characterId; } }

    void Start () {
        realPosition = transform.position;
        realRotation = transform.rotation;
    }

    void Update () {
        // Do nothing
    }

    internal void LoadCharacter(SNCharacterUpdatePacket cuPacket) {
        guid = cuPacket.CharacterGuid;
        characterId = cuPacket.CharacterId;
        name = cuPacket.CharacterName;
        shipId = cuPacket.ShipId;
        realPosition = new Vector3(cuPacket.ShipPosX, cuPacket.ShipPosY, cuPacket.ShipPosZ);
        realRotation = new Quaternion(cuPacket.ShipRotX, cuPacket.ShipRotY, cuPacket.ShipRotZ, cuPacket.ShipRotW);
        UpdateTransform();

        Instantiate(Resources.Load("Ships/Ship1/Ship1"), shipModel.transform);
    }

    internal void UpdateCharacter(SNCharacterUpdatePacket cuPacket) {
        realPosition = new Vector3(cuPacket.ShipPosX, cuPacket.ShipPosY, cuPacket.ShipPosZ);
        realRotation = new Quaternion(cuPacket.ShipRotX, cuPacket.ShipRotY, cuPacket.ShipRotZ, cuPacket.ShipRotW);
        UpdateTransform();
    }

    void UpdateTransform() {
        transform.position = Vector3.Lerp(transform.position, realPosition, 0.1f);
        transform.rotation = Quaternion.Lerp(transform.rotation, realRotation, 0.5f);
    }
}

您看到代码有什么问题吗?

我与2位玩家的游戏经历如下: 当我与两名玩家一起开始游戏时,它们在相同的位置(0,0,0)和相同的旋转(0,0,0)生成。 假设其他玩家仅绕X轴连续旋转。我遇到的是:

  1. 最初的90度旋转效果很好。
  2. 接下来的180度旋转物体保持原位
  3. 最后90度旋转效果很好

在第一个版本中,我没有发送四元数的'w'值,但是在第二个版本中添加了它,但没有帮助。请注意,旋转没有限制,用户可以在所有方向上无限旋转。 顺便说一句,定位很好。

我可能无法完全理解四元数,但我认为它们的目的是避免万向节锁定问题。

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

回答我自己的问题。我使用了transform.localEulerAngles而不是transform.rotation,一切似乎都很好。

现在,我唯一不确定的是万向节锁定是否可以通过此更改发生。