Unity3d通过PhotonServer访问MySQL数据库

来源:互联网 发布:mac安装win7双系统 编辑:程序博客网 时间:2024/06/05 16:36

原文地址:blog.liujunliang.com.cn

接着上一篇文章内容继续开发

源码下载地址:点击打开链接

上一片篇文章介绍使用NHibernate完成类和数据库表的映射

本文将对NHibernate数据进行简单封装,方便在PhotonServer服务器中进行调用

using NHibernate;using NHibernate.Cfg;using MyGameServer.Domain;using NHibernate.Criterion;using System.Collections.Generic;namespace MyGameServer.Helper{    public static class NHibernateHelper    {        private static ISessionFactory sessionFactory = null;        private static ISession session = null;        public static ISession GetSession        {            get            {                if (sessionFactory == null)                {                    Configuration cfg = new Configuration();                    //解析固定路径配置文件nhibernate.cfg.xml                    cfg.Configure();                    //映射目标程序集 解析映射文件 Student.xml ......                    cfg.AddAssembly(typeof(Student).Assembly);                    //获取会话对象                    sessionFactory = cfg.BuildSessionFactory();                }                session = sessionFactory.OpenSession();                return session;            }            private set { }        }        //添加行        public static void AddData<T>(T t)        {            using (ISession session = GetSession)            {                using (ITransaction transaction=session.BeginTransaction())                {                    GetSession.Save(t);                    transaction.Commit();                }            }        }        //添加列        public static void RemoveData<T>(T t)        {            using (ISession session = GetSession)            {                using (ITransaction transaction = session.BeginTransaction())                {                    GetSession.Delete(t);                    transaction.Commit();                }            }        }        //通过ID获取对象        public static T GetDataById<T>(int id)        {            using (ISession session = GetSession)            {                using (ITransaction transaction = session.BeginTransaction())                {                    T t = session.Get<T>(id);                    transaction.Commit();                    return t;                }            }        }        /// <summary>        /// 通过名称获取对象        /// </summary>        /// <typeparam name="T">需要获取的对象</typeparam>        /// <param name="dataBaseName">在数据库中的列名称</param>        /// <param name="targetName">获取对象的目标名</param>        /// <returns></returns>        public static T GetDataByName<T>(string dataBaseName, string targetName)        {            using (ISession session = GetSession)            {                T t = session.CreateCriteria(typeof(T)).Add(Restrictions.Eq(dataBaseName, targetName)).UniqueResult<T>();                return t;            }        }        /// <summary>        /// 得到表内的全部对象        /// </summary>        /// <typeparam name="T"></typeparam>        /// <returns></returns>        public static ICollection<T> GetAllUsers<T>()        {            using (ISession session = GetSession)            {                IList<T> ts = session.CreateCriteria(typeof(T)).List<T>();                return ts;            }        }        //查询是否有符合id和姓名相同的对象        public static bool VerifyUser<T>(params object[] arg)        {            using (ISession session = GetSession)            {                T t = session                    .CreateCriteria(typeof(T))                    .Add(Restrictions.Eq(arg[0].ToString(), arg[1]))//类属性名 属性值                    .Add(Restrictions.Eq(arg[2].ToString(), arg[3]))                    .UniqueResult<T>();                if (t == null)                {                    return false;                }                return true;            }        }        /// <summary>        /// 更新数据表        /// </summary>        /// <typeparam name="T">数据表映射的对象</typeparam>        /// <param name="t"></param>        public static void UpdateData<T>(T t)        {            using (ISession session = GetSession)            {                using (ITransaction transaction=session.BeginTransaction())                {                    session.Update(t);                    transaction.Commit();                }            }        }    }}


在主函数调用

using NHibernate;using NHibernate.Cfg;using LJL.Domain;using LJL.Helper;namespace LJL{    class Program    {        static void Main(string[] args)        {            Student sd = new Student { mID = 6, mName = "小张", mScore = 10 };            NHibernateHelper.AddData(sd);        }    }}


运行程序,一切正常,打开SQLyog,在student数据表中添加一行数据

接下来就是在PhotonServer中调用,来实现与MySQL数据库交互

按图下将类、配置文件集成到类库中(注意需要修改下类和配置文件中的程序集及命名空间


接下来就是在Unity3d游戏客户端中与PhotonServer通信进而访问本地数据库

在Unity3d客户端上创建UI(这里简单拖入输入框和按钮)

如下图创建脚本


我们的游戏有很多中请求(比如登入、注册请求等等)

所以都继承自BaseRequest

using ExitGames.Client.Photon;using System.Collections;using System.Collections.Generic;using UnityEngine;public abstract class BaseRequest : MonoBehaviour{    [HideInInspector]    //该请求的操作类型    public Collective.OperationMode operationMode = Collective.OperationMode.Default;    public virtual void Start() { }    public abstract void OnOperationRequest();    public abstract void OnOperationResponse(OperationResponse operationResponse);}


这里博主简单的做了一下登录请求

using ExitGames.Client.Photon;using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.UI;public class LoginRequest : BaseRequest{    //用户名    private InputField mInputName;    //密码    private InputField mInputPassword;    public override void Start()    {        operationMode = Collective.OperationMode.LOGIN;        GameContext.GetInstance.AddRequest(this);        mInputName = GameObject.Find("IDInputField").GetComponent<InputField>();        mInputPassword = GameObject.Find("NameInputField").GetComponent<InputField>();        //登录按钮点击事件        GameObject.Find("LoginButton").GetComponent<Button>().onClick.AddListener(() => { OnOperationRequest(); });    }    public override void OnOperationRequest()    {        GameContext.GetInstance.peer.OpCustom(                                                (byte)this.operationMode,                                                new Dictionary<byte, object> { { (byte)Collective.ParameterMode.NAME, mInputName.text }, { (byte)Collective.ParameterMode.PASSWORD, mInputPassword.text } },                                                true                                              );    }    public override void OnOperationResponse(OperationResponse operationResponse)    {                Collective.OperationResult resultCode = (Collective.OperationResult)operationResponse.ReturnCode;        if (resultCode == Collective.OperationResult.SUCCESS)        {            //登录成功            Debug.Log("用户登录成功");        }        else if(resultCode == Collective.OperationResult.FAIL)        {            //登录失败            Debug.Log("登录失败");        }    }}


最后附上上篇博文GameContext脚本,在这里有些地方发生了更新

using System.Linq;using System.Collections.Generic;using UnityEngine;using UnityEngine.UI;using ExitGames.Client.Photon;public class GameContext : MonoBehaviour,IPhotonPeerListener{    /// <summary>    /// 存储操作类型与请求    /// </summary>    public Dictionary<Collective.OperationMode, BaseRequest> requestDic = new Dictionary<Collective.OperationMode, BaseRequest>();    public PhotonPeer peer;    private static GameContext _instance;    public static GameContext GetInstance    {        get        {            if (_instance == null)            {                _instance = GameObject.Find("GameContext").GetComponent<GameContext>();            }            return _instance;        }    }    public void DebugReturn(DebugLevel level, string message)    {           }    //接收服务器发来的事件    public void OnEvent(EventData eventData)    {        switch (eventData.Code)        {            case 0:                //获取事件数据                object value = eventData.Parameters.FirstOrDefault(q => q.Key == 1).Value;                Debug.Log(value.ToString());                break;            default:                break;        }    }    //接收响应数据(客户端发送了请求)    public void OnOperationResponse(OperationResponse operationResponse)    {        BaseRequest request = requestDic.FirstOrDefault(q => q.Key == (Collective.OperationMode)operationResponse.OperationCode).Value;        if (request != null)        {            request.OnOperationResponse(operationResponse);        }        else        {            //获取响应数据失败            Debug.LogError("获取响应数据失败");        }    }    //连接状态发送改变    public void OnStatusChanged(StatusCode statusCode)    {        Debug.Log("数据连接状态发生的改变:" + statusCode);    }    private void Start()    {        //传输协议UDP 、 通过Listener接收服务器端的响应        peer = new PhotonPeer(this, ConnectionProtocol.Udp);        //连接本地服务器        peer.Connect("127.0.0.1:5055", "MYGameServer");    }    private void Update()    {        //和服务器实时保持数据连接        peer.Service();                     }    private void OnDestroy()    {        if (peer != null && peer.PeerState == PeerStateValue.Connected)        {            //断开连接            peer.Disconnect();        }    }    public void AddRequest(BaseRequest request)    {        if (request != null)        {            requestDic.Add(request.operationMode, request);        }        else        {            Debug.LogError("添加数据为空");        }    }    public void RemoveRequest(BaseRequest request)    {        if (request != null && requestDic.ContainsValue(request))        {            requestDic.Remove(request.operationMode);        }        else        {            Debug.LogError("移除失败");        }    }}

其中Collective是生成的一个类库,该类库包含一些在客户端和服务器端都共同使用枚举类型(源码最后一起打包给大家学习)

在服务器端需要处理相似的逻辑

也是创建请求类,将各种请求继承自BaseRequest

在主类中对各中请求类加入到字典容器中,当监听到数据请求时候,寻找到相应的请求类进行对数据库数据操作(增、删、改、查)

并将最终数据返回给客户端(success、fail)

BaseRequest.cs

using Photon.SocketServer;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace MyGameServer.Request{    public abstract class BaseRequest    {        public Collective.OperationMode operationMode = Collective.OperationMode.DEDAULF;        public abstract void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters, ClientPeer peer);            }}


LoginRequest.cs

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using MyGameServer.Request;using Photon.SocketServer;using MyGameServer.Helper;using MyGameServer.Domain;namespace MyGameServer.Request{    public class LoginRequest : BaseRequest    {        public LoginRequest()        {            operationMode = Collective.OperationMode.LOGIN;        }        public override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters, ClientPeer peer)        {            Dictionary<byte, object> parameterDic = operationRequest.Parameters;                       bool result = NHibernateHelper.VerifyUser<Student>(                                                    //类属性名、属性值                                                    "mID", int.Parse(parameterDic.FirstOrDefault(q => q.Key == (byte)Collective.ParameterMode.NAME).Value.ToString()),                                                    "mName", parameterDic.FirstOrDefault(q => q.Key == (byte)Collective.ParameterMode.PASSWORD).Value.ToString()                                                );            MyGameServer.LOG.Info(parameterDic.FirstOrDefault(q => q.Key == (byte)Collective.ParameterMode.NAME).Value.ToString());            MyGameServer.LOG.Info(parameterDic.FirstOrDefault(q => q.Key == (byte)Collective.ParameterMode.PASSWORD).Value.ToString());            OperationResponse response = new OperationResponse(operationRequest.OperationCode);            response.ReturnCode = (short)Collective.OperationResult.FAIL;            if (result)            {                response.ReturnCode = (short)Collective.OperationResult.SUCCESS;                MyGameServer.LOG.Info("验证成功");            }            peer.SendOperationResponse(response, sendParameters);        }    }}


其中附上上篇文章服务器端的MyGameServer.cs,在这里有所更新(添加字典容器用于将请求类存储)

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using Photon.SocketServer;using System.IO;using ExitGames.Logging;using ExitGames.Logging.Log4Net;using log4net.Config;using MyGameServer.Domain;using MyGameServer.Helper;using MyGameServer.Request;namespace MyGameServer{    //服务器框架主类 框架入口    public class MyGameServer : Photon.SocketServer.ApplicationBase    {        public static Dictionary<byte, object> requestDic = new Dictionary<byte, object>();        //单例模式        public static ILogger LOG = LogManager.GetCurrentClassLogger();            //当有客户端接入时候调用        protected override PeerBase CreatePeer(InitRequest initRequest)        {            LOG.Info("有一个客户端连接进服务器");            AddRequestOperation();            return new ClientPeer(initRequest);        }        //当框架启动时候调用        protected override void Setup()        {            //设置配置文件属性            log4net.GlobalContext.Properties["Photon:ApplicationLogPath"] = Path.Combine(Path.Combine(this.ApplicationRootPath, "bin_Win64"), "log");//设置日志文件存储目录            //日志配置文件            FileInfo logConfigFileInfo = new FileInfo(Path.Combine(this.BinaryPath, "log4net.config"));            if (logConfigFileInfo.Exists)//配置文件存在            {                //设置Photon日志插件为Log4Next                LogManager.SetLoggerFactory(Log4NetLoggerFactory.Instance);                //Log4Next这个插件读取配置文件                XmlConfigurator.ConfigureAndWatch(logConfigFileInfo);            }            LOG.Info("服务器初始化完成");                    }        //将含有的交互请求全部添加到字典里        private void AddRequestOperation()        {            requestDic.Clear();            BaseRequest request = new LoginRequest();            requestDic.Add((byte)request.operationMode, request);        }        //当框架停止时候调用        protected override void TearDown()        {                    }    }}

其中客户端类ClientPeer.cs数据监听函数需要修改

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using Photon.SocketServer;using PhotonHostRuntimeInterfaces;using MyGameServer.Request;namespace MyGameServer{    public class ClientPeer : Photon.SocketServer.ClientPeer    {        public ClientPeer(InitRequest ir) : base(ir) { }        //该客户端断开连接        protected override void OnDisconnect(DisconnectReason reasonCode, string reasonDetail)        {                    }        //该客户端出操作请求        protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters)        {            BaseRequest request = (BaseRequest)MyGameServer.requestDic.FirstOrDefault(q => q.Key == (byte)operationRequest.OperationCode).Value;            if (request != null)            {                request.OnOperationRequest(operationRequest, sendParameters, this);            }            else            {                MyGameServer.LOG.Info("获取请求操作失败");            }        }       }}


将解决方案重新生成一下,用PhotonControl开启MyGameServer

在Unity开启一个客户端

对数据进行验证,发现一切正常!!!