在有目的的LAN设置上,我希望Unity的NetworkTransform
仅发送每个帧。 (模式是“同步变换”,而不是刚体,等等。)
我想知道如何做到这一点..如果您仅将发送速率设置为0.00001,它实际上是否会在对象移动的每一帧中进行操作?
(Inspector界面最多允许29Hz,如果需要较小的值,只需在代码中进行设置即可。)
我也在想类似剧本的事情……
void Update() { .. SetDirtyBit( ? ); }
会这样做吗?
(而且,您在那里用作位掩码是什么?)
通过实验确定这种事情真的需要永远。显然Unity的doco是个玩笑。而且我无法用谷歌搜索任何已经想到的人。有经验吗?
更多信息。我们进行了一些实验,实际上,如果将其设置为一个很小的值,它会 似乎 同步每帧NetworkTransform
。
(当然,它没有移动也不会打扰,正如@Programmer指出的那样。)
HOV E V E R ( 不会 )对于运动物体或摄像机位置不会产生平滑的结果。我不知道为什么;它与Update循环以及更改发生的时间有关。但是您得到的是“非常好的抖动”。
我做了一个实验,仅使用Commands和Rpcs ,每帧发送一些信息(实际上是从一个客户端到另一个客户端)。
我专门使用了专用的单以太网网络,这些应用程序除了在每帧(即使用Command / Rpc进行“手动”发送)信息(即在Update()上)之外几乎没有做任何事情。
实际上,它静止会丢弃许多帧,通常不会发送。 (比方说,它在10秒内损失了10或20。)
悲痛!
如果您需要在局域网系统上说“每帧”发送一些信息,请不要打扰。
答案 0 :(得分:2)
如果您只是将发送速率设置为0.00001,它实际上是否会 物体正在移动的框架?
是,但是当对象的变换没有移动或旋转时,无论NetworkTransform.sendInterval
的值如何,都不会通过网络对其进行更新。
我也在想类似剧本的事情……
void Update() { .. SetDirtyBit( ? ); }
是。如果您需要为该对象发送网络更新,则需要每帧调用SetDirtyBit
。
而且,您在那里用作位掩码是什么?
SetDirtyBit
函数在技术上是SyncVar
属性的函数版本。该参数的实际记载并不多,但是如果更改了标记为SyncVar
的变量,其脏掩码将更改为1
。这也意味着,如果要为对象发送网络更新,则应将1
传递给SetDirtyBit
函数。
您还应该从带有[Command]
属性的函数中使用它,而不是直接从Update
函数中使用它。如下所示:
void Update()
{
if (isLocalPlayer)
{
CmdUpdateTransform();
}
}
[Command]
void CmdUpdateTransform()
{
SetDirtyBit(1u);
}
虽然Unity声称您可以仅使用SetDirtyBit
函数来更新转换。我不认为这是真的。该声明缺少很多信息。您将需要OnSerialize
进行序列化和发送数据,并需要OnDeserialize
进行接收和反序列化。 SetDirtyBit
函数仅用于确定要发送的数据。它用于减少使用uNET引起的带宽问题。
以下代码显示SetDirtyBit
的使用应为什么样。可能需要进行一些更改才能在您这边工作。
public class Example : NetworkBehaviour
{
private const uint SEND_POSITION = 1u;
private const uint SEND_ROTATION = 2u;
private const uint SEND_SCALE = 3u;
void Update()
{
uint dirtyBit = syncVarDirtyBits;
dirtyBit |= SEND_POSITION;
dirtyBit |= SEND_ROTATION;
dirtyBit |= SEND_SCALE;
if (isLocalPlayer)
{
CmdUpdateTransform(dirtyBit);
}
}
[Command]
void CmdUpdateTransform(uint dirtyBit)
{
SetDirtyBit(dirtyBit);
}
public override bool OnSerialize(NetworkWriter writer, bool initialState)
{
if ((this.syncVarDirtyBits & SEND_POSITION) != 0u)
{
writer.Write(this.transform.position);
}
if ((this.syncVarDirtyBits & SEND_ROTATION) != 0u)
{
writer.Write(this.transform.rotation);
}
if ((this.syncVarDirtyBits & SEND_SCALE) != 0u)
{
writer.Write(this.transform.localScale);
}
return true;
}
public override void OnDeserialize(NetworkReader reader, bool initialState)
{
if ((this.syncVarDirtyBits & SEND_POSITION) != 0u)
{
Vector3 pos = reader.ReadVector3();
}
if ((this.syncVarDirtyBits & SEND_ROTATION) != 0u)
{
Quaternion rot = reader.ReadQuaternion();
}
if ((this.syncVarDirtyBits & SEND_SCALE) != 0u)
{
Vector3 scale = reader.ReadVector3();
}
}
}
答案 1 :(得分:1)
在Unity Docs中说
如果sendInterval为零,则为该脚本设置了脏位时,更新将在帧的末尾发送。请注意,设置SyncVar的值将自动设置脏位。
因此,您可以使用NetworkSettings
使用自己的脚本using UnityEngine.Networking;
[NetworkSettings(channel = 1, sendInterval = 0.0f)]
class MyScript : NetworkBehaviour
{
[SyncVar]
int value;
}
但是SyncVar
仅适用于服务器->客户端。
但是您可以使用SetDirtyBit手动将行为设置为肮脏。
或者您也可以使用InvokeSyncEvent直接同步某些值。
Here我发现了有关脏比特的更多信息。