血条(Health Bar)的预制设计。具体要求如下:
分别使用 IMGUI 和 UGUI 实现使用 UGUI,血条是游戏对象的一个子元素,任何时候需要面对主摄像机分析两种实现的优缺点给出预制的使用方法因为要求使用UGUI时,血条是游戏对象的一个子元素,所以先创建一个游戏对象:
在Hierarchy窗口右击打开上下文菜单,选择3D Object,选择Plane,为游戏对象添加基本的舞台。点击菜单栏中的Assets,点击Import Package,选择Characters,然后一步步操作引入资源。展开资源视图Standard Assets::Characters::ThirdPersonCharacter::Prefabs,然后将预制体ThirdPersonController拖入Hierarchy窗口,改名为Ethan。检查以下属性 Plane 的 Transform 的 Position = (0,0,0)Ethan 的 Transform 的 Position = (0,0,0),Rotation = (0,180,0)Main Camera 的 Transform 的 Position = (0,1,-10)运行检查成果,控制人物来回走动。然后为人物加上血条:
给Ethan添加Canvas子对象:右击Ethan,选择UI,选择Canvas。选中Ethan的子对象Canvas,在Inspector视图修改Canvas的属性: 将Canvas组件中的Render Mode设为World Space。将Rect Transform组件的(Pos X, Pos Y, Width, Height)设置为(0,2,160,20)。将Rect Transform组件中的Scale(X, Y)设置为(0.01, 0.01)。 选择Ethan的子对象Canvas,选择上下文菜单中UI的Slider,添加滑条作为血条子对象。然后展开Slider: 将Handle Slide Area禁灰。将Background的Left设为-10,Scale X设为0.88,即将Background设置为血条的边框。将Fill Area展开,将Fill的Image组件中的Color选为红色。选择Slider,将Slider组件的Min Value设为0,将Max Value设为100。运行检查成果运行后发现血条能跟随游戏对象移动,但是却不能一直朝向主摄像机,这需要给Canvas添加脚本LookAtCamera.cs:
using UnityEngine; public class LookAtCamera : MonoBehaviour { void Update() { this.transform.LookAt(Camera.main.transform.position); } }然后再给角色Ethan的子对象Canvas添加一个血条的控制器HealthControl.cs:
using UnityEngine; using UnityEngine.UI; public class HealthControl : MonoBehaviour { // 血条 public Slider mainSlider; // 恢复血的时间的间隔 public float duration = 10; // 用于计时 private float dur_time = 0; // 当前血量 private float health; // 增/减后血量 private float resultHealth; // 增减血 private bool flag = false; void Start () { // 设置最大血量、最小血量、回血间隔以及现在血量 mainSlider.maxValue = 100; mainSlider.minValue = 0; duration = 10; // mainSlider.wholeNumbers = true; mainSlider.value = mainSlider.maxValue / 2; health = mainSlider.value; resultHealth = health; } void Update () { // 计时以回血 if(mainSlider.value < mainSlider.maxValue - 0.1 && !flag) { dur_time += Time.deltaTime; if(dur_time >= duration) { resultHealth = mainSlider.value + 10 > mainSlider.maxValue ? mainSlider.maxValue : mainSlider.value + 10; dur_time = 0; } } // 发生碰撞,减血 else if (flag) { resultHealth = mainSlider.value - 20 < mainSlider.minValue ? mainSlider.minValue : mainSlider.value - 20; flag = false; } // 平滑减少血量 health = Mathf.Lerp(health, resultHealth, 0.05f); mainSlider.value = health; // 控制slider中Fill Area的显示,以更符合血量的显示 if (mainSlider.value <= 0.01) mainSlider.transform.GetChild(1).localScale = Vector3.zero; else mainSlider.transform.GetChild(1).localScale = Vector3.one; } // 外部控制减少血量 public void ReduceHealth() { flag = true; } }然后将血条Slider添加到脚本HealthControl中: 然后检验一下血量控制的脚本: - 添加一个cube,右键点击Hierarchy窗口打开上下文窗口,选择3D Object,选择Cube,然后给Cube添加一个碰撞检测脚本CubeCollide.cs:
using UnityEngine; public class CubeCollide : MonoBehaviour { private void OnCollisionEnter(Collision collision) { if(collision.gameObject.name == "Ethan") { collision.gameObject.GetComponentInChildren<HealthControl>().ReduceHealth(); } } } 调整cube的大小:在Inspector窗口将Scale X设置为5运行检测一下:思路:用HorizontalScrollbar(水平滚动条)的宽度作为血条的显示值: - 右击Hierachy窗口打开上下文菜单,选择Create Empty,重命名为IMGUI_HealthBar。 - 给IMGUI_HealthBar添加脚本IMGUIHealthControl.cs:
using UnityEngine; public class IMGUIHealthControl : MonoBehaviour { // 当前血量 public float health = 50; // 增/减后血量 private float resultHealth = 0; private Rect bloodBar; private Rect upButton; private Rect downButton; void Start () { // 初始值 health = 50; resultHealth = 50; // 居中 float w = Screen.width; float h = Screen.height; // 血条横向 bloodBar = new Rect((w - 200) / 2, (h - 20) / 2, 200, 20); // 加血按钮 upButton = new Rect(w / 3, 100, 40, 20); // 减血按钮 downButton = new Rect(w / 3 * 2, 100, 40, 20); } void OnGUI () { if (GUI.Button(upButton, "加血")) resultHealth = health + 10 > 100 ? 100 : health + 10; if (GUI.Button(downButton, "减血")) resultHealth = health - 10 < 0.1 ? 0 : health - 10; GUI.color = new Color(0.2f, 0.2f, 0.2f, 0.5f); health = Mathf.Lerp(health, resultHealth, 0.05f); GUI.HorizontalScrollbar(bloodBar, 0, health, 0, 100); } } 运行检测一下:前面没有使用预制,在这里得修改一下:
在Project窗口新建文件夹Resources,在Resources里面新建文件夹Prefabs。然后将Ethan里面的Canvas对象拖曳到Prefabs里面制作成预制体,重命名为UGUI_HealthBar,将IMGUI_HealthBar也拖曳下来。使用Prefabs里面的UGUI_HealthBar预制体制作血条:给Ethan添加LoadResources.cs脚本 using UnityEngine; public class LoadResources : MonoBehaviour { private void OnEnable() { if(gameObject.name == "Ethan") { Canvas canvas = Instantiate(Resources.Load("Prefabs/UGUI_HealthBar", typeof(Canvas)), Vector3.zero, Quaternion.identity, null) as Canvas; canvas.gameObject.SetActive(true); canvas.gameObject.transform.SetParent(this.transform); } else { GameObject gameObject = Instantiate(Resources.Load("Prefabs/IMGUI_HealthBar", typeof(GameObject)), Vector3.zero, Quaternion.identity, null) as GameObject; gameObject.SetActive(true); } } } 使用Prefabs里面的IMGUI_HealthBar预制体制作血条:在Hierachy窗口添加一个空对象Main,添加脚本LoadResources.cs。运行检测一下。最终运行效果是与没有使用预制体的时候是一致的。