Unity进阶–通过PhotonServer实现人物选择和多人同步–PhotonServer(四)

news2024/12/26 12:10:12

文章目录

  • Unity进阶–通过PhotonServer实现人物选择和多人同步–PhotonServer(四)
    • 服务端
    • 客户端

Unity进阶–通过PhotonServer实现人物选择和多人同步–PhotonServer(四)

服务端

  • 服务端结构如下:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SO0Ba1ul-1692427583534)(../AppData/Roaming/Typora/typora-user-images/image-20230809174547636.png)]

  • UserModel

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace PhotonServerFirst.Model.User
    {
        public class UserModel
        {
            public int ID;
            public int Hp;
            public float[] Points = new float[] { -4, 1, -2 }; 
            public UserInfo userInfo;
        }
    
        public class UserInfo
        {
            public static UserInfo[] userList = new UserInfo[] {
                new UserInfo(){ ModelID = 0, MaxHp = 100, Attack = 20, Speed = 3 },
                new UserInfo(){ ModelID = 1, MaxHp = 70, Attack = 40, Speed = 4 }
            };
            public int ModelID;
            public int MaxHp;
            public int Attack;
            public int Speed;
        } 
    }
    
    
    • Messaage

      namespace Net
      {
          public class Message
          {
              public byte Type;
              public int Command;
              public object Content;
              public Message() { }
      
              public Message(byte type, int command, object content)
              {
                  Type = type;
                  Command = command;
                  Content = content;
              }
          }
          //消息类型
          public class MessageType
          {
              //unity
              //类型
              public static byte Type_Audio = 1;
              public static byte Type_UI = 2;
              public static byte Type_Player = 3;
              //声音命令
              public static int Audio_PlaySound = 100;
              public static int Audio_StopSound = 101;
              public static int Audio_PlayMusic = 102;
              //UI命令
              public static int UI_ShowPanel = 200;
              public static int UI_AddScore = 201;
              public static int UI_ShowShop = 202;
      
              //网络
              public const byte Type_Account = 1;
              public const byte Type_User = 2;
              //注册账号
              public const int Account_Register = 100;
              public const int Account_Register_Res = 101;
              //登陆
              public const int Account_Login = 102;
              public const int Account_Login_res = 103;
      
              //选择角色
              public const int User_Select = 104; 
              public const int User_Select_res = 105; 
              public const int User_Create_Event = 106;
      
              //删除角色
              public const int User_Remove_Event = 107;
          }
      }
      
      
    • PSPeer

      using System;
      using System.Collections.Generic;
      using Net;
      using Photon.SocketServer;
      using PhotonHostRuntimeInterfaces;
      using PhotonServerFirst.Bll;
      
      namespace PhotonServerFirst
      {
          public class PSPeer : ClientPeer
          {
              public PSPeer(InitRequest initRequest) : base(initRequest)
              {
      
              }
      
              //处理客户端断开的后续工作
              protected override void OnDisconnect(DisconnectReason reasonCode, string reasonDetail)
              {
                  //关闭管理器
                  BLLManager.Instance.accountBLL.OnDisconnect(this);
                  BLLManager.Instance.userBLL.OnDisconnect(this);
              }
      
              //处理客户端的请求
              protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters)
              {
                  PSTest.log.Info("收到客户端的消息");
                  var dic = operationRequest.Parameters;
      
                  //打包,转为PhotonMessage
                  Message message = new Message();
                  message.Type = (byte)dic[0];
                  message.Command = (int)dic[1];
                  List<object> objs = new List<object>();
                  for (byte i = 2; i < dic.Count; i++)
                  {
                      objs.Add(dic[i]);
                  }
                  message.Content = objs.ToArray();
      
                  //消息分发
                  switch (message.Type)
                  {
                      case MessageType.Type_Account:
                          BLLManager.Instance.accountBLL.OnOperationRequest(this, message); 
                          break;
                      case MessageType.Type_User:
                          BLLManager.Instance.userBLL.OnOperationRequest(this, message);
                          break;
                  }
              }
          }
      }
      
      
      • UserBLL

        using Net;
        using PhotonServerFirst.Model.User;
        using PhotonServerFirst.Dal;
        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Text;
        
        namespace PhotonServerFirst.Bll.User
        {
            class UserBLL : IMessageHandler
            {
                public void OnDisconnect(PSPeer peer)
                {
                    //下线
                    UserModel user = DALManager.Instance.userDAL.GetUserModel(peer);
                    //移除角色
                    DALManager.Instance.userDAL.RemoveUser(peer);
                    //通知其他角色该角色已经下线
                    foreach (PSPeer otherpeer in DALManager.Instance.userDAL.GetuserPeers())
                    {
                        SendMessage.Send(otherpeer, MessageType.Type_User, MessageType.User_Remove_Event, user.ID);
                    }
        
                }
        
                    public void OnOperationRequest(PSPeer peer, Message message)
                {
                    switch (message.Command)
                    {
                        case MessageType.User_Select:
                            //有人选了角色
                            //创建其他角色
                            CreateOtherUser(peer, message);
                            //创建自己的角色
                            CreateUser(peer, message);
                            //通知其他角色创建自己
                            CreateUserByOthers(peer, message); 
                            break;
                    }
                }
        
                    //创建目前已经存在的角色
                    void CreateOtherUser(PSPeer peer, Message message)
                    {
                        //遍历已经登陆的角色
                        foreach (UserModel userModel in DALManager.Instance.userDAL.GetUserModels())
                        {
                            //给登录的客户端响应,让其创建这些角色 角色id 模型id 位置
                            SendMessage.Send(peer, MessageType.Type_User, MessageType.User_Create_Event, userModel.ID, userModel.userInfo.ModelID, userModel.Points);
                        }
                    }
        
                    //创建自己角色
                    void CreateUser(PSPeer peer, Message message)
                    {
                        object[] obj = (object[])message.Content;
                        //客户端传来模型id
                        int modelId = (int)obj[0];
                        //创建角色
                        int userId = DALManager.Instance.userDAL.AddUser(peer, modelId);
                        //告诉客户端创建自己的角色
                        SendMessage.Send(peer, MessageType.Type_User, MessageType.User_Select_res, userId, modelId, DALManager.Instance.userDAL.GetUserModel(peer).Points);
                    }
        
                    //通知其他角色创建自己
                    void CreateUserByOthers(PSPeer peer, Message message)
                    {
                        UserModel userModel = DALManager.Instance.userDAL.GetUserModel(peer);
                        //遍历全部客户端,发送消息
                        foreach (PSPeer otherpeer in DALManager.Instance.userDAL.GetuserPeers())
                        {
                            if (otherpeer == peer)
                            {
                                continue;
                            }
                            SendMessage.Send(otherpeer, MessageType.Type_User, MessageType.User_Create_Event, userModel.ID, userModel.userInfo.ModelID, userModel.Points);
                        }
                }
            }   
         }
        
        
      • BLLManager

        using PhotonServerFirst.Bll.User;
        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Text;
        
        namespace PhotonServerFirst.Bll
        {
            public class BLLManager
            {
                private static BLLManager bLLManager;
                public static BLLManager Instance
                {
                    get
                    {
                        if(bLLManager == null)
                        {
                            bLLManager = new BLLManager();
                        }
                        return bLLManager;
                    }
                }
                //登录注册管理
                public IMessageHandler accountBLL;
                //角色管理
                public IMessageHandler userBLL;
        
                private BLLManager()
                {
                    accountBLL = new PhsotonServerFirst.Bll.Account.AccountBLL();
                    userBLL = new UserBLL();
                }
        
            }
        }
        
        
        • UserDAL

          using System;
          using System.Collections.Generic;
          using System.Linq;
          using System.Text;
          using PhotonServerFirst.Model.User;
          
          namespace PhotonServerFirst.Dal.User
          {
              class UserDAL
              {
                  //角色保存集合
                  private Dictionary<PSPeer, UserModel> peerUserDic = new Dictionary<PSPeer, UserModel>();
                  private int userId = 1;
          
                  /// <summary>
                  ///添加一名角色
                  /// </summary>
                  /// <param name="peer">连接对象</param>
                  /// <param name="index">几号角色</param>
                  /// <returns>用户id</returns>
                  public int AddUser(PSPeer peer, int index)
                  {
                      UserModel model = new UserModel();
                      model.ID = userId++;
                      model.userInfo = UserInfo.userList[index];
                      model.Hp = model.userInfo.MaxHp;
                      if (index == 1)
                      {
                          model.Points = new float[] { 0, 2, -2 };
                      }
                      peerUserDic.Add(peer, model);
                      return model.ID;
                  }
          
                  ///<summary>
                  ///移除一名角色
                  /// </summary>
                  public void RemoveUser(PSPeer peer)
                  {
                      peerUserDic.Remove(peer);
                  }
          
          
                  ///<summary>
                  ///得到用户模型
                  ///</summary>
                  ///<param name="peer">连接对象</param>
                  ///<returns>用户模型</returns>
                  public UserModel GetUserModel(PSPeer peer){
                       return peerUserDic[peer];
                  }
          
                  ///<summary>
                  ///得到全部的用户模型
                  ///</summary>
                  public UserModel[] GetUserModels() {
                      return peerUserDic.Values.ToArray();
                  }
          
                  ///<summary>
                  ///得到全部有角色的连接对象
                  ///</summary>
                  public PSPeer[] GetuserPeers()
                  {
                      return peerUserDic.Keys.ToArray();
                  }
          
              }
          }
          
          
        • DALManager

          using PhotonServerFirst.Bll;
          using PhotonServerFirst.Dal.User;
          using System;
          using System.Collections.Generic;
          using System.Linq;
          using System.Text;
          
          namespace PhotonServerFirst.Dal
          {
              class DALManager
              {
                  private static DALManager dALManager;
                  public static DALManager Instance
                  {
                      get
                      {
                          if (dALManager == null)
                          {
                              dALManager = new DALManager();
                          }
                          return dALManager;
                      }
                  }
                  //登录注册管理
                  public AccountDAL accountDAL;
                  //用户管理
                  public UserDAL userDAL;
          
                  private DALManager()
                  {
                      accountDAL = new AccountDAL();
                      userDAL = new UserDAL();
                  }
              }
          }
          
          

