游戏开发日志9(敌人血条制作)

原理其实很简单,先通过UI创建一张image,和一个mask,通过改变mask的width值来显示血量的剩余量,但是我想要稍稍改进一下,让血量decrease/increase不那么突兀。

这里使用到了Coroutine(协程):

关于协程
1,什么是协程
协程,从字面意义上理解就是协助程序的意思,我们在主任务进行的同时,需要一些分支任务配合工作来达到最终的效果

稍微形象的解释一下,想象一下,在进行主任务的过程中我们需要一个对资源消耗极大的操作时候,如果在一帧中实现这样的操作,游戏就会变得十分卡顿,这个时候,我们就可以通过协程,在一定帧内完成该工作的处理,同时不影响主任务的进行

2,协程的原理
首先需要了解协程不是线程,协程依旧是在主线程中进行

然后要知道协程是通过迭代器来实现功能的,通过关键字IEnumerator来定义一个迭代方法。

IEnumerator都需要一个yield return 返回

 3、协程的使用
首先通过一个迭代器定义一个返回值为IEnumerator的方法,然后再程序中通过StartCoroutine来开启一个协程即可:

在正式开始代码之前,需要了解StartCoroutine的两种重载方式:

StartCoroutine(string methodName):这种是没有参数的情况,直接通过方法名(字符串形式)来开启协程
StartCoroutine(IEnumerator routine):通过方法形式调用
StartCoroutine(string methodName,object values):带参数的通过方法名进行调用

在一个协程开始后,同样会对应一个结束协程的方法StopCoroutine与StopAllCoroutines两种方式,但是需要注意的是,两者的使用需要遵循一定的规则,在介绍规则之前,同样介绍一下关于StopCoroutine重载:

StopCoroutine(string methodName):通过方法名(字符串)来进行
StopCoroutine(IEnumerator routine):通过方法形式来调用
StopCoroutine(Coroutine routine):通过指定的协程来关闭
刚刚我们说到他们的使用是有一定的规则的,那么规则是什么呢,答案是前两种结束协程方法的使用上,如果我们是使用StartCoroutine(string methodName)来开启一个协程的,那么结束协程就只能使用StopCoroutine(string methodName)和StopCoroutine(Coroutine routine)来结束协程。

接下来写一个EnemyBar脚本,挂在Canvas_EnemyBar上,调好参数。

 

public class EnemyBar : MonoBehaviour
{
    [field: SerializeField]
    public int MaxValue { get; private set; }
    [field: SerializeField]
    public int Value { get; private set; }

    [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()
    {
        _fullWidth = red.rect.width;
    }

    private void Update()
    {
        if (Input.GetKeyDown("k"))
        {
            Change(20);
        }
        if (Input.GetKeyDown("l"))
        {
            Change(-20);
        }
    }

    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);
    }
}

这里仅为测试代码,后续我会让它跟随机器人移动,并且相应变化。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值