王者荣耀实时对战服务器Photon之PUN玩家UI预设

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

本节将指导您创建Player UI系统。 我们需要显示玩家角色的名称及其当前的血量HP。 我们还需要让UI来随玩家角色。

这个部分与Photon pun网络联系无关,但是它提出了一个非常重要的设计模式问题,提供了一些网络周围的高级功能,并且在开发中使用这种设计方式。

现在的问题是:我们如何为每个pun联网的玩家提供UI

我们将有一个UI Prefab与之匹配PlayerUI脚本.我们的PlayerManager脚本将保存此UI Prefab的引用,并且将在PlayerManager启动时进行实例化UI Prefab预设

Creating the UI Prefab

1.打开任何场景,你有一个UICanvas

2.Slider UI GameObject添加到Canvas,将其命名为Player UI

3.Rect Transform垂直锚点设置为Middle,将Horizontal锚点设为中心

4.RectTransform宽度设置为80,高度设置为15

5.选择背景子物体,将其图像组件颜色设置为红色

6.选择子物体“填充区域/填充”,将其图像颜色设置为绿色

7.添加一个Text UI GameObject作为Player UI的子物体,将其命名为Player Name Text

8.将玩家UI从层次结构拖到您的资产中的Prefab文件夹中,制作完成预设。

9.我们不需要它了,删除场景中的实例。

The PlayerUI Scripts Basics

1.创建一个新的C#脚本,并将其称为PlayerUI

2.下面的代码是基本的脚本结构,相应地编辑和保存PlayerUI脚本:

using UnityEngine;

using UnityEngine.UI;

using System.Collections;

namespace Com.MyCompany.MyGame

    public class PlayerUI : MonoBehaviour 

    {

        #region Public Properties

        [Tooltip("UI Text to display Player's Name")]

        public Text PlayerNameText;

        [Tooltip("UI Slider to display Player's Health")]

        public Slider PlayerHealthSlider;

        #endregion

        #region Private Properties

        #endregion

        #region MonoBehaviour Messages

        #endregion

        #region Public Methods

        #endregion

    }

3.保存脚本

现在我们来创建Prefab本身。

1.PlayerUI脚本添加到Prefab PlayerUI

2.将子物体GameObjectPlayer Name Text”拖放到PlayerNameText控件

3.将滑块组件拖放到PlayerHealthSlider 控件

Instantiation and binding with the player

Binding PlayerUI with Player

PlayerUI脚本将需要知道哪个角色代表显示其对应的hp和名称,让我们创建一个公共方法来实现此绑定。

1.打开脚本PlayerUI

2.创建私有变量

PlayerManager _target;

3在公共方法区域中添加此公共方法

public void SetTarget(PlayerManager target)

    if (target == null) 

    {

        Debug.LogError("<Color=Red><a>Missing</a></Color> PlayMakerManager target for PlayerUI.SetTarget.",this);

        return;

    }

    // Cache references for efficiency

    _target = target;

    if (PlayerNameText != null) 

    {

        PlayerNameText.text = _target.photonView.owner.name;

    }

4.在MonoBehaviour Update中添加此方法

void Update()

    // Reflect the Player Health

    if (PlayerHealthSlider != null) 

    {

        PlayerHealthSlider.value = _target.Health;

    }


5保存PlayerUI脚本。

有了这个,到目前为止,我们知道有UI可以显示目标玩家的名字和HP数值了。

Instantiation

我们如何实例化这个Prefab,每次我们实例化一个玩家Prefab。 在初始化过程中,最好的方法是在PlayerManager中。

1打开脚本PlayerManager

2添加公共字段以保留对Player UI引用的引用,如下所示:

[Tooltip("The Player's UI GameObject Prefab")]

public GameObject PlayerUiPrefab;

3在Start()方法中添加此代码

if (PlayerUiPrefab!=null)

    GameObject _uiGo =  Instantiate(PlayerUiPrefab) as GameObject;

    _uiGo.SendMessage ("SetTarget", this, SendMessageOptions.RequireReceiver);

} else {

    Debug.LogWarning("<Color=Red><a>Missing</a></Color> PlayerUiPrefab reference on player Prefab.",this);

我们向刚刚创建的实例发送消息。我们需要一个接收器,这意味着如果SetTarget没有找到组件来响应它,我们将进行警报。 另一种方式是从实例中获取PlayerUI组件,然后直接调用SetTarget。 通常建议直接使用组件,但也可以通过各种方式实现同样的功能。

然而,这是远远不够的,当我们需要处理删除角色时,我们当然不想在场景中有孤立的UI实例,所以我们需要在找到对应的目标进行销毁UI实例。

1打开PlayerUI脚本

2将其添加到Update()函数

// Destroy itself if the target is null, It's a fail safe when Photon is destroying Instances of a Player over the network

if (_target == null) 

    Destroy(this.gameObject);

    return;

 

当一个新的场景进行加载,UI被销毁,但我们的角色需要我们实例化它,当我们知道一个场景进行加载,我们这样做:

4打开脚本PlayerManager

5将此代码添加到CalledOnLevelWasLoaded()方法中

GameObject _uiGo = Instantiate(this.PlayerUiPrefab) as GameObject;

_uiGo.SendMessage("SetTarget", this, SendMessageOptions.RequireReceiver);

Parenting to UI Canvas

Unity UI系统的一个非常重要的约束是任何UI元素都必须放置在Canvas GameObject中,因此我们需要处理这一点,当这个PlayerUI Prefab将被实例化时,我们将在初始化PlayerUI时执行此操作。

1.打开脚本PlayerUI

2.在MonoBehaviour Messages区域内添加此方法

void Awake()

    this.GetComponent<Transform>().SetParent (GameObject.Find("Canvas").GetComponent<Transform>());


为什么要找Canvas? 因为当场景要加载和卸载时,我们的Prefab也是如此,画布将会每次都有所不同。 为了避免更复杂的代码结构,我们将以最快的方式。 

Following the targeted Player

我们需要在屏幕上播放Player UI。 这意味着要解决的几个小问题:

UI是一个2d元素,角色是一个3d元素。 在这种情况下,我们如何匹配显示?

我们不希望UI用户界面轻轻的摆放在角色头顶上,我们怎么能从屏幕上偏离角色的位置呢?

1打开PlayerUI脚本

2在公共属性区域内添加此公共属性

[Tooltip("Pixel offset from the player target")]

public Vector3 ScreenOffset = new Vector3(0f,30f,0f);

3在私有属性消息区域内添加这两个私有属性

float _characterControllerHeight = 0f;

Transform _targetTransform;

Vector3 _targetPosition;

4_target设置后,将以下代码附加到SetTarget()方法。

CharacterController _characterController = _target.GetComponent<CharacterController> ();

// Get data from the Player that won't change during the lifetime of this Component

if (_characterController != null)

_characterControllerHeight = _characterController.height;


我们知道我们的角色是基于CharacterController组件的,它具有一个Height属性,我们需要这样做才能对Player上的UI元素进行适当的偏移。

5在公共方法区域中添加此公共方法

void LateUpdate() 

// #Critical

// Follow the Target GameObject on screen.

if (_targetTransform!=null)

    _targetPosition = _targetTransform.position;

    _targetPosition.y += _characterControllerHeight;

    this.transform.position = Camera.main.WorldToScreenPoint (_targetPosition) + ScreenOffset;

保存脚本

因此,将2d位置与3d位置匹配的技巧是使用CameraWorldtoScreenPoint功能,因为在我们的游戏中,我们只有一个,我们可以把Unity Scene的默认设置的主摄像头。

注意我们如何在几个步骤中设置偏移量:首先我们得到目标的实际位置,然后添加_characterControllerHeight,最后,在推断出Player顶部的屏幕位置之后,我们添加了屏幕偏移量。


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

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


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


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