两种方式实现血条
分析两种实现的优缺点
IMGUI
官方提供的是OnGUI函数来开发UI界面,当然问题也比较多,首先不支持可视化开发,其次UI始终位于所有3D对象的上方,无法实现在UI上添加3D模型的效果。
IMGUI开发简单,仅需几行代码,但是IMGUI需要在将3D位置映射到屏幕位置后,如果对结果进行加减,会使得血条位置偏移过多。
UGUI
优点:
1. 首先,5.2版本之后,Unity逐渐将一部分UGUI的计算放到子线程去做,以此来缓解主线程的压力;
2. UGUI有锚点,更方便屏幕自适应。
UGUI尚未成熟,但毕竟是官方的,新出的unity5使用了全新的ab打包方式,看上去要封杀ngui的样子。
缺点:
1. UGUI如果人物过多,需要太多的canvas
一、使用IMGUI实现血条
IMGUI实现
将下面的脚本挂载在游戏对象上就行了
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class IMGUI : MonoBehaviour {
public float healthPanelOffset = 2f;
private void OnGUI()
{
Vector3 worldPos = new Vector3(transform.position.x, transform.position.y, transform.position.z);
Vector2 screenPos = Camera.main.WorldToScreenPoint(worldPos);
Rect rect = new Rect(screenPos.x -50,screenPos.y,100,100);
GUI.HorizontalScrollbar(rect, 0, 75, 0, 100);
}
}
UGUI实现
- 首先,通过菜单 Assets -> Import Package -> Characters 导入资源
- 在层次视图,Context 菜单 -> 3D Object -> Plane 添加 Plane 对象
- 资源视图展开 Standard Assets :: Charactors :: ThirdPersonCharater :: Prefab
- 将 ThirdPersonController 预制拖放放入场景,改名为 Ethan
- 检查以下属性
- Plane 的 Transform 的 Position = (0,0,0)
- Ethan 的 Transform 的 Position = (0,0,0)
- Main Camera 的 Transform 的 Position = (0,1,-10)
- 选择 Ethan 用上下文菜单 -> UI -> Canvas, 添加画布子对象
- 选择 Ethan 的 Canvas,用上下文菜单 -> UI -> Slider 添加滑条作为血条子对象
- 选择 Ethan 的 Canvas,在 Inspector 视图
- 展开 Slider
- 选择 Handle Slider Area,禁灰(disable)该元素
- 选择 Background,禁灰(disable)该元素
- 选择 Fill Area 的 Fill,修改 Image 组件的 Color 为 红色
- 选择 Slider 的 Slider 组件
- 设置 MaxValue 为 100
- 设置 Value 为 75
将下面的脚本挂载在ethen上
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class UIScript : MonoBehaviour {
public Canvas canvas;
public GameObject healthPrefab;
public float healthPanelOffset = 2f;
public GameObject healthPanel;
private Slider healthSlider;
// Use this for initialization
void Start () {
healthPanel = Instantiate(healthPrefab) as GameObject;
healthPanel.transform.SetParent(canvas.transform, false);
healthSlider = healthPanel.GetComponentInChildren<Slider>();
Vector3 worldPos = new Vector3(transform.position.x, transform.position.y + healthPanelOffset, transform.position.z);
Vector3 screenPos = Camera.main.WorldToScreenPoint(worldPos);
healthPanel.transform.position = new Vector3(screenPos.x, screenPos.y, screenPos.z);
}
// Update is called once per frame
void Update () {
Vector3 worldPos = new Vector3(transform.position.x, transform.position.y + healthPanelOffset, transform.position.z);
Vector3 screenPos = Camera.main.WorldToScreenPoint(worldPos);
healthPanel.transform.position = new Vector3(screenPos.x, screenPos.y, screenPos.z);
}
}