在上篇末尾是不是看到了玩家头上的绿色?没错吗,那就是它的血条,下面来一步一步制作
血条是使用的UGUI的Slider制作的,结构如下:
分别设置Background和fill的颜色为红色和绿色。这个就不详细赘述了。
给玩家添加Health脚本,代码如下:
private int MaxHP = 100;
public Slider Slider;
public int CurrentHP;
private void Start()
{
CurrentHP = MaxHP;
}
public void TakeDamage(int damage)
{
if (!isServer) return;
CurrentHP -= damage;
ShowHPSlider();
if (CurrentHP <= 0)
{
CurrentHP = 0;
CurrentHP = 100;
}
}
public void ShowHPSlider()
{
Slider.value = CurrentHP / (float)MaxHP;
}
然后给子弹添加Bullet脚本,代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Bullet : MonoBehaviour {
private void OnCollisionEnter(Collision collision)
{
collision.gameObject.GetComponent<Health>().TakeDamage(10);
Destroy(this.gameObject);
}
}
只需要进行碰撞检测调用玩家的受伤方法。这样写完后进行测试会发现血是在掉,可是血条在客户端和服务器并不同步。
因为子弹是在服务器生成,由于网络延迟等原因,当服务器的子弹先一步接触玩家子弹会立即销毁,这时候其他客户端的子弹可能在还没有碰到其他玩家的情况下也被销毁了,于是服务器端子弹碰到的玩家会掉血,而客户端上面显示的由于子弹没有与玩家接触到所以不会掉血。效果如下:
这个时候我们需要让玩家的血量在服务器上面操作然后同步给客户端,首先我们给CurrentHP添加[SyncVar]特性使变量在服务器做更改同步到客户单,然后添加一个方法每当血量变化时在客户端改变Slider的值,修改代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
public class Health : NetworkBehaviour
{
public bool IsEnemy;//是否是敌人
private int MaxHP = 100;//最大血量
public Slider Slider;
[SyncVar(hook =("ShowHPSlider"))]//然CurrentHP在服务器做更改并同步到客户端。钩子勾住一个方法
public int CurrentHP;
private NetworkStartPosition[] startPos;//玩家的开始生成位置数组
private void Start()
{
startPos = GameObject.FindObjectsOfType<NetworkStartPosition>();
CurrentHP = MaxHP;
}
/// <summary>
/// 受伤方法
/// </summary>
/// <param name="damage"></param>
public void TakeDamage(int damage)
{
if (!isServer) return;//血量的变化只在服务器执行
CurrentHP -= damage;
if (CurrentHP <= 0)
{
CurrentHP = 0;
if (IsEnemy)
{
Destroy(this.gameObject);//是敌人没血直接删除
}
RpcResSpawn();//是玩家没血则重生
CurrentHP = 100;//回复血量
}
}
/// <summary>
/// 在[SyncVar(hook())]的hook里面的方法,带的参数代表的特性所针对的变量,当变量值发生改变时就会调用这个方法
/// 更改血条的显示
/// </summary>
/// <param name="currentHp"></param>
public void ShowHPSlider(int currentHp)
{
Slider.value = currentHp / (float)MaxHP;
}
/// <summary>
/// 玩家的重生,
/// </summary>
[ClientRpc]///在服务器端调用下面的方法,在连接的客户端执行代码
public void RpcResSpawn()
{
if (startPos != null && startPos.Length > 0)
{
transform.position = startPos[Random.Range(0, startPos.Length)].transform.position;
}
}
}
下面在看看效果:
这里我们还需要为血条添加一个脚本使血条时刻面向摄像机避免玩家旋转血条跟着旋转:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UI_LookAtCamera : MonoBehaviour {
private void Update()
{
transform.LookAt(Camera.main.transform);
}
}
脚本挂在Canvas上面即可。
完全OK,这篇里面还设置了玩家的位置生成和死亡的重生,我们下篇在讲。
欢迎加群:4364930讨论。