王者荣耀实时对战服务器Photon之PUN玩家UI预设
本节将指导您创建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.将子物体GameObject“Player 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位置匹配的技巧是使用Camera的WorldtoScreenPoint功能,因为在我们的游戏中,我们只有一个,我们可以把Unity Scene的默认设置的主摄像头。
注意我们如何在几个步骤中设置偏移量:首先我们得到目标的实际位置,然后添加_characterControllerHeight,最后,在推断出Player顶部的屏幕位置之后,我们添加了屏幕偏移量。
不管你有关于Photon产品的问题或者是Photon价格问题或者Photon教程方面的问题或者其他问题都可以联系我们给我我们留言,我们真诚的为您服务。
关注我们公众号PhotonServer 获取最新教程资源。
王者荣耀实时对战服务器Photon之Pun应用系列文章 如果你喜欢请关注我公众号,并推荐给你你的小伙伴,谢谢。