提示:素材來源網路,侵權必刪
Unity3D 多層血條特效
- 效果圖
- 滑鼠左右鍵控制其血條增減
- 一、準備專案工程
- 1.創建專案,準備一個物體如圖
- 2.制作血條預制體,把此預制體放在Resources下
- 二、效果代碼
- 1.創建Controller腳本掛在Hierarchy下創建的物體上
- 2.創建LifeBar腳本
- 3.創建LifeBarItem腳本
- 總結
效果圖
滑鼠左右鍵控制其血條增減

提示:以下是本篇文章正文內容,下面案例可供參考
一、準備專案工程
1.創建專案,準備一個物體如圖
提示:Hierarchy面板需準備如下

2.制作血條預制體,把此預制體放在Resources下
提示:創建四個Image按此排列

二、效果代碼
1.創建Controller腳本掛在Hierarchy下創建的物體上
代碼如下(示例):
using System.Collections.Generic;
using UnityEngine;
namespace HKZ
{
/// <summary>
/// 測驗代碼
/// </summary>
public class Controller : MonoBehaviour
{
private LifeBar bar;
private void Start()
{
Canvas canvas = FindObjectOfType<Canvas>();
if (canvas == null)
{
Debug.LogError("場景中沒有Canvas組件");
return;
}
SpawnLifeBar(canvas);
}
/// <summary>
/// 生成血條
/// </summary>
/// <param name="canvas"></param>
private void SpawnLifeBar(Canvas canvas)
{
GameObject prefab = Resources.Load<GameObject>("LifeBar");
bar = Instantiate(prefab, canvas.transform).AddComponent<LifeBar>();
List<LifeBarDate> date = new List<LifeBarDate>();
date.Add(new LifeBarDate(null, Color.green));
date.Add(new LifeBarDate(null, Color.red));
date.Add(new LifeBarDate(null, Color.yellow));
bar.Init(transform, 350, date);
}
/// <summary>
/// 控制物體移動
/// </summary>
private void Update()
{
if (Input.GetKey(KeyCode.A))
{
Move(Vector3.left);
}
if (Input.GetKey(KeyCode.D))
{
Move(Vector3.right);
}
if (Input.GetKey(KeyCode.W))
{
Move(Vector3.up);
}
if (Input.GetKey(KeyCode.S))
{
Move(Vector3.down);
}
if (Input.GetMouseButtonDown(0))
{
int ran = Random.Range(10, 50);
bar.ChangeLife(-ran);
}
if (Input.GetMouseButtonDown(1))
{
int ran = Random.Range(10, 50);
bar.ChangeLife(ran);
}
}
/// <summary>
/// 物體移動
/// </summary>
/// <param name="dircetion"></param>
private void Move(Vector3 dircetion)
{
transform.Translate(dircetion * Time.deltaTime * 5);
}
}
}
2.創建LifeBar腳本
代碼如下(示例):
using System.Collections.Generic;
using UnityEngine;
namespace HKZ
{
public class LifeBar : MonoBehaviour
{
private Transform _target;//要跟隨的物體
private Vector3 offset;//跟隨物體的偏移量
private List<LifeBarDate> Dates;
private LifeBarItem nextBar;//下一個血條
private LifeBarItem currentBar;//當前血條
private float unitLifeScale;//血條大小
private int currentIndex;//當前是哪個血條
/// <summary>
/// 初始化資料
/// </summary>
/// <param name="target"></param>
/// <param name="lifeMax"></param>
/// <param name="lifeBarDates"></param>
public void Init(Transform target, int lifeMax, List<LifeBarDate> lifeBarDates)
{
currentIndex = 0;
_target = target;
offset = GetOffset(target);
Dates = lifeBarDates;
nextBar = transform.Find("NextBar").gameObject.AddComponent<LifeBarItem>();
currentBar = transform.Find("CurrentBar").gameObject.AddComponent<LifeBarItem>();
nextBar.Init();
currentBar.Init();
RectTransform rect = GetComponent<RectTransform>();
unitLifeScale = rect.rect.width * Dates.Count / lifeMax;//拿到血條大小
SetBarDate(currentIndex, lifeBarDates);
}
/// <summary>
/// 得到目標物最上方位置
/// </summary>
/// <param name="target"></param>
/// <returns></returns>
private Vector3 GetOffset(Transform target)
{
Renderer renderer = target.GetComponent<Renderer>();
if (renderer == null)
{
return Vector3.zero;
}
return Vector3.up * renderer.bounds.max.y;
}
private void Update()
{
if (_target == null)
{
return;
}
//跟隨目標物
transform.position = Camera.main.WorldToScreenPoint(_target.position + offset + new Vector3(0, 9, 0));
}
/// <summary>
/// 更新血條變化
/// </summary>
/// <param name="value"></param>
public void ChangeLife(float value)
{
float Width = currentBar.ChangeLife(value * unitLifeScale);
if (Width < 0 && ChangeIndex(1))
{
Exchange();
currentBar.transform.SetAsLastSibling();
nextBar.ResetToWidth();
SetBarDate(currentIndex, Dates);
ChangeLife(Width / unitLifeScale);
}
else if (Width > 0 && ChangeIndex(-1))
{
Exchange();
currentBar.transform.SetAsLastSibling();
currentBar.ResetToZero();
SetBarDate(currentIndex, Dates);
ChangeLife(Width / unitLifeScale);
}
}
/// <summary>
/// -1代表加血 1代表減血
/// </summary>
/// <param name="symbol"></param>
private bool ChangeIndex(int symbol)
{
int index = currentIndex + symbol;
if (index >= 0 && index < Dates.Count)
{
currentIndex = index;
return true;
}
return false;
}
private void Exchange()
{
var temp = nextBar;
nextBar = currentBar;
currentBar = temp;
}
public void SetBarDate(int index, List<LifeBarDate> date)
{
if (index < 0 || index >= date.Count)
{
return;
}
currentBar.SetDate(Dates[index]);
if (index + 1 >= date.Count)
{
nextBar.SetDate(new LifeBarDate(null, Color.white));
}
else
{
nextBar.SetDate(date[index + 1]);
}
}
}
/// <summary>
/// 血條資料
/// </summary>
public struct LifeBarDate
{
public Sprite BarSprite;
public Color BarMainColor;
public LifeBarDate(Sprite barSprite, Color barMainColor)
{
BarSprite = barSprite;
BarMainColor = barMainColor;
}
}
}
3.創建LifeBarItem腳本
代碼如下(示例):
using DG.Tweening;
using UnityEngine;
using UnityEngine.UI;
namespace HKZ
{
public class LifeBarItem : MonoBehaviour
{
private RectTransform rect;
public RectTransform Rect
{
get
{
if (rect == null)
{
rect = GetComponent<RectTransform>();
}
return rect;
}
}
private Image image;
public Image Image
{
get
{
if (image == null)
{
image = GetComponent<Image>();
}
return image;
}
}
private float defaultWidth;
private LifeBarItem child;
/// <summary>
/// 初始化資料
/// </summary>
public void Init()
{
if (transform.Find("AdditionBar") != null)
{
child = transform.Find("AdditionBar").gameObject.AddComponent<LifeBarItem>();
}
defaultWidth = Rect.rect.width;
}
/// <summary>
/// 設定資料
/// </summary>
/// <param name="date"></param>
public void SetDate(LifeBarDate date)
{
Image.color = date.BarMainColor;
if (date.BarSprite != null)
{
Image.sprite = date.BarSprite;
}
if (child != null)
{
child.SetDate(date);
}
}
/// <summary>
/// 更變血條
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public float ChangeLife(float value)
{
if (child != null)
{
child.DOKill();
child.Image.color = Image.color;
child.Rect.sizeDelta = Rect.sizeDelta;
child.Image.DOFade(0, 0.5f).OnComplete(() => child.ChangeLife(value));
}
Rect.sizeDelta += Vector2.right * value;
return GetOutRange();
}
/// <summary>
/// 得到當前血條
/// </summary>
/// <returns></returns>
private float GetOutRange()
{
float offset = 0;
if (Rect.rect.width < 0)
{
offset = Rect.rect.width;
ResetToZero();
}
else if (Rect.rect.width > defaultWidth)
{
offset = Rect.rect.width - defaultWidth;
ResetToWidth();
}
return offset;
}
/// <summary>
/// 扣血顯示下一條時恢復默認狀態
/// </summary>
public void ResetToZero()
{
Rect.sizeDelta = Vector2.zero;
}
/// <summary>
/// 加血顯示下一條時恢復默認狀態
/// </summary>
public void ResetToWidth()
{
Rect.sizeDelta = Vector2.right * defaultWidth;
}
}
}
效果出來了吧!

總結

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/286700.html
標籤:其他
上一篇:Unity3d中UGUI組件精簡復盤(二)Canvas及其相關組件
下一篇:JS實作簡單的坦克坦克移動及換向
