由于要使得血条跟随敌人,我把血条UI设置为敌人的子级,并赋值给每个敌人。
要使敌人被击中后相应的减少血量,MaxValue和Value就不需要序列化了,所以我把它们设为了private,然后在Change函数里传入子弹的伤害值DanmageValue就行了,但是有一个问题,子弹是未实例化的,所以要将DanmageValue设为static,如果在Update函数里调用还要去判断是否trigger,不如直接在子弹的脚本里调用Change更省事。
public class EnemyBar : MonoBehaviour
{
private int MaxValue;
private int Value;
[SerializeField]
private RectTransform white;
[SerializeField]
private RectTransform red;
[SerializeField]
private float _animationSpeed = 10f;
private float _fullWidth;
private float TargetWidth => Value * _fullWidth / MaxValue;
private Coroutine _adjustBarWidthCoroutine;
private void Start()
{
MaxValue = GetComponentInParent<EnemyController>().hp;
_fullWidth = red.rect.width;
}
public void Change(int amount)
{
Value = Mathf.Clamp(Value + amount, 0, MaxValue);
if (_adjustBarWidthCoroutine != null)
{
StopCoroutine(_adjustBarWidthCoroutine); //关闭上一次的协程
}
_adjustBarWidthCoroutine = StartCoroutine(AdjustBarWidth(amount));
}
private IEnumerator AdjustBarWidth(int amount)
{
var suddenChangeBar = amount >= 0 ? white : red;
var slowChangeBar = amount >= 0 ? red : white;
suddenChangeBar.setWidth(TargetWidth);
while(Mathf.Abs(suddenChangeBar.rect.width-slowChangeBar.rect.width)>0.1f)
{
slowChangeBar.setWidth(Mathf.Lerp(slowChangeBar.rect.width, TargetWidth,
Time.deltaTime * _animationSpeed));
yield return null; //下一帧再执行下一次循环,直到循环结束
}
slowChangeBar.setWidth(TargetWidth);
//yield return 0;
}
}
public static class RectTransformExtension
{
public static void setWidth(this RectTransform t,float width)
{
t.sizeDelta = new Vector2(width, t.rect.height);
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
EnemyController enemyController = collision.gameObject.GetComponent<EnemyController>();
if(enemyController!=null)
{
if(GameObject.Find(" 齿轮增强器").GetComponent<GearEnhance>().enabled)
{
DamageValue += 9;
}
else
{
DamageValue = 1;
}
collision.gameObject.GetComponentInChildren<EnemyBar>().Change(-DamageValue);
enemyController.hp= enemyController.hp-DamageValue;
if(enemyController.hp<=0)
{
enemyController.Fix();
}
}
Destroy(gameObject);
}
测试后还是发现了一个问题:敌人被击一次血条就见底。
于是我要看看MaxValue和Value的值
private void Start()
{
MaxValue = GetComponentInParent<EnemyController>().hp;
Debug.Log(MaxValue+"/"+Value);
_fullWidth = red.rect.width;
}
原来是Value忘了赋值,在后面添加一句Value = MaxValue;就好了
在敌人被修复后关闭血条
很简单只需要两行: public GameObject Bar; Bar.SetActive(false);
再把canvas_EnemyBar赋值给Bar就行了。
明天我会创造一个更强的Boss,拥有更厚的血量,并且被击的部位不同受到的伤害也不同,攻击力更强且有一个强大的技能。