PhotonCloud服务器之Maco Polo教程(Part V 完结篇)
发表于2016-08-07
Contents 目录
1、Overview 概述
2、Walking Vikings 行走的维京人
3、Photon Cloud 光子云
4、Starting From Scratch 写在前边的话
5、Reception: Getting a Room 接受:获取一个房间(不是开房的意思→_→)
6、Marco Polo: Syncing Positions 马可波罗:同步位置
7、Shout and Respond 喊叫和回应
PhotonCloud服务器之Marco Polo教程(Part V)
8、Switch “It” 转化“It”
9、Conclusion 总结
Switch “It” 转换
到目前为止,我们已经做得差不多了。现在唯一缺少的就是辨别彼此的游戏逻辑,即“它是谁?”,因此我们需要标记怪物。
现在完成第一块的游戏逻辑:我们在“Marco Polo”文件夹创建一个c#脚本“GameLogic”,并将它添加到“Scripts”对象上。
第一个进入一个房间Player是“it”。我们知道,当OnJoinedRoom()方法被调用时,我们刚进房间,通过查看PhotonNetwork.playerList我们可以很容易地知道我们是否是第一个。
Player IDs 玩家ID
Photon使用玩家“ID”或“playerNumber”标记在房间里每一个球员。因为这是一个整数,所以数据相对较小。由于它不重复,所以我们可以通过ID和房间内的所有玩家“交谈”;
我们的本地客户机ID存储在PhotonNetwork.player.ID。如果只有我们一个人,我们会保存到“playerWhoIsIt”变量里。因为这是一个静态字段,所以可以很容易在不同的脚本访问它。
1 2 3 4 5 6 7 8 9 10 11 12 | public static int playerWhoIsIt; void OnJoinedRoom() { // game logic: if this is the only player, we're "it" if (PhotonNetwork.playerList.Length == 1) { playerWhoIsIt = PhotonNetwork.player.ID; } Debug.Log( "playerWhoIsIt: " + playerWhoIsIt); } |
我们将创建一个方法“TaggedPlayer”用来设置“playerWhoIsIt”,使它成为一个RPC,所以玩家在游戏中已经可以称之为it。
1 2 3 4 5 6 | [PunRPC] void TaggedPlayer( int playerID) { playerWhoIsIt = playerID; Debug.Log( "TaggedPlayer: " + playerID); } |
这一次我们将PhotonView添加到在scene里面的“Script”对象。因为是场景hierarchy面板的一部分,所以它的拥有者就是“Scene”。因为GameLogic和PhotonView 在同一个游戏物体上,所以我们可以通过获取PhotonView组件来调用RPC。
如果只有一个玩家更新新玩家,那就已经足够了。在unity 的Networking中没有主机这一概念,但是PUN有:主客户端永远都是整个房间中ID最小的一个。每个客户端都可以通过PhotonNetwork.isMasterClient这一属性来查看自己是否是目前的房主。
我们在GameLogic脚本中添加方法OnPhotonPlayerConnected()和静态方法"TagPlayer"。静态方法好处就是可以从任意位置调用。我们会在后面用到。这部分代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | private static PhotonView ScenePhotonView; void Start() { ScenePhotonView = this .GetComponent(); } void OnPhotonPlayerConnected(PhotonPlayer player) { Debug.Log( "OnPhotonPlayerConnected: " + player); // when new players join, we send "who's it" to let them know // only one player will do this: the "master" if (PhotonNetwork.isMasterClient) { TagPlayer(playerWhoIsIt); } } public static void TagPlayer( int playerID) { Debug.Log( "TagPlayer: " + playerID); ScenePhotonView.RPC( "TaggedPlayer" , PhotonTargets.All, playerID); } |
玩家可以随时离开,这样可能会造成掉线的玩家连接不上。
当有人离开房间,PUN将调用OnPhotonPlayerDisconnected方法。我们应该判断离开的人是不是房主,如果是,就分配一个新的值。当然这部分工作只是会有房主来做。
1 2 3 4 5 6 7 8 9 10 11 12 13 | void OnPhotonPlayerDisconnected(PhotonPlayer player) { Debug.Log( "OnPhotonPlayerDisconnected: " + player); if (PhotonNetwork.isMasterClient) { if (player.ID == playerWhoIsIt) { // if the player who left was "it", the "master" is the new "it" TagPlayer(PhotonNetwork.player.ID); } } } |
我们在“Marco Polo”文件夹新建一个c#脚本“ClickDetector”,并将其拖动到“monsterprefab”游戏物体上。在这篇文章中,我们会用Update方法来监测鼠标点击是否选中了这个player。我们获取到点击的对象(如果有的话),并确保它不是地面或我们怪物。
一旦我们知道那个被点击了,我们便得到它的PhotonView,转而便知道怪物属于哪个Player,所以我们可以使用该玩家ID进行标记。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | using System; using UnityEngine; public class ClickDetector : MonoBehaviour { void Update() { // if this player is not "it", the player can't tag anyone, so don't do anything on collision if (PhotonNetwork.player.ID != GameLogic.playerWhoIsIt) { return ; } if (Input.GetButton( "Fire1" )) { GameObject goPointedAt = RaycastObject(Input.mousePosition); if (goPointedAt != null && goPointedAt != this .gameObject && !goPointedAt.name.Equals( "Plane" , StringComparison.OrdinalIgnoreCase)) { PhotonView rootView = goPointedAt.transform.root.GetComponent(); GameLogic.TagPlayer(rootView.owner.ID); } } } private GameObject RaycastObject(Vector2 screenPos) { RaycastHit info; if (Physics.Raycast(Camera.mainCamera.ScreenPointToRay(screenPos), out info, 200)) { return info.collider.gameObject; } return null ; } } |
“Marco” 和“Polo”GUI按钮为任意玩家显示。这个显示通过监测“playerWhoIsIt"也很容易改变。我们就是“it”,只显示“Marco。
RandomMatchmaker应修改如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | void OnGUI() { GUILayout.Label(PhotonNetwork.connectionStateDetailed.ToString()); if (PhotonNetwork.connectionStateDetailed == PeerState.Joined) { bool shoutMarco = GameLogic.playerWhoIsIt == PhotonNetwork.player.ID; if (shoutMarco && GUILayout.Button( "Marco!" )) { this .myPhotonView.RPC( "Marco" , PhotonTargets.All); } if (!shoutMarco && GUILayout.Button( "Polo!" )) { this .myPhotonView.RPC( "Polo" , PhotonTargets.All); } // and so on... |
已完结