Unity:在专用服务器上通过网络进行旋转同步

Posted

技术标签:

【中文标题】Unity:在专用服务器上通过网络进行旋转同步【英文标题】:Unity: Rotation sync over network on dedicated server 【发布时间】:2018-12-06 08:58:21 【问题描述】:

这可能被问了十几次,但我似乎无法在任何地方找到答案。

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

这里有我的玩家移动/旋转控制器:

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");
        
    

此脚本应用于我的角色对象,即一艘船。请注意,角色对象有一个子对象,它是船本身,具有固定的旋转和位置,不会改变。当角色移动/旋转时,我将以下内容发送到服务器:位置(x,y,z)和旋转(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 轴连续旋转。我正在经历的是:

    前 90 度。旋转效果很好。 下一个 180 度。对象保持在原位的旋转度 最后 90 度。旋转渲染很好

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

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

任何帮助将不胜感激。

【问题讨论】:

我不知道它是否有帮助,但您能否在实际发送和接收网络内容的位置添加代码? 【参考方案1】:

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

现在我唯一不确定的是这种变化是否会发生万向节锁定。

【讨论】:

以上是关于Unity:在专用服务器上通过网络进行旋转同步的主要内容,如果未能解决你的问题,请参考以下文章

搭建虚拟专用网络服务器

专用网络的 CORS (RFC1918) 在呼叫本地服务时发出警告

ⅤPn是啥?

Unity中实现通过鼠标对物体进行旋转平移缩放

Unity:如何通过网络销毁游戏对象?

怎么在Ubuntu下搭建服务器