PhotonCloud服务器之Maco Polo教程(Part V 完结篇)

发表于2016-08-07
评论0 1.9k浏览
  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);
}
  当越来越多的玩家进入房间,我们需要让他们知道谁是目前“it”(就是主人)。每当有人进入,PUN便会调用OnPhotonPlayerConnected方法,所以响应是很容易的。We will create a method “TaggedPlayer” to set “playerWhoIsIt” and make it a RPC, so players who are in the game already might call it.
  我们将创建一个方法“TaggedPlayer”用来设置“playerWhoIsIt”,使它成为一个RPC,所以玩家在游戏中已经可以称之为it。  
1
2
3
4
5
6
[PunRPC]
void TaggedPlayer(int playerID)
{
    playerWhoIsIt = playerID;
    Debug.Log("TaggedPlayer: " + playerID);
}
  我们已经准备了一个RPC方法,除非脚本添加到一些带有PhotonView组件的游戏物体,否则我们不能调用它。从逻辑上来讲,记录谁是“it”并不是我们怪物的任务,因此让我们添加另一个PhotonView。
  这一次我们将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);
}
  Left Behind 遗留问题
  玩家可以随时离开,这样可能会造成掉线的玩家连接不上。
  当有人离开房间,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);
        }
    }
}
  我们还需要一种方法来标记玩家。由于Colliders(碰撞体)具有唯一性,所以我们通过点击碰撞来检测。
  我们在“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;
    }
}
  使用静态方法TagPlayer,很容易标记一个玩家。
  “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...
  Conclusion 总结对于这个游戏,我也是深有感触,photonCloud云服务用起来挺方便的,但也有他的局限性,不怎么适合大型的游戏的(当然如果只是2-4个人联机还是能玩起来的),而且这个服务,挺吃网络的,我们自己做的赛车游戏(我们并没有考虑性能啊)也就进入房间和退出房间比较卡,其他的时间也是挺流畅的,不得不说,还是photon比较良心的,嘿嘿,那么以上就是我们的marcoPolo教程,有兴趣的可以点击下载打好的包,里面都有源代码,对你学习服务器还是很有帮助的!
  已完结








如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引