本文来自网易云社区
作者:汪毅军
在游戏中,头顶血条的是一个非常常见的功能,其中血条可分为2D血条和3D血条。2D血条不会随着模型远近而变化,始终保持着相同的大小;但3D血条会随着模型远近移动而产生透视,会显得比较真实。在大多数情况下,我们应该都会选择2D血条,当然也有一些特殊的地方3D血条会更加合适,今天就来看看这两种实现方案。
2D血条的实现思路
首先需要确定模型头顶的坐标,该坐标可以直接在模型上预设好也可以直接通过计算
Collider
来获取。
我们拿到头顶的世界坐标后,通过3D相机把这个点转换到屏幕坐标,然后这个坐标就是血条的位置。
剩下的就是根据位置调整显示血条即可。
2D血条的实现
实现2D血条的话,需要将
Canvas
的
RenderMode
调整为
ScreenSpace-Overlay
。这个
Canvas
是所有的UI组件共用的。具体结构如下:
然后通过Slider制作血条
接下来按照实现思路来实现相关代码。由于2D血条没有透视问题,所以只需实时更新血条位置即可。
public class CHpBar : MonoBehaviour
private Slider hpSlider;
private RectTransform rectTrans;
public Transform target;
public Vector3 offsetPos; //头顶偏移量
private void Start()
hpSlider = GetComponent<Slider>();
rectTrans = GetComponent<RectTransform>();
//更新血量
//hpSlider.value
private void Update()
if(target==null) return;
//通过Collider来获取头顶坐标
var col = target.GetComponent<Collider>();
var topAhcor = new Vector3(col.bounds.center.x, col.bounds.max.y, col.bounds.center.z);
//加上头顶偏移量
Vector3 tarPos = topAhcor;
var viewPos = Camera.main.WorldToViewportPoint(tarPos); //得到视窗坐标
Vector2 screenPos;
if (viewPos.z > 0f && viewPos.x > 0f && viewPos.x < 1f && viewPos.y > 0f && viewPos.y < 1f)
//获取屏幕坐标
screenPos = Camera.main.WorldToScreenPoint(tarPos+offsetPos); //加上头顶偏移量
//不在可视窗口的模型,把名字移动到视线外
screenPos = Vector3.up * 3000f;
//转化为屏幕坐标
rectTrans.position = screenPos;
可以发现,不论模型怎么移动,2D血条始终都会朝向保持着原始大小。
3D血条的实现思路
3D的话就得把血条固定在模型头上面
每一帧都得根据模型的旋转来调整血条,使血条始终朝着摄像机,这样才不会导致血条旋转、缩放等问题
3D血条的实现
3D血条需要将Canvas
的RenderMode
调整为World Space
。并且将Canvas
作为模型的Child。具体结构如下:
代码的实现比较简单,直接矫正画布使其一直朝着摄像机
public class CHpCanvas : MonoBehaviour
private void Update()
transform.rotation = Camera.main.transform.rotation;
可以发现,3D血条会跟随模型产生透视效果
两个血条方案各有自己的适用场景。3D血条更加真实,但是由于一个对象一个Canvas
,所以性能方面没有2D血条好。2D血条的话在显示效果上没有3D的好,但是性能方面比3D的好。此外在于一些特殊情况下(比如摄像机绘制RenderTexture),使用3D血条的去处理要比2D血条要简便很多。
参考文章: https://www.jianshu.com/p/a9fd13594f18
网易云免费体验馆,0成本体验20+款云产品!