王者荣耀实时对战服务器Photon之PUN玩家网络实例化

发表于2017-11-19
评论0 2.2k浏览

本节将介绍Photon Pun网络上的“角色”预制实例化,并实现在运行场景自动切换所需的各种功能。

实际上我们的角色”预制制作很容易的。当我们进入房间时,我们需要实例化,我们可以依靠GameManager Script Start()传递消息。

1.打开GameManager脚本

2.在公共变量区域中,添加以下变量

[Tooltip("The prefab to use for representing the player")]

public GameObject playerPrefab;

3.在Start()方法中,添加以下内容并保存GameManager脚本。

if (playerPrefab == null) 

    Debug.LogError("<Color=Red><a>Missing</a></Color> playerPrefab Reference. Please set it up in GameObject 'Game Manager'",this);

} 

else

    Debug.Log("We are Instantiating LocalPlayer from "+Application.loadedLevelName);

// we're in a room. spawn a character for the local player. it gets synced by using PhotonNetwork.Instantiate

    PhotonNetwork.Instantiate(this.playerPrefab.name, new Vector3(0f,5f,0f), Quaternion.identity, 0);

4.保存脚本。

定义一个公共的变量“角色”预制。我们可以直接在“GameManager”预制中拖放,而不是在每个场景中,因为“角色”预制是一种资产,因此引用将保持原样(而不是引用一个 GameObject在一个层次结构中,Prefab只能在同一场景中实例化时才能执行)。

警告:始终确保应该通过网络实例化的Prefab在资源文件夹中,这是Photon的要求。

然后,在Start()上,我们实例化(在正确检查我们有一个“角色”预制引用之后),

请注意,我们实例化在地板以上(上面5个单位,而玩家只有2个单位高)。以防止新玩家加入房间时发生碰撞,讲玩家向上移动来避免突然的碰撞和避免“堕落”到地下下面的情况发生。

然而,我们这么做还是不够的,我们有一个当其他玩家加入时,会加载不同的场景,我们希望保持一致性,而不是因为其中一个离开而破坏现有玩家。 所以我们需要告诉Unity不要破坏我们创建的实例,这反过来又意味着我们现在需要检查当加载场景时是否需要实例化。

Keeping track of the player instance

1.打开PlayerManager脚本

2.在“公共变量”区域中,添加以下内容

[Tooltip("The local player instance. Use this to know if the local player is represented in the Scene")]

public static GameObject LocalPlayerInstance;

3.在Awake()方法中,添加以下内容

// #Important

// used in GameManager.cs: we keep track of the localPlayer instance to prevent instantiation when levels are synchronized

if ( photonView.isMine)

    PlayerManager.LocalPlayerInstance = this.gameObject;

// #Critical

// we flag as don't destroy on load so that instance survives level synchronization, thus giving a seamless experience when levels load.

DontDestroyOnLoad(this.gameObject);

4.保存PlayerManager脚本

通过这些修改,我们可以在GameManager脚本中实现该检查,以便只有在必要时进行实例化。

打开GameManager脚本

if语句判断实例化调用

if (PlayerManager.LocalPlayerInstance==null)

    Debug.Log("We are Instantiating LocalPlayer from "+Application.loadedLevelName);

    // we're in a room. spawn a character for the local player. it gets synced by using PhotonNetwork.Instantiate

    PhotonNetwork.Instantiate(this.playerPrefab.name, new Vector3(0f,5f,0f), Quaternion.identity, 0);

else

    Debug.Log("Ignoring scene load for "+Application.loadedLevelName);


保存GameManager脚本

这样,我们在PlayerManager脚本中进行判断,没有对localPlayer的现有实例化的情况下才实例化。

Manage player position when outside the arena

我们还有一件事要注意。 竞技场场景的大小根据玩家的数量而变化,这意味着有一种情况,如果一个玩家离开,另一个玩家接近当前竞技场大小的限制,他们将只会发现自己在更小的竞技场之外,它会加载,我们需要解决这个问题,并且在这种情况下简单地将玩家重新定位到竞技场的中心。 这是您的游戏和水平设计中的一个问题。

目前,由于Unity已经改进了“场景管理”,而Unity 5.4已经弃用了一些回调,因此创建一个可以在所有Unity版本(从Unity 4.7到最新版本)中运行的代码稍微复杂一些。 所以我们需要基于Unity版本的不同的代码。 它与Photon Pun网络无关,但是要重新掌握您的项目以便更新。

打开PlayerManager脚本

在脚本的顶部添加以下定义

#if UNITY_5 && (!UNITY_5_0 && !UNITY_5_1 && !UNITY_5_2 && ! UNITY_5_3) || UNITY_2017

#define UNITY_MIN_5_4

#endif

在Start()方法的末尾,添加以下代码

#if UNITY_MIN_5_4

// Unity 5.4 has a new scene management. register a method to call CalledOnLevelWasLoaded.

UnityEngine.SceneManagement.SceneManager.sceneLoaded += (scene, loadingMode) =>

        {

            this.CalledOnLevelWasLoaded(scene.buildIndex);

        };

#endif

MonoBehaviour CallBacks”区域中添加以下两种方法

#if !UNITY_MIN_5_4

/// <summary>See CalledOnLevelWasLoaded. Outdated in Unity 5.4.</summary>

void OnLevelWasLoaded(int level)

   this.CalledOnLevelWasLoaded(level);

#endif

void CalledOnLevelWasLoaded(int level)

    // check if we are outside the Arena and if it's the case, spawn around the center of the arena in a safe zone

    if (!Physics.Raycast(transform.position, -Vector3.up, 5f))

    {

        transform.position = new Vector3(0f, 5f, 0f);

    }

保存PlayerManager脚本

这个新代码正在增加场景跳转加载的级别,并将当前角色的位置向下,看看我们是否碰撞了任何东西。 如果我们不这样做,这就意味着我们不在竞技场的上方,我们需要重新定位到中心,就像我们第一次进入房间时一样。

为了完成场景的跳转加载,如果您的Unity版本低于Unity 5.4,我们将使用Unity的回调OnLevelWasLoaded。 如果您使用的是Unity 5.4或更高版本,则OnLevelWasLoaded不再可用,而您必须使用新的SceneManagement系统。 最后,为了避免重复代码,我们只需要从OnLevelWasLoadedSceneManager.sceneLoaded回调函数调用CalledOnLevelWasLoaded方法。

不管你有关于Photon产品的问题或者是Photon价格问题或者Photon教程方面的问题或者其他问题都可以联系我们给我我们留言,我们真诚的为您服务。

关注我们公众号PhotonServer 获取最新教程资源。


王者荣耀实时对战服务器Photon之Pun应用系列文章 如果你喜欢请关注我公众号,并推荐给你你的小伙伴,谢谢。


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