25、血量Canvas的制作
更改血条颜色
让滚动条右边的圆点消失(已经操作后的截图)
各组件配置如下:
在场景中,让名字置于血条前方
26、血量的显示
在Player.cs中更新代码:
using System;
using UnityEngine;
using UnityEngine.UI;
using Mirror;
public class Player : NetworkBehaviour
{
……
public Text label;
public Image hpImage;
public Slider healthSlider;
……
public override void OnStartClient()
{
Team team = GameManager.GetInstance().teams[teamIndex];
for (int i = 0; i < renderers.Length; i++) // 遍历所有需要渲染的对象,即杆子和旗面
{
renderers[i].material = team.material;
}
// HP颜色的修改
label.text = "Player";
hpImage.color = team.color;
}
……
}
将HUD这些canvas始终朝向摄像机
在LookAtCam.cs添加代码:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LookAtCam : MonoBehaviour
{
private Transform camTransform;
private Transform myTransform;
private void Awake()
{
camTransform = Camera.main.transform;
myTransform = this.transform;
}
private void Update()
{
myTransform.LookAt(myTransform.position + camTransform.rotation * Vector3.forward, camTransform.rotation * Vector3.up);
}
}
测试
27、子弹功能的实现
由于子弹速度快,因此将碰撞检测换为连续,效果好点
在Bullet更新代码:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;
public class Bullet : NetworkBehaviour
{
……
public int damage = 3;
……
[HideInInspector] [SyncVar] public GameObject owner;
……
private void OnTriggerEnter(Collider other)
{
GameObject obj = other.gameObject; // 获取子弹碰撞的对象
Player player = obj.GetComponent<Player>(); // 获取该对象的player组件,如果无返回Null
if (player != null) // 碰撞对象是坦克
{
if (player.gameObject == owner) return; // 是自己
if (player.teamIndex == owner.GetComponent<Player>().teamIndex) return; // 是同类
player.killedBy = owner;
}
if (!isServer) return;
if(player) player.TankDamage(this); // 触发坦克少血机制
Destroy(this.gameObject); // 子弹销毁
}
}
在Player.cs中添加如下代码:
using System;
using UnityEngine;
using UnityEngine.UI;
using Mirror;
public class Player : NetworkBehaviour
{
……
[HideInInspector] public int maxHealth;
[HideInInspector] [SynVar] public GameObject killedBy; // 击杀对象
……
[HideInInspector] [SyncVar(hook = nameof(OnHealthChange))] public int health = 10;
……
private void Awake()
{
……
maxHealth = health;
}
……
……
[Command]
void CmdShoot(short xPos, short zPos)
{
……
obj.GetComponent<Bullet>().owner = gameObject;
……
}
……
[Server]
public void TankDamage(Bullet bullet)
{
health -= bullet.damage;
if (health <= 10)
{
// 当前玩家死亡
}
}
protected void OnHealthChange(int oldValue, int newValue)
{
health = newValue;
healthSlider.value = (float)health / maxHealth;
}
}
由于OnTriggerEnter的特殊性,可以看Unity基础篇。因为子弹和坦克都有刚体属性,而生成地没有刚体属性,所以子弹和坦克的Collider组件中,is trigger需要打勾, 此使坦克之间的碰撞也就失效了,而是执行 OnTriggerEnter函数的逻辑。
而子弹和生产地中有一个有刚体,所以无论如何都会触发OnTriggerEnter函数
测试