【3D技术宅公社】XR数字艺术论坛  XR技术讨论 XR互动电影 定格动画

 找回密码
 立即注册

QQ登录

只需一步,快速开始

调查问卷
论坛即将给大家带来全新的技术服务,面向三围图形学、游戏、动画的全新服务论坛升级为UTF8版本后,中文用户名和用户密码中有中文的都无法登陆,请发邮件到324007255(at)QQ.com联系手动修改密码

3D技术论坛将以计算机图形学为核心,面向教育 推出国内的三维教育引擎该项目在持续研发当中,感谢大家的关注。

查看: 2388|回复: 4

[基础教程] 【PhotonEngine 学习笔记】(一)简单使用

[复制链接]
发表于 2018-12-22 19:20:48 | 显示全部楼层 |阅读模式
本帖最后由 icetone 于 2018-12-22 19:28 编辑


https://blog.csdn.net/qq_25021249/article/details/84404009
前言
关于Photon引擎的基础教程视频、文章等等网上有一大堆。我们使用该引擎也有一端时间了,主要是unity项目中的多人联机模块,这里主要总结一下学过的知识,若对他人也有所帮助,那更是极好的。

PhotonEngine简介
官方网址:https://www.photonengine.com/en-US/Photon

The world’s #1 independent networking engine and multiplayer platform — Fast, reliable, scalable. Made for anyone: indies, professional studios and AAA productions.
PhotonEngine是世界排名第一的网络开发引擎、多人网络服务平台,他快速,可靠,并可扩展。适用于所有人:独立开发者,专业工作室或是3A级别大作。

Photon SDKs
SDKs网址:https://www.photonengine.com/en-us/sdks#

Photon makes multiplayer game development across platforms easy,Last but not least for the broad support of platforms and APIs to develop for.
Photon可以轻松实现跨平台多人游戏开发,支持多种平台并且提供对应的API接口。

不同功能的SDK
1.Realtime、PUN:基于Photon云平台的服务器
2.Chat、Voice:主要用于通讯
3.SELF-HOSTED(我们主要说这个):自主添加服务器逻辑的
Photon SDKs

SDK:SELF-HOSTED
SELF-HOSTED

下载安装
下载并安装,得到以下文件夹
本地Server

依次打开:…\deploy\bin_Win64
(等会我们编写服务器逻辑的时候需要修改这个路径下的一些文件)
在这里插入图片描述

服务器端逻辑
创建自己的服务器项目(类库)
因为PhotonEngine已经完成了服务器几乎所有通讯逻辑代码,并封装成很简单的接口,我们只需要在此基础上添加自己的游戏逻辑代码。因此创建一个类库项目,最终生成一个dll,丢给Photon去执行即可。
在这里插入图片描述

导入必要的dll文件
实现最基础的通讯和日志输出功能,我们需要导入以下五个dll:
(文件目录:"…\lib")

ExitGamesLibs.dll
Photon.SocketServer.dll
PhotonHostRuntimeInterfaces.dll
ExitGames.Logging.Log4Net.dll
log4net.dll
服务器的入口和出口(继承ApplicationBase类)
using System;
using Photon.SocketServer;
using ExitGames.Logging;
using System.IO;

namespace MyServer
{
    public class MyApplication : ApplicationBase
    {
        ///日志文件输出类
        static readonly ILogger log = LogManager.GetCurrentClassLogger();

        /// <summary>
        /// 服务器开启后,自动调用该函数
        /// </summary>
        protected override void Setup()
        {
            //这四句是设置日志文件的格式
            LogManager.SetLoggerFactory(ExitGames.Logging.Log4Net.Log4NetLoggerFactory.Instance);
            log4net.GlobalContext.Properties["Photon:ApplicationLogPath"] = Path.Combine(this.ApplicationRootPath, "log");
            //输出日志文件的名字
            log4net.GlobalContext.Properties["LogFileName"] = "LenQiy_" + this.ApplicationName;
            log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo(Path.Combine(this.BinaryPath, "log4net.config")));

            ShowSysLog("服务器开启。");
        }
        /// <summary>
        /// 服务器关闭后,自动调用该函数
        /// </summary>
        protected override void TearDown()
        {
            ShowSysLog("服务器关闭。");
        }
        /// <summary>
        /// 当有 "新客户端" 连接到服务器的时候,自动调用该函数
        /// </summary>
        protected override PeerBase CreatePeer(InitRequest initRequest)
        {
            ShowSysLog("新连接一个客户端。");
            return new MyPeer(initRequest);
        }

        /// <summary>
        /// 测试日志
        /// </summary>
        public static void ShowTestLog(string s)
        {
            log.Debug("【======================Test======================】  " + s);
        }
        /// <summary>
        /// 系统日志
        /// </summary>
        /// <param name="s"></param>
        public static void ShowSysLog(string s)
        {
            log.Debug("【System】  " + s);
        }
        /// <summary>
        /// 错误日志
        /// </summary>
        /// <param name="funcName"></param>
        /// <param name="exc"></param>
        public static void ShowErrorLog(string exc)
        {
            log.Debug("【>>>>>Error<<<<<】  " + exc);
        }
    }
}

服务器和客户端交流中心(继承ClientPeer类)
旧版本(我们之前用的 v3-4-31-10808),这里继承PeerBase类

using System.Collections.Generic;
using Photon.SocketServer;
using PhotonHostRuntimeInterfaces;

namespace MyServer
{
    public class MyPeer : ClientPeer
    {
        /// <summary>
        /// 新连接的"客户端对象"在服务器端的"一一对应的对象"
        /// </summary>
        /// <param name="initRequest"></param>
        public MyPeer(InitRequest initRequest) : base(initRequest) { }

        /// <summary>
        /// 客户端断开连接后,自动调用这里
        /// </summary>
        protected override void OnDisconnect(DisconnectReason reasonCode, string reasonDetail)
        {
            MyApplication.ShowSysLog("退出一个客户端");
        }
        /// <summary>
        /// 客户端发送消息后,服务器端在这里接受
        /// </summary>
        protected override void OnOperationRequest(OperationRequest request, SendParameters sendParameters)
        {
            /*  OperationResponse类的成员
             *  byte OperationCode: 命令代码,和要求时的命令代表相同,代表该要求的回传值,该值自定义
             *  Dictionary<byte,object>Parameters: 回传的内容,该值自定义
             *  short ReturnCode: 回传状态的值,该值自定义
             *  string DebugMessage: 回传的日志,该值自定义
             *  
             *  SendParameters类的成员
             *  byte ChannelId: 频道,通常都用0频道,除非特别需求否则不建议更改
             *  bool Encrypted: 是否加密,true为加密,默认为false
             *  bool Flush: 立即传输,会让queue尚未传送的往后延,默认为false
             *  bool Unreliable: 可靠传输,默认为true
             */

            //从客户端往服务器发数据,用OperationRequest
            //可以根据判断request.OperationCode值,来处理不同类型的事件消息
            byte reqCode = request.OperationCode;
            //客户端传来的值
            Dictionary<byte, object> reqPara = request.Parameters;
            switch (reqCode)
            {
                case 0:
                    object value1 = null;
                    reqPara.TryGetValue(0, out value1);
                    break;
                case 1:
                    object value2 = null;
                    reqPara.TryGetValue(0, out value2);
                    break;
            }


            //从服务器往客户端发数据,用OperationResponse
            OperationResponse response =new OperationResponse();
            //回传的命令Code和接收到的一致即可
            response.OperationCode = request.OperationCode;
            //这里自定义格式,到了客户端按照自定义的格式对应的读取即可
            response.Parameters = new Dictionary<byte, object>();
            response.Parameters.Add(0, "值");
            response.Parameters.Add(1, "值");
            response.Parameters.Add(2, "值");
            //回传状态的值
            response.ReturnCode = 0;
            //回传日志
            response.DebugMessage = "这是我的回传日志。";
            SendOperationResponse(response, sendParameters);

        }
    }
}
生成dll包,导入Photon服务器软件中
选择 生成 => 生成解决方案
(快捷键Ctrl+Shift+B)
生成的dll文件默认路径为:"…\bin\Debug"
在这里插入图片描述

当服务器端写好后,打开之前下载的Photon SDK文件夹,“…\deploy”,并在此目录下创建自己的服务器端文件夹,把我们生成的MyServer.dll文件复制粘贴到该文件夹中
在这里插入图片描述

在Photon软件中设置自己的服务器
“…\deploy\bin_Win64\PhotonServer.config”
在这里插入图片描述

打开PhotonServer.config文件在"'Configuration"节点内添加

<Configuration>
        //在这一层内添加下面一大段
        //内容格式和源文件已有设置文件的一样,把部分节点名字改成自己服务器中对应的名字即可
</Configuration>
<MyServer
                MaxMessageSize="512000"
                MaxQueuedDataPerPeer="512000"
                PerPeerMaxReliableDataInTransit="51200"
                PerPeerTransmitRateLimitKBSec="256"
                PerPeerTransmitRatePeriodMilliseconds="200"
                MinimumTimeout="5000"
                MaximumTimeout="30000"
                DisplayName="MyServer">

    <UDPListeners>
      <UDPListener
                                IPAddress="0.0.0.0"
                                Port="5055">
      </UDPListener>
    </UDPListeners>

    <TCPListeners>
      <TCPListener
                                IPAddress="0.0.0.0"
                                Port="4530"
                                PolicyFile="Policy\assets\socket-policy.xml"
                                InactivityTimeout="10000"
                                >
      </TCPListener>
    </TCPListeners>

    <PolicyFileListeners>
      <PolicyFileListener
                        IPAddress="0.0.0.0"
                        Port="843"
                        PolicyFile="Policy\assets\socket-policy.xml">
      </PolicyFileListener>
      <PolicyFileListener
                        IPAddress="0.0.0.0"
                        Port="943"
                        PolicyFile="Policy\assets\socket-policy-silverlight.xml">
      </PolicyFileListener>
    </PolicyFileListeners>

    <WebSocketListeners>
      <WebSocketListener
                                IPAddress="0.0.0.0"
                                Port="9090"
                                DisableNagle="true"
                                InactivityTimeout="10000"
                                OverrideApplication="Master">
      </WebSocketListener>

      <WebSocketListener
                                IPAddress="0.0.0.0"
                                Port="9091"
                                DisableNagle="true"
                                InactivityTimeout="10000"
                                OverrideApplication="Game">
      </WebSocketListener>

    </WebSocketListeners>

    <Runtime
                        Assembly="PhotonHostRuntime, Culture=neutral"
                        Type="PhotonHostRuntime.PhotonDomainManager"
                        UnhandledExceptionPolicy="Ignore">
    </Runtime>
    <Applications Default="MyServer">
      <Application
                                Name="MyServer"
                                BaseDirectory="MyServer"
                                Assembly="MyServer"
                                Type="MyServer.MyApplication"
                                ForceAutoRestart="true"
                                WatchFiles="dll;config"
                                ExcludeFiles="log4net.config"
                                >
      </Application>
      <Application
                                Name="CounterPublisher"
                                BaseDirectory="CounterPublisher"
                                Assembly="CounterPublisher"
                                Type="Photon.CounterPublisher.Application"
                                ForceAutoRestart="true"
                                WatchFiles="dll;config"
                                ExcludeFiles="log4net.config">
      </Application>
    </Applications>
  </MyServer>

打开Photon服务器软件,并开启自己的服务器逻辑
打开下面的应用程序
在这里插入图片描述

在这里插入图片描述
【application】可以用于Windows 普通系统:
开启:Start as application
停止:Stop application

【service】可以用于Windows 普通系统 和 Windows Server系统
先安装:Install service
开启:Start service
重启:Restart service
停止:Stop service
移除:Stop service

客户端逻辑
Unity中导入dll包
在自己的Unity客户端项目中导入Photon3Unity.dll
目录:"…\lib"
在这里插入图片描述

Unity客户端逻辑(继承IPhotonPeerListener)
using UnityEngine;
using System.Collections.Generic;
using ExitGames.Client.Photon;
using System;

public class PhotonEngine : MonoBehaviour, IPhotonPeerListener
{
    PhotonPeer peer;

    void Awake()
    {
        //自己服务器项目的名字
        string serverName = "MyServer";

        //服务器软件所在的电脑的Ip,局域网、广域网皆可
        string ip = "192.168.1.100";
        //通讯协议:TCP为4530,Upd为5055
        string port = "5055";
        //服务器请求地址
        string serverAddr= ip + ":" + port;

        ConnectionProtocol protocol;
        //通讯协议,与端口号(port)必须保持一致
        protocol = ConnectionProtocol.Tcp;
        peer = new PhotonPeer(this, protocol);

        //请求连接服务器
        peer.Connect(serverAddr, serverName);
    }

    /// <summary>
    /// 实时与服务器保持通讯
    /// </summary>
    void FixedUpdate()
    {
        if (peer != null)
        {
            peer.Service();
        }
    }

    /// <summary>
    /// 给服务器发送消息
    /// </summary>
    public void SendRequest()
    {
        //发送至服务器的消息的类型
        byte opCode = 0;
        //发送至服务器的消息内容
        Dictionary<byte, object> para = new Dictionary<byte, object>();
        para.Add(0, "值1");
        para.Add(1, "值2");
        para.Add(2, "值3");

        peer.SendOperation((byte)opCode, para, SendOptions.SendUnreliable);
    }

    /// <summary>
    /// 服务器传回来的日志,自定义的
    /// </summary>
    public void DebugReturn(DebugLevel level, string message)
    {
        Debug.Log(level + " : " + message);
    }

    /// <summary>
    /// 服务端传过来的事件,自定义的
    /// </summary>
    public void OnEvent(EventData eventData)
    {

    }

    /// <summary>
    /// 服务器端传回来的消息,自定义的
    /// </summary>
    public void OnOperationResponse(OperationResponse operResq)
    {
        //服务器发送回来的消息的类型code
        //operResq.OperationCode

        //服务器发送回来了的消息内容字典,按照服务器发送的格式解析即可获得
        //operResq.Parameters
    }

    //连线状态更改通知
    public void OnStatusChanged(StatusCode statusCode)
    {
        switch (statusCode)
        {
            case StatusCode.Connect:
                Debug.Log("连接服务器成功");
                break;
            //case StatusCode.Disconnect:
            default:
                Debug.Log("与服务器断开连接");
                break;
        }
    }
}

点评

请看x.co/aua(网址) 肺炎,最新消息 ,国内和国外不一样的报道.海外更真实...... git.io/ghhhh (网址)  发表于 2020-6-4 03:47
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|3D数字艺术论坛 ( 沪ICP备14023054号 )

GMT+8, 2024-4-20 10:10

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表