unity webgl联机游戏【3.手写WebSocket联机房间的创建】
Python接收这个索引值,并返回端口(如果已经没有可用端口,就返回0)并创建新的进程。创建房间时,Unity端读取下拉菜单的索引值,向服务器发送这个索引值。点击房间号切换场景,并保留端口号。
·
一、静息状态
这个状态下,unity向服务器发送100,服务器返回已创建房间的端口,如下:
void FixedUpdate()
{
requestCount+=Time.fixedDeltaTime;
// 每秒发送一次请求
if(requestCount>1f)
{
ws.Send(BitConverter.GetBytes(100));
requestCount=0;
for(int i=0;i<6;i++)
{
RoomList[i]=0;
}
}
}
if playerNum==100:
concatenated_data=b''
for hostName in room_list:
concatenated_data += struct.pack('i', hostName)
await websocket.send(concatenated_data)
continue
一、创建房间
创建房间时,Unity端读取下拉菜单的索引值,向服务器发送这个索引值
public void AddRoom()
{
if ( ws.GetState() == WebSocketState.Open)
ws.Send(BitConverter.GetBytes(dropDown.value+1));
else
Debug.Log(111);
}
Python接收这个索引值,并返回端口(如果已经没有可用端口,就返回0)并创建新的进程
# 从端口中抽取未被占用的端口号
roomHost=None
for host in PublicHostList:
if host in room_list:
continue
else:
roomHost=host
room_list.append(host)
if roomHost is None:
print('端口已满')
# 发0
await websocket.send(struct.pack('i', 0))
continue
else:
# 发送在线的房间号
concatenated_data=b''
for hostName in room_list:
concatenated_data += struct.pack('i', hostName)
await websocket.send(concatenated_data)
new_room=subprocess.Popen(['python3', 'roomServer.py'] + [str(playerNum),str(roomHost)])
new_rooms.append(new_room)
三、进入房间
点击房间号切换场景,并保留端口号
四、完整代码如下:
服务端
import asyncio
import websockets
import struct
import subprocess
# 房间列表,房间内参数:人数;房间号(端口号)
room_list=[]
# 开放端口号
PublicHostList=[80]
# 活跃的房间
new_rooms=[]
# WebSocket服务器处理客户端连接的异步函数
async def echo(websocket):
try:
# 异步接收客户端发送的数据
async for data in websocket:
# 检查进程
for index,new_room in enumerate(new_rooms):
if new_room.poll() is not None:
print("房间"+str(room_list[index])+"已经结束")
new_rooms.remove(new_room)
room_list.remove(room_list[index])
# 从数据中解包玩家人数
playerNum = struct.unpack('i', data[:4])[0]
if playerNum==100:
concatenated_data=b''
for hostName in room_list:
concatenated_data += struct.pack('i', hostName)
await websocket.send(concatenated_data)
continue
print('请求的房间人数:'+str(playerNum))
# 从端口中抽取未被占用的端口号
roomHost=None
for host in PublicHostList:
if host in room_list:
continue
else:
roomHost=host
room_list.append(host)
if roomHost is None:
print('端口已满')
# 发0
await websocket.send(struct.pack('i', 0))
continue
else:
# 发送在线的房间号
concatenated_data=b''
for hostName in room_list:
concatenated_data += struct.pack('i', hostName)
await websocket.send(concatenated_data)
new_room=subprocess.Popen(['python3', 'roomServer.py'] + [str(playerNum),str(roomHost)])
new_rooms.append(new_room)
except websockets.exceptions.ConnectionClosed:
print("连接已关闭")
# 启动WebSocket服务器的异步函数
async def main():
# 启动WebSocket服务器
async with websockets.serve(echo, "0.0.0.0", 3389):
# 保持服务器运行
await asyncio.Future()
# 运行WebSocket服务器
asyncio.run(main())
客户端
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using HybridWebSocket;
using System;
using UnityEngine.UI;
using System.Linq;
public class updateRoom : MonoBehaviour
{
// Start is called before the first frame update
private WebSocket ws; // WebSocket 实例
public string IP;
public GameObject[] RoomButtonList;
public int[] RoomList;
public Dropdown dropDown;
public float requestCount;
void Start()
{
// 创建 WebSocket 实例
ws = WebSocketFactory.CreateInstance(IP);
// 添加 OnOpen 事件监听器
ws.OnOpen += () =>
{
Debug.Log("WS connected!");
Debug.Log("WS state: " + ws.GetState().ToString());
};
// 添加 OnMessage 事件监听器
ws.OnMessage += (byte[] msg) =>
{
RevAction(msg);
};
// 添加 OnError 事件监听器
ws.OnError += (string errMsg) =>
{
Debug.Log("WS error: " + errMsg);
};
// 添加 OnClose 事件监听器
ws.OnClose += (WebSocketCloseCode code) =>
{
Debug.Log("WS closed with code: " + code.ToString());
};
ws.Connect();
}
void OnDestroy()
{
if (ws != null)
{
ws.Close();
}
}
void RevAction(byte[] msg)
{
for(int i=0;i<msg.Length/4;i++)
{
int roomHost=BitConverter.ToInt32(msg, i*4);
Debug.Log(roomHost);
RoomList[i]=roomHost;
}
}
void FixedUpdate()
{
requestCount+=Time.fixedDeltaTime;
// 每秒发送一次请求
if(requestCount>1f)
{
ws.Send(BitConverter.GetBytes(100));
requestCount=0;
for(int i=0;i<6;i++)
{
RoomList[i]=0;
}
}
// 给发送
for(int i=0;i<6;i++)
{
RoomButtonList[i].GetComponent<enterRoom>().myHost=RoomList[i];
Transform child = RoomButtonList[i].transform.GetChild(0);
// 检查子对象是否有Text组件
Text childText = child.gameObject.GetComponent<Text>();
if (childText != null)
{
// 修改Text组件的文本
if(RoomList[i]!=0)
childText.text = "房间号:"+RoomList[i];
else
childText.text = "";
}
}
}
// 添加房间
public void AddRoom()
{
if ( ws.GetState() == WebSocketState.Open)
ws.Send(BitConverter.GetBytes(dropDown.value+1));
else
Debug.Log(111);
}
}
客户端场景切换
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class enterRoom : MonoBehaviour
{
public int myHost;
public SaveParam SaveParam;
// Start is called before the first frame update
void Start()
{
GetComponent<Button>().onClick.AddListener(EnterRoom);
}
// Update is called once per frame
void Update()
{
}
// 加入房间
public void EnterRoom()
{
if(myHost==0)
return;
// 跳转场景
SceneManager.LoadScene("双人房");
// 保存端口
SaveParam.Host=myHost;
}
// 退出房间
public void OutRoom()
{
SceneManager.LoadScene("Start");
}
}
更多推荐
所有评论(0)