MargaretChen
Unity简单联网(二)

Unity简单联网(二)

记录实现位置同步功能中遇到的Bug

粘包问题

客户端与服务端传输数据的过程中,可能因为网络波动等原因,很多条数据连在一起,接收方会接收到一条很长很长的数据,就不能正确的进行格式化,所以需要在每条消息末尾添加‘&’, 然后在接受的时候根据‘&’分割字符串,每条消息分开处理,具体代码如下

发送端:

1
2
string str = JsonConvert.SerializeObject(message);
byte[] bytes = System.Text.Encoding.Default.GetBytes(str + "&");

接收端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int len = socket.Receive(readbuffer);
string str = System.Text.Encoding.Default.GetString(readbuffer, 0, len);
foreach (var s in str.Split('&'))
{
if (s.Length > 0)
{
lock (toDoListLock)
{
Message msg = JsonConvert.DeserializeObject<Message>(s);
todoList.Enqueue(msg);
//Debug.Log($"Enqueue: {msg}");
}
}
}

线程使用公共资源

网络编程由于具有很多阻塞方法,一般都需要使用多线程处理,就会出现多个线程同时使用一个公共资源,从而引发问题。可以将公共资源放到主线程中处理,如果确实没办法放到主线程中处理,可以使用锁,具体方法如下:

在线程中对代码块加锁,防止其他线程进入到此代码块从而冲突使用公共资源

1
2
3
4
5
6
7
8
9
private static readonly object toDoListLock = new object();

//todoList为公共资源
void fun1(){
lock (toDoListLock)
{
msg = todoList.Dequeue();
}
}

点击到游戏界面以外,游戏停止

测试的时候发现一个问题,假设有AB两个客户端, 加入我在移动B玩家,同一时间A玩家不会移动。当我鼠标点击客户端A的窗口时A玩家才移动。这是因为当鼠标点击game视图以外游戏会进入停止模式,如下图所示我在高出坠落时,点击其他应用程序角色就直接停止在半空中,当我重新点击Unity.exe后玩家才继续坠落。

pic

根据Unity文档,开发者可以调用API获取当前Application状态

详情请看:相关链接

根据Unity Discussions上的回答, 在设置中运行应用在后台运行就可以解决这个问题

勾上ProjectSetting-Player-Resolution and Presentation-Run In Background后,程序可以在后台运行,客户端也能实现实时更新

pic

后续计划

此联网功能仅仅是实现了简单的位置同步,后边准备参考Youtube上的课程
使用Netcode for GameObjects 完成带角色动画的联网功能。

Author:MargaretChen
Link:http://margaret-chen217.github.io/2023/07/30/Unity简单联网(二)/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可