UnityMultiplayer 多人在线服务端客户端通用架构的使用指南

Posted CoderZ1010

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UnityMultiplayer 多人在线服务端客户端通用架构的使用指南相关的知识,希望对你有一定的参考价值。

文章目录


🚩 Import

  • 在框架Package Manager中搜索并下载导入Socket模块;
  • Package包中包含Server服务端内容以及protogen工具,将其解压到工程外;

🚀 protogen使用方法

  • 编写的.proto文件放入proto文件夹中;

  • 打开run.bat文件,编辑编译指令;

  • 运行run.bat文件,生成后的.cs脚本在cs文件夹中,将其放入到Unity中即可;

注:.proto文件编译为.cs脚本后,该脚本一般不轻易改动。

  • 如果有大量的.proto文件需要编译,编辑编译指令可能会比较繁琐,因此可以使用自定义的工具Protogen Helper来自动创建run.bat文件。

代码如下:

using System.IO;
using UnityEngine;
using UnityEditor;
using System.Text;
using System.Diagnostics;

namespace Mutiplayer

    /// <summary>
    /// Proto通信协议类编译工具
    /// </summary>
    public class ProtogenHelper : EditorWindow
    
        [MenuItem("Multiplayer/Protogen Helper")]
        public static void Open()
        
            var window = GetWindow<ProtogenHelper>("Protogen Helper");
            window.maxSize = new Vector2(1000f, 60f);
            window.minSize = new Vector2(200f, 60f);
            window.Show();
        

        //根路径
        private string rootPath;
        private const string prefsKey = "Protogen.exe Path";

        private void OnEnable()
        
            rootPath = EditorPrefs.HasKey(prefsKey) ? EditorPrefs.GetString(prefsKey) : string.Empty;
        

        private void OnGUI()
        
            GUILayout.Label("protogen.exe所在路径:");
            GUILayout.BeginHorizontal();
            
                string path = GUILayout.TextField(rootPath);
                if (path != rootPath)
                
                    rootPath = path;
                    EditorPrefs.SetString(prefsKey, rootPath);
                
                if (GUILayout.Button("Browse", GUILayout.Width(55f)))
                
                    path = EditorUtility.OpenFolderPanel("选择路径", rootPath, null);
                    if (path != rootPath)
                    
                        rootPath = path;
                        EditorPrefs.SetString(prefsKey, rootPath);
                    
                
            
            GUILayout.EndHorizontal();

            if (GUILayout.Button("Create .bat"))
            
                string protoPath = rootPath + "/proto";
                if (!Directory.Exists(protoPath))
                
                    UnityEngine.Debug.Log($"<color=red>文件夹不存在</color> protoPath");
                    return;
                
                string csPath = rootPath + "/cs";
                //如果cs文件夹不存在则创建
                if (!Directory.Exists(csPath))
                
                    Directory.CreateDirectory(csPath);
                
                DirectoryInfo di = new DirectoryInfo(protoPath);
                //获取所有.proto文件信息
                FileInfo[] protos = di.GetFiles("*.proto");
                //使用StringBuilder拼接字符串
                StringBuilder sb = new StringBuilder();
                //遍历
                for (int i = 0; i < protos.Length; i++)
                
                    string proto = protos[i].Name;
                    //拼接编译指令
                    sb.Append(rootPath + @"/protogen.exe -i:proto\\" + proto + @" -o:cs\\" + proto.Replace(".proto", ".cs") + "\\r\\n");
                
                sb.Append("pause");

                //生成".bat文件"
                string batPath = $"rootPath/run.bat";
                File.WriteAllText(batPath, sb.ToString());
                //打开该文件夹
                Process.Start(rootPath);
            
        
    

🪐 客户端接口

  • Connect: 连接服务端;
/// <summary>
/// 连接服务端
/// </summary>
/// <param name="ip">服务器IP地址</param>
/// <param name="port">端口</param>
public void Connect(string ip, int port)
  • Send:发送数据;
/// <summary>
/// 发送数据
/// </summary>
/// <param name="proto">协议</param>
public void Send(IExtensible proto)
  • Close:关闭与服务端的连接;
/// <summary>
/// 关闭连接
/// </summary>
public void Close()

🌈 服务端接口

  • 向单个客户端发送数据;
/// <summary>
/// 向客户端发送协议(单点发送)
/// </summary>
/// <param name="client">客户端</param>
/// <param name="proto">协议</param>
public static void Send(Client client, IExtensible proto)
  • 向所有客户端发送数据;
/// <summary>
/// 向所有客户端发送协议(广播)
/// </summary>
/// <param name="proto">协议</param>
public static void Send(IExtensible proto)
  • 向指定客户端之外的所有客户端发送数据;
/// <summary>
/// 向指定客户端之外的所有客户端发送协议
/// </summary>
/// <param name="proto">协议</param>
/// <param name="except">不需要发送的客户端</param>
public static void Send(IExtensible proto, Client except)
  • 关闭指定客户端的连接;
/// <summary>
/// 关闭客户端连接
/// </summary>
/// <param name="client">客户端</param>
public static void Close(Client client)

🧭 数据处理

根据解析出的协议名来调用相应的处理方法:

以上是服务端对ProtoTest类型协议的处理示例,服务端通过Send将该消息转发给所有客户端。

🎨 Example

using UnityEngine;
using SK.Framework.Sockets;
using System.Collections.Generic;

 public class Example : MonoBehaviour

    private Vector2 scroll;
    private List<string> messages = new List<string>();
    private string content;
    private NetworkManager NetworkManager;

    private void OnGUI()
    
        GUI.enabled = !NetworkManager.IsConnected;
        if (GUILayout.Button("Connect", GUILayout.Width(200f), GUILayout.Height(50f)))
        
            NetworkManager.Connect("127.0.0.1", 8801);
        
        GUI.enabled = NetworkManager.IsConnected;
        if (GUILayout.Button("Disconnect", GUILayout.Width(200f), GUILayout.Height(50f)))
        
            NetworkManager.Close();
        

        GUILayout.BeginVertical("Box", GUILayout.Height(200f), GUILayout.Width(300f));
        scroll = GUILayout.BeginScrollView(scroll);
        
            for (int i = 0; i < messages.Count; i++)
            
                GUILayout.Label(messages[i]);
            
        
        GUILayout.EndScrollView();
        GUILayout.EndVertical();

        GUILayout.BeginHorizontal();
        content = GUILayout.TextField(content, GUILayout.Height(50f));
        if (GUILayout.Button("Send", GUILayout.Width(50f), GUILayout.Height(50f)))
        
            if (!string.IsNullOrEmpty(content))
            
                ProtoBuf.IExtensible proto = new proto.ProtoTest.ProtoTest()  content = content ;
                NetworkManager.Send(proto);
                content = string.Empty;
            
        
        GUILayout.EndHorizontal();
    
    private void Start()
    
        NetworkManager = GetComponent<NetworkManager>();
    

    public void OnProtoTestEvent(proto.ProtoTest.ProtoTest protoTest)
    
        messages.Add(protoTest.content);
    

Unity Multiplayer 多人在线示例工程:https://github.com/136512892/Unity-Multiplayer

git初识

git初识:

介绍:

版本控制器!!
完成 协同开发 项目,帮助程序员整合代码

软件:SVN 、 GIT

git:集群化、多分支

版本控制器 - 控制的对象是开发的项目代码
代码开发时间轴:需求1 > 版本库1 > 需求2 > 版本库2 > 版本库1 > 版本库2 

git 与SVN 区别:

SVN : 服务端    客服端  (不能直接交互) 一对多

--》服务器 炸了--》 数据丢失

GIT: 服务端    客服端 (多对多)
--》客服端可作为临时 服务端

安装:
1.下载对应版本:https://git-scm.com/download
2.安装git:在选取安装路径的下一步选取 Use a TrueType font in all console windows 选项


git 工作流程:

工作区   -------》  暂存区  -----》  服务端(管理) 交互(socket)    《----服务端(管理)

工作流程:

技术图片

基础命令:

1.将已有的文件夹 - 初始化为git仓库:
    cd 目标文件夹内部
    git init    

2.在指定目录下 - 初始化git仓库
     cd 目标目录
    git init 仓库名

3.在仓库目录终端下 - 设置全局用户
    git config --global user.name '用户名'
    git config --global user.email '用户邮箱'

注:在全局文件 C:Users用户文件夹.gitconfig新建用户信息,在所有仓库下都可以使用(默认)

4.在仓库目录终端下 - 设置局部用户
    git config user.name '用户名'
    -- 用户名
    git config user.email '用户邮箱'
    -- 用户邮箱
注:在当前仓库下的config新建用户信息,只能在当前仓库下使用
注:一个仓库有局部用户,优先使用局部用户,没有配置再找全局用户
    
5.  查看仓库状态:
    当仓库中有文件增加、删除、修改,都可以在仓库状态中查看
    >: git status  
        -- 查看仓库状态
    >: git status -s  
        -- 查看仓库状态的简约显示


--> 工作区操作:
    通过任何方式完成的文件删与改
    空文件夹不会被git记录
    
6.撤销工作区操作:改、删:

    >: git checkout .
        -- 撤销所有暂存区的提交
    >: git checkout 文件名
        -- 撤销某一文件的暂存区提交

7.  工作区内容提交到暂存区:
    >: git add .  
        -- 添加项目中所有文件
    >: git add 文件名  
        -- 添加指定文件
        
8. 撤销暂存区提交:add的逆运算:
    >: git reset HEAD .
    -- 撤销所有暂存区的提交
    >: git reset 文件名
        -- 撤销某一文件的暂存区提交

9.提交暂存区内容到版本库:

    git commit -m "版本描述信息"  # 信息要明确

10.撤销版本库提交:commit的逆运算

回滚暂存区已经提交到版本库的操作:
    查看历史版本:
        >: git log
        >: git reflog
    查看时间点之前|之后的日志:
        >: git log --after 2018-6-1
        >: git log --before 2018-6-1
        >: git reflog --after 2018-6-1
        >: git reflog --before 2018-6-1
    查看指定开发者日志
        >: git log --author author_name
        >: git reflog --author author_name
    回滚到指定版本:
        回滚到上一个版本:
            >: git reset --hard HEAD^
            >: git reset --hard HEAD~
        回滚到上三个版本:
            >: git reset --hard HEAD^^^
            >: git reset --hard HEAD~3
        回滚到指定版本号的版本:
            >: git reset --hard 版本号
            >: eg: git reset --hard 35cb292

以上是关于UnityMultiplayer 多人在线服务端客户端通用架构的使用指南的主要内容,如果未能解决你的问题,请参考以下文章

git初识

wps多人在线编辑怎么弄

怎么多人在线编辑excel表格?

网络编程遇到相关问题

我可以在不支付 Unity Multiplayer 服务的情况下使用 Unity 网络 HLAPI 吗?

多人游戏服务器