赞
踩
总目录https://blog.csdn.net/qq_54263076/category_11900070.html?spm=1001.2014.3001.5482
1. 受击反馈
在我的程序里,我也使用了攻击碰撞盒的建立。并且是通过受击动画和击退来完成受击反馈的。最后通过协程来结束受击判定条件。当然根据大佬的教程来说,如果并没有受击动画的话,咱们可以改变动画播放速度+协程调回原来的速度和改变精灵图变白色来进行受击反馈。
敌人角色动画的创建
敌人状态机及其参数
如果手动验证的话,打开受伤参数Ishurt的话,你会停留在受伤状态hurt里,所以需要通过协程来自动将受伤参数调回false。
承接上面第4节课,攻击判定触发器更新
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
-
- public class attackTrigger : MonoBehaviour
- {
- private Transform player;//获取人物
- private Animator ani;//获取人物动画器
- private AnimatorStateInfo state;//动画状态
- private GameObject em;//敌人管理器,用来对象池
-
- public float atkItemsBack = 1;
- public float atkItemsUp = 1;
- public float playerSpeedInfectBack = 1;
- // Start is called before the first frame update
- void Start()
- {
- player = gameObject.transform.parent;
- ani = player.GetComponent<Animator>();
- em = GameObject.Find("EnemyManager");
-
- }
-
- // Update is called once per frame
- void Update()
- {
-
- }
- public void OnTriggerEnter2D(Collider2D collision)
- {
- //攻击到了物品或敌人产生击退
- if (collision.tag == "items" || collision.tag == "enemy")
- {
-
- //获取人物与物品位置向量
- Vector3 v = collision.transform.position-player.position ;
-
- //冻结z轴
- v.z = 0;
- //获取横轴,速度影响击退距离
- float h = Input.GetAxis("Horizontal");
-
- //如果处于动画2,4时额外实施向上的力、速度
- //挑飞
- state = ani.GetCurrentAnimatorStateInfo(0);
- if (state.IsName("attack2") || state.IsName("attack4"))
- {
- v.y += (atkItemsBack * 5*atkItemsUp);
- }
- collision.GetComponent<Rigidbody2D>().velocity=v* atkItemsBack+Vector3.right*h* playerSpeedInfectBack*5;
-
- }
- //攻击到了敌人
- if (collision.tag == "enemy")
- {
-
- //敌人受伤
-
- //找到被攻击到的敌人
- GameObject enemyGo = collision.gameObject;
-
- //受伤动画
- enemyGo.GetComponent<Animator>().SetBool("Ishurt",true);
- StartCoroutine(endHurt(enemyGo));//开启协程结束受伤动画
- //伤害计算
- enemyGo.GetComponent<CharacterPanel>().hurt(transform.parent.GetComponent<CharacterPanel>().Atk);
- /* //在敌人管理器中找到敌人对象池,并保存信息
- em.GetComponent<Pool>().Push(enemyGo);*/
-
- }
-
- }
- IEnumerator endHurt(GameObject enemyGo)
- {
-
- yield return 0;//此处暂停,下一帧执行
- enemyGo.GetComponent<Animator>().SetBool("Ishurt", false);
- StopCoroutine(endHurt( enemyGo));
-
- }
- }
上面的伤害计算hurt()函数就是我下面要讲的角色的面板脚本
2.为了方便进行数值计算,为每个角色增加角色面板脚本
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEngine.UI;
- public class CharacterPanel : MonoBehaviour
- {
-
- public float Hpmax = 100;//最大生命
- public float Hp = 100;//生命
- public float Atk = 10;//攻击力
- public float AtkRan = 1;//攻击浮动
- public float Def = 10;//防御力
- // Start is called before the first frame update
- void Start()
- {
-
- }
-
- // Update is called once per frame
- void FixedUpdate()
- {
- check();
- }
- //标准化检查
- private void check()
- {
- if (Hp > Hpmax) Hp = Hpmax;//血量不超过上限
- if (Hp < 0) Hp = 0;//血量不超过下限
- }
- public void hurt(float atk)
- {
-
- Hp -= (20*atk / (20 + Def))+ Random.Range(-AtkRan, AtkRan);
- Debug.Log(atk);
- }
- }
只要谁受伤了就直接调用它面板里的函数hurt
3.跟随血条+延迟血条的创建
由于血条需要移动,如果用UI的话(UI必须放在画布下面且固定),需要计算坐标,很难处理。所以直接加上去血条作为角色的子体更加方便,我们需要创建一个血条空对象。然后在血条项下加入最大血条,延迟扣血血条和目前血条三个空物体,并分别赋予不同的颜色。并未这三个空物体加上sprite渲染组件放血条图片。
注意为三个精灵图设置好图层顺序,按照实际效果显示
根据上面教程, 需要注意的是要更改血条精灵图的锚点为靠左边,这样可以通过控制localScale中x来使得图片缩短。注意:作为子物体,当调整HP的大小和位置的时候,子物体用的是相对坐标,它的Scale的x永远是1;
现在为HP加上脚本
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
-
- public class HPControl : MonoBehaviour
- {
- public float delHpSpeed = 1;//延迟血条减少速度
- public float delHpTime = 1;//延时血条减少时间间隔
- private CharacterPanel character ;//角色面板
- private Transform hpBox;//血条图片
- private Transform delhpBox;//延迟血条图片
- // Start is called before the first frame update
- void Start()
- {
- character = transform.GetComponentInParent<CharacterPanel>();
- hpBox = transform.GetChild(1);//0-HPmaxBox 1-hpBox 2-delhpBox
- delhpBox = transform.GetChild(2);
- }
-
- // Update is called once per frame
- void FixedUpdate()
- {
- check();
-
- }
- //检查血量变化控制血条
- private void check() {
-
- float x = character.Hp / character.Hpmax;
- if (delhpBox.localScale.x >= x)//延迟血条与血条有数差
- {
- hpBox.localScale = new Vector3(x, 1, 1);
- //延迟血条开启协程
- StartCoroutine(delHP(x));
- }
- }
- IEnumerator delHP(float x)
- {
- while (delhpBox.localScale.x >= x)//直到延迟血条完成
- {
- Debug.Log(1);
- yield return new WaitForSeconds(0.2f* delHpTime);//等待0.2*delHpTime秒
- delhpBox.localScale =new Vector3(delhpBox.localScale.x-0.0001f* delHpSpeed, 1, 1);
- }
- }
-
- }
其中协程是为了延迟执行需要,可以用来制作延迟扣血血条
完成了!!!
代码优化,在我后面调试中发现协程不止执行了一次,丢失了间隔执行的特性,下面是我的优化代码
思路就是引入一个新的变量deltime,if那一句中。加上可执行次数判断,协程执行完成后立刻让他变成0,在协程中,while语句执行完后再让他回1。
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
-
- public class HPControl : MonoBehaviour
- {
- public float delHpSpeed = 1;//延迟血条减少速度
- public float delHpTime = 1;//延时血条减少时间间隔
- public float AlpHpTime = 1;//延时血条变淡速度
- private CharacterPanel character ;//角色面板
- private Transform hpBox;//血条图片
- private Transform delhpBox;//延迟血条图片
- private float delHPtime = 1;
-
- // Start is called before the first frame update
- void Start()
- {
- character = transform.GetComponentInParent<CharacterPanel>();
- hpBox = transform.GetChild(1);//0-HPmaxBox 1-hpBox 2-delhpBox
- delhpBox = transform.GetChild(2);
- }
-
- // Update is called once per frame
- void FixedUpdate()
- {
- check();
-
- }
- //检查血量变化控制血条
- private void check() {
-
- float x = character.Hp / character.Hpmax;
- hpBox.localScale = new Vector3(x, 1, 1);
- if (delhpBox.localScale.x > x)
- {//血条显示
- for (int i = 0; i < transform.childCount; i++)
- {
- transform.GetChild(i).GetComponent<SpriteRenderer>().color = new Color(transform.GetChild(i).GetComponent<SpriteRenderer>().color.r, transform.GetChild(i).GetComponent<SpriteRenderer>().color.g, transform.GetChild(i).GetComponent<SpriteRenderer>().color.b, 1);
-
- }
- }
- if ((delhpBox.localScale.x > x)&& delHPtime == 1)//延迟血条与血条有数差
- {
-
- //延迟血条开启协程
- StartCoroutine(delHP(x));
- delHPtime = 0;
-
- }
-
- }
- IEnumerator delHP(float x)
- {
- yield return new WaitForSeconds(0.7f);//起初停顿时间
-
- while (delhpBox.localScale.x >= x)//直到延迟血条完成
- {
-
- yield return new WaitForSeconds(0.005f* delHpTime);//间隔0.005*delHpTime秒
- delhpBox.localScale =new Vector3(delhpBox.localScale.x-0.001f* delHpSpeed, 1, 1);
- }
- delHPtime = 1;
-
- }
-
- }
协程有俩个作用,
一个是延时既有帧延时(yield return 数字/null(延时一帧) )也有时间延时,例如上面的
yield return new WaitForSeconds(0.7f);//起初停顿时间
第二个是暂停分帧/分时执行函数,使得函数不在一帧中瞬间执行完。将yield return 放在for或者while循环中,例如上面的
while (delhpBox.localScale.x >= x)//直到延迟血条完成
{yield return new WaitForSeconds(0.005f* delHpTime);//间隔0.005*delHpTime秒
delhpBox.localScale =new Vector3(delhpBox.localScale.x-0.001f* delHpSpeed, 1, 1);
}
下一篇
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。