客户端

  • 客户端页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fYrrhFIg-1692427583535)(../AppData/Roaming/Typora/typora-user-images/image-20230809134945235.png)]

  • 绑在panel上

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using Net;
    
    public class SelectPanel : MonoBehaviour
    {
        // Start is called before the first frame update
        void Start()
        {
            
        }
    
        // Update is called once per frame
        void Update()
        {
            
        }
    
        public void SelectHero(int modelId){
            //告诉服务器创建角色
            PhotonManager.Instance.Send(MessageType.Type_User, MessageType.User_Select, modelId);
            //摧毁选择角色页面
            Destroy(gameObject);
            //显示计分版
            UImanager.Instance.SetActive("score", true);
        }
    
    }
    
    
  • 后台持续运行

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L95228mk-1692427583536)(../AppData/Roaming/Typora/typora-user-images/image-20230809152745663.png)]

    • 建一个usermanager,绑定以下脚本

      using System.Collections;
      using System.Collections.Generic;
      using UnityEngine;
      using Net;
      
      public class UserManager : ManagerBase 
      {
          void Start(){
              MessageCenter.Instance.Register(this);
          }
      
          public override void ReceiveMessage(Message message){
              base.ReceiveMessage(message);
              //打包
              object[] obs = (object[])message.Content;
              //消息分发
              switch(message.Command){
                  case MessageType.User_Select_res:
                  selectUser(obs);
                  break;
                  case MessageType.User_Create_Event:
                  CreateotherUser(obs);
                  break;
                  case MessageType.User_Remove_Event:
                  RemoveUser(obs);
                  break;
              }
          }  
      
          public override byte GetMessageType(){
              return MessageType.Type_User;
          }
      
          //选择了自己的角色
          void selectUser(object[] objs){
              int userId =(int)objs[0];
              int modelId = (int)objs[1];
              float[] point = (float[])objs[2];
              if (userId > 0)
              {
                  //创建角色
                  GameObject UserPre = Resources.Load<GameObject>("User/" + modelId);
                  UserControll user = Instantiate(UserPre,new Vector3(point[0],point[1],point[2]),Quaternion.identity).GetComponent<UserControll>();
      
                  UserControll.ID =userId;
                  //保存到集合中
                  UserControll.idUserDic.Add(userId, user);
              }
              else {
                  Debug.Log("创建角色失败");
              }
          }
      
          //创建其他角色
          void CreateotherUser(object[] objs){
              //打包
              int userId = (int)objs[0];
              int modelId = (int)objs [1];
              float[] point = (float[])objs[2];
              GameObject UserPre = Resources.Load<GameObject>("User/" + modelId);
              UserControll user = Instantiate(UserPre, new Vector3(point[0],point[1], point[2]),Quaternion.identity).GetComponent<UserControll>();
              UserControll.idUserDic.Add(userId, user);
          }
      
          //删除一名角色
          void RemoveUser(object[] objs){
              int userId = (int)objs[0];
              UserControll user = UserControll.idUserDic[userId];
              UserControll.idUserDic.Remove(userId);
              Destroy(user.gameObject);
          }
      
      
      }
      
      
    • 给物体上绑定

      using System.Collections;
      using System.Collections.Generic;
      using UnityEngine;
      
      public class UserControll : MonoBehaviour
      {
          //保存了所有角色的集合
          public static Dictionary<int, UserControll> idUserDic = new Dictionary<int, UserControll>();
          //当前客户端角色的id
          public static int ID;
          private Animator ani;
      
          // Start is called before the first frame update
          void Start()
          {
              ani = GetComponent<Animator>();
          }
      
          // Update is called once per frame
          void Update()
          {
              
          }
      }
      
      
    • 别忘了按钮绑定

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hdlPzRk2-1692427583536)(../AppData/Roaming/Typora/typora-user-images/image-20230809174710292.png)]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/899032.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

houdini volume trail volume几种模式

1vdb from polygon 先 attribwrangle v 后vdbfrompolygon v 2 volume 3

在 Transformer 之前生成文本 Text generation before transformers

1. 在 Transformer 之前生成文本 重要的是要注意&#xff0c;生成算法并不是新的。先前的语言模型使用了一个叫做循环神经网络或RNN的架构。尽管RNN在其时代很强大&#xff0c;但由于需要大量的计算和内存来很好 地执行生成任务&#xff0c;所以它们的能力受到了限制。让我们看…

好用的消售管理系统十大排行榜

销售管理是企业经营至关重要的一环。市场上有很多销售管理系统&#xff0c;对小企业来说&#xff0c;购买和实施CRM系统昂贵且复杂。这里有一份好用的10大免费销售管理系统榜单&#xff0c;让您既可以节省成本&#xff0c;又享受到高效的销售管理。 Zoho CRM&#xff1a; Zoh…

Tesla Model S 3对比分析拆解图

文章来源&#xff1a;网络 需要特斯拉电驱样件的请&#xff1a;shbinzer &#xff08;拆车邦&#xff09; 5 款电机&#xff0c;其中扁线永磁同步电机最大功率从 202kW 提升至 220kW&#xff0c;最大扭矩从 404Nm提升至 440Nm。 Model S/X→Model 3/Y&#xff1a;双电机版本…

软考A计划-系统集成项目管理工程师-收尾管理

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 &#x1f449;关于作者 专注于Android/Unity和各种游…

2023河南萌新联赛第(五)场:郑州轻工业大学

A.买爱心气球 原题链接 : 登录—专业IT笔试面试备考平台_牛客网 博弈论 : #include <iostream> using namespace std; int t,n,m; string s1 "Alice",s2 "Bob"; int main() {cin>>t;while(t--){cin>>n>>m;if (n % 3 0) {cou…

02_BigKey

02——BigKey 一、MoreKey案例 大批量往redis里面插入2000w测试数据key 真实生产案例 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LfbSfvNL-1692427337323)(https://you-blog.oss-accelerate.aliyuncs.com/2023/202303052248850.png)] 生产上严…

购买steam余额有风险吗?以及N种被红锁的情况

购买steam余额有风险吗&#xff1f;以及N种被红锁的情况 无论是打游戏的玩家&#xff0c;还是像我们这类靠倒卖装备赚钱的小商贩&#xff0c;都面临充值美金余额的问题&#xff0c;我们现在主要是找的专业充值渠道做代充。 最近我发现群里有极个别学员通过自己的方法找到了一…

Spring源码深度解析二(AOP)

书接上文 9. AOP源码深度剖析 概述 AOP&#xff08;Aspect Orient Programming&#xff09;&#xff1a;面向切面编程&#xff1b; 用途&#xff1a;用于系统中的横切关注点&#xff0c;比如日志管理&#xff0c;事务管理&#xff1b; 实现&#xff1a;利用代理模式&#x…

【Java面试题】线程中start方法和run方法的区别?

start start作用是启动一个新线程。 当用start()开始一个线程后&#xff0c;线程就进入就绪状态&#xff0c;使线程所代表的虚拟处理机处于可运行状态&#xff0c;这意味着它可以由JVM调度并执行。但是这并不意味着线程就会立即运行。只有当CPU分配时间片时&#xff0c;这个线…

05_bitmaphyperloglogGEO

Bitmap&hyperloglog&GEO 面试问 记录对集合中的数据进行统计在移动应用中&#xff0c;需要统计每天的新增用户数和第2天的留存用户数&#xff1b;在电商网站的商品评论中&#xff0c;需要统计评论列表中的最新评论&#xff1a;在签到打卡中&#xff0c;需要统计一个月内…

Learning to Super-resolve Dynamic Scenes for Neuromorphic Spike Camera论文笔记

摘要 脉冲相机使用了“integrate and fire”机制来生成连续的脉冲流&#xff0c;以极高的时间分辨率来记录动态光照强度。但是极高的时间分辨率导致了受限的空间分辨率&#xff0c;致使重建出的图像无法很好保留原始场景的细节。为了解决这个问题&#xff0c;这篇文章提出了Sp…

亚马逊产品排名关键因素解析,通过测评干预需要具备哪些条件

亚马逊产品排名的高低意味着分配的流量多少以及销量的高低。影响产品排名的因素主要包括以下四个方面&#xff1a; 1. 产品销量 产品销量是反映产品在同类产品销售情况的一个重要指标。它在产品Listing中展示&#xff0c;并且平台每小时会更新一次该排行榜。平台算法认为&…

设计模式之状态模式(State)的C++实现

1、状态模式的提出 在组件功能开发过程中&#xff0c;某些对象的状态经常面临变化&#xff0c;不同的状态&#xff0c;其对象的操作行为不同。比如根据状态写的if else条件情况&#xff0c;且这种条件变化是经常变化的&#xff0c;这样的代码不易维护。可以使用状态模式解决这…

用ceres实现lio-sam角点匹配

文章开始先扯一堆废话&#xff0c;lio-sam作者手推平面点和角点匹配&#xff0c;对于初学者&#xff0c;尤其数学不好者学习有一定难度&#xff0c;对于工程落地和后期优化而言难度较大。本文基于主流优化库实现角点匹配&#xff0c;以下内容均为原创和作者实测干货&#xff08…

学习笔记230802---vue项目手写css样式二次悬浮状态问题

问题描述 今天在开发页面时&#xff0c;遇到一个很棘手的问题&#xff0c;需求页面做一个卡片效果&#xff0c;鼠标悬浮在卡片上&#xff0c;出现一个选项卡&#xff0c;鼠标悬浮每一项&#xff0c;文字和图标都要变成选中状态的颜色。选项卡的每一项都是通过数据循环渲染来的…

Selenium自动化测试面试必备:高频面试题及答案整理

自动化测试已经成为现代软件测试中不可或缺的一部分。在自动化测试中&#xff0c;Selenium是最受欢迎的工具之一&#xff0c;因为它可以模拟用户与Web应用程序的交互。因此&#xff0c;对于许多测试工程师来说&#xff0c;熟练掌握Selenium框架是非常重要的。如果你正在寻找一份…

CW12B-3A-RCWW12B-6A-RCW12B-10A-RCWW12B-20A-RCWW12B-30A-RCWW12B-40A-R导轨式滤波器

CW4L2-3A-R1 CW4L2-6A-R1 CW4L2-10A-R1 CW4L2-20A-R1 CW4L2-30A-R1导轨式滤波器 CW12B-3A-R CWW12B-6A-R CW12B-10A-R CWW12B-20A-R CWW12B-30A-R CWW12B-40A-R导轨式滤波器 CW12C-3A-R CWW12C-6A-R CWW12C-10A-R CW12C-20A-R CW12C-30A-R导轨式滤波器 CW4L2-3A-R…

Python学习之操作XML文件详解

概要 我们经常需要解析用不同语言编写的数据&#xff0c;Python 提供了许多第三方库来解析或拆分用其他语言编写的数据&#xff0c;今天我们来学习下 Python XML 解析器的相关功能。 什么是 XML&#xff1f; XML 是可扩展标记语言&#xff0c;它在外观上类似于 HTML&#xff…

all in one之安装zerotier(第四章)

好像zerotier国内ipv4不能使用 pve安装zerotier 内网穿透软件总结参考 安装参考教程 安装命令&#xff1a; curl -s https://install.zerotier.com | sudo bash官网 如果有以下问题&#xff0c;进行解决&#xff0c;如果没有则跳过。 问题&#xff1a;-bash: sudo: comman…