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


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

我有一个用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);
}
}

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

我在游戏中与两名玩家的经验如下:当我用两个玩家开始游戏时,他们在相同的位置(0,0,0(和相同的旋转(0,0,0(产卵。假设另一个玩家仅围绕X轴连续旋转。我正在经历的是:

  1. 旋转90度后,效果良好
  2. 接下来旋转180度,对象将保持原位
  3. 最后90度的旋转效果良好

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

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

如有任何帮助,我们将不胜感激。

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

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

最新更新