使用Photon引擎进行unity网络游戏开发(四)——Photon引擎实现网络游戏逻辑
网络游戏逻辑处理与MasterClient
网络游戏逻辑处理:
方法一:编写Photon服务器与客户端程序
客户端传递数据之服务器,服务器完成逻辑判断,并将结果返回给客户端
方法二:编写客户端程序
游戏逻辑在客户端处理,photon服务器只负责客户端之间数据验证和传递
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();
}
}
动画信息同步
方法一:针对使用Animator组件的动画,使用PhotonAnimatorView快速开发。
方法二:使用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());
}
}