使用Photon引擎进行unity网络游戏开发(四)——Photon引擎实现网络游戏逻辑

摘要:
ReSourcesPrefabName:需要在资源文件下实例化的Prefab的名称Position:需要实例化的对象的出生点Quaternion:需要实例化对象的旋转信息Group:便于识别每个对象的分组信息,例如,区分我们的PhotonNetwork。敌人的实例。对于example://Generate播放器对象voidInstancePlayer(){playerCustomProperties=PhotonNetwork.player.CustomProperties;如果{localPlayer=PhotonNetwork;}//如果玩家属于团队2,则生成RobotPlayer对象elseif{localPlayer=PhotonNetwork.Instance;}localPlayer.name=PhotonNetwork.player。昵称;}游戏对象状态同步位置面向信息同步方法1:将Transfrom组件拖动到PhotonView组件上的observedcomponentS属性。
使用Photon引擎进行unity网络游戏开发(四)——Photon引擎实现网络游戏逻辑
Photon
PUN
Unity
网络游戏开发
网络游戏逻辑处理与MasterClient

网络游戏逻辑处理:

方法一:编写Photon服务器与客户端程序

客户端传递数据之服务器,服务器完成逻辑判断,并将结果返回给客户端
enter description here

方法二:编写客户端程序

游戏逻辑在客户端处理,photon服务器只负责客户端之间数据验证和传递
enter description here

Master Client

  • 使用客户端处理网络游戏逻辑时,必须保证游戏房间内只有一个客户端处理网络游戏逻辑,我们选择某个客户端来网络处理游戏逻辑
  • 这个客户端根据其他客户端发送的数据,处理网络游戏逻辑。之后,将处理结果发送给所有客户端同步

PUN Master Client

在PUN的客户端Client中,包含一个MasterClient,我们使用MasterClient来处理网络游戏逻辑

  • MasterCIient是PUN里一个特殊的客户端,每个游戏房间Room有且仅有一个MasterClient
  • MasterCIient拥有比一般客户端更高的权限,包括将其它客户端踢出游戏房间、管理网络游戏场景对象等
  • MasterClient离开房间后,GameServer会自动选择ID最小的客户端作为MasterCIient
  • 使用PhotonNetwork.isMasterCIient判断本地客户端是否为MasterCIient

玩家对象生成

Photon中生成玩家对象需要调用下面方法实例化。

  • ReSourcesPrefabName:需要实例化Prefab在resources文件下下名称
  • Position:需要实例化对象的出生点
  • Quaternion:需要实例化对象的旋转信息
  • Group:编组信息,方便区分各个对象,如区分出我方和敌方 PhotonNetwork.Instantiate("ReSourcesPrefabName",Position,Quaternion, Group)
    例如:
    //生成玩家对象
    void InstancePlayer()
    {
        playerCustomProperties = PhotonNetwork.player.CustomProperties;
        if (playerCustomProperties["Team"].ToString().Equals("Team1"))
        {
            localPlayer = PhotonNetwork.Instantiate("MyPlayer",
                TeamOneSpTrans[(int)playerCustomProperties["TeamNum"]].position, Quaternion.identity, 0);
        }
        //如果玩家属于队伍2,生成RobotPlayer对象
        else if (PhotonNetwork.player.CustomProperties["Team"].ToString().Equals("Team2"))
        {
            localPlayer = PhotonNetwork.Instantiate("MyPlayer",
                TeamTwoSpTrans[(int)playerCustomProperties["TeamNum"]].position, Quaternion.identity, 0);
        }

        localPlayer.name = PhotonNetwork.player.NickName;
    }

游戏对象状态同步

位置朝向信息同步

方法一:通过将Transfrom组件拖到PhotonView组件上的observed componentS属性上。该方式尽管会传输对象的位置旋转信息,但是由于通信间隔的存在,导致对象运动不连续

方法二:使用PhotonTransformView实现玩家位置与朝向的同步。

PhotonTransformView组件内置几种插值算法,可以使用内置插值方法实现玩家的平滑“移动。

方法三:使用OnPhotonSerializeView(PhotonStream,PhotonMessageInfo)方法同步

使用该方法时需自行处理位置和旋转的插值。

private void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)  
    {  
        if (stream.isWriting)  
        {  
            //We own this player: send the others our data  
            ...
            stream.SendNext(transform.position);  
            stream.SendNext(transform.rotation);  
        }  
        else  
        {  
            ...
            PlayerPosition = (Vector3)stream.ReceiveNext();  
            PlayerRotation = (Quaternion)stream.ReceiveNext();  
        }  
    }  

enter description here

enter description here

enter description here

enter description here

动画信息同步

方法一:针对使用Animator组件的动画,使用PhotonAnimatorView快速开发。

enter description here

方法二:使用OnPhotonSerializeView(PhotonStream,PhotonMessageInfo)方法同步。使用该方法将动画参数的值传递,来实现动画的同步,该方法对animation组件动画适用。

Animation动画:
如player有针对于其动画的控制脚本,通过Update函数中的playerState来判断动画表现,这里我们传递playerState来实现动画同步

private void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)  
    {  
        if (stream.isWriting)  
        {  
            //We own this player: send the others our data  
            ...
           stream.SendNext(player.playerState);  
        }  
        else  
        {  
            ...
           player.playerState = (PlayAnimation)stream.ReceiveNext(); ;  
        }  
    }  

Animator动画:
animator组件中通过各个参数来控制动画的分支走向,这里我们同步其参数来实现动画同步

private void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)  
    {  
        if (stream.isWriting)  
        {  
            //We own this player: send the others our data  
            ...
           stream.SendNext(ani.GetFloat("RunSpeed"));  	
		   stream.SendNext(ani.GetBool("isJump"));  
        }  
        else  
        {  
            ...
           ani.SetFloat("RunSpeed",(string)stream.ReceiveNext());
		   ani.SetBool("isJump",(bool)stream.ReceiveNext());
        }  
    }  

免责声明:文章转载自《使用Photon引擎进行unity网络游戏开发(四)——Photon引擎实现网络游戏逻辑》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Go日志库使用-logrus继续推荐几款VisualStudio的插件(二)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Unity3d Shader

Unity3d Shader 预览Surface Shader主要用来实现光照相关处理,可能更简洁。Vertex and Fragment Shader如果不与光照交互, 则可以用这个shader,更录活fixed function shaders固定shader主要用于老旧卡ShaderLab不管写哪种shader,最终通过shaderLab实现,其组织结...

AssetPostprocessor.OnPreprocessModel

今天对工程中的模型做一些统一设置, 然后发现一个问题, 就是修改了设置点Apply之后, 又会被改回默认设置. 最后搜了一下, 处理方案是使用assetImport的userData进行判断. 参考文章: <Manage Default Asset Import Settings in Unity> http://www.cliffordroc...

【Unity/Kinect】手势识别Gesture

在Unity的AssetStore官方商店下载Kinect v2 Examples案例包,参考KinectDemos/GestureDemo这个文件夹下的例子。 自定义一个类,实现KinectGestures.GestureListenerInterface接口。参考案例中的CubeGestureListener中的用法。下面演示监听SwipeLeft向左...

从屏幕刷新频率到Unity VSync

显示器有一个属性叫屏幕刷新频率,它是指每秒刷新屏幕的次数,单位为Hz,一般设置为60Hz。 什么是刷新屏幕呢?我们屏幕是由像素矩阵组成的,其(CRT)显示图像的原理是靠电子束从左到右、从上到下逐行激发屏幕内表面的荧光粉单元(像素)来实现的。电子束一次水平方向的扫描叫行扫描,一次完整的扫描就是刷新屏幕,形成的图像就是一帧。因此60Hz的刷新率也就是每秒60...

Unity3D之Mesh(一)绘制三角形

前言: Unity自带几种简单的模型,如cube等;一般情况下,其余模型有3D建模软件生成,以合适的文件格式导入unity中;而mesh(以我目前很粗浅的了解)的一般用途就是:对现有的模型进行变形,以达到各种奇幻酷炫的表现效果。 但是由于自己的项目需要,需要由数据(外部解释stl文件获得)按照特定情况以及要求实时地产生各种几何模型,故需要用Mesh进行建模...

Unity应用架构设计(10)——绕不开的协程和多线程(Part 2)

在上一回合谈到,客户端应用程序的所有操作都在主线程上进行,所以一些比较耗时的操作可以在异步线程上去进行,充分利用CPU的性能来达到程序的最佳性能。对于Unity而言,又提供了另外一种『异步』的概念,就是协程(Coroutine),通过反编译,它本质上还是在主线程上的优化手段,并不属于真正的多线程(Thread)。那么问题来了,怎样在Unity中使用多线程呢...