using System.Collections; using System.Collections.Generic; using UnityEngine; using DG.Tweening; using Sirenix.OdinInspector; /// /// 撞钟类,控制地藏头上的钟 /// public class Bell : MonoBehaviour { // _____ _ _ _ // | __ \ | | | (_) // | |__) | _| |__ | |_ ___ // | ___/ | | | '_ \| | |/ __| // | | | |_| | |_) | | | (__ // |_| \__,_|_.__/|_|_|\___| /// /// 攻击前置动作钟上浮多少距离 /// [Header("攻击前置动作钟上浮多少距离")] public float upDistance; /// /// 攻击将会持续多长时间 /// [Header("攻击将会持续多长时间")] public float atkTime; /// /// 主人,也就是地藏Boss /// [HideInInspector] public DiZang owner; /// /// 钟飞上去将要花费多少时间(降下来也是这个值) /// [Header("钟飞上去将要花费多少时间(降下来也是这个值)")] public float upTime; /// /// 干扰多长时间能造成伤害和击飞? /// [Header("干扰多长时间能造成伤害和击飞?")] public float annoyingToHitTime; [Header("声波Shader")] public BellShader bellShader; [Header("声波受击粒子")] public GameObject particleObj; // _____ _ _ // | __ \ (_) | | // | |__) | __ ___ ____ _| |_ ___ // | ___/ '__| \ \ / / _` | __/ _ \ // | | | | | |\ V / (_| | || __/ // |_| |_| |_| \_/ \__,_|\__\___| /// /// 当前正在攻击吗 /// [SerializeField][Button][ReadOnly][Header("当前正在攻击吗(不包括钟上下过程))")] private bool isAtking = false; private MyPlayer player; /// /// 浮动动画,用来重启浮动动画解决Tween的一些局限性问题 /// public Tweener floatTweener; private float annoyingToHitTimeLeft; /// /// 此时是否在干扰玩家 /// [SerializeField] private bool isAnnoyingPlayer; /// /// 钟的初始位置 /// private Vector3 startPositon; // _____ _ _ ____ _ // / ____| | | | _ \ | | // | | __ _| | | |_) | __ _ ___| | __ // | | / _` | | | _ < / _` |/ __| |/ / // | |___| (_| | | | |_) | (_| | (__| < // \_____\__,_|_|_|____/ \__,_|\___|_|\_\ void Start(){ annoyingToHitTimeLeft = annoyingToHitTime; startPositon = transform.position; //启动浮动动画 RestartFloat(); } void Update(){ //如果钟正在攻击 if(isAtking) { bellShader.isBell = true; particleObj.SetActive(true); if(!player.isAnnoying){ player.OnInAnnoying(); } //创建一条从钟射向玩家的射线 Ray2D ray = new Ray2D( (Vector2)transform.position, (Vector2)(player.transform.position - transform.position) ); Debug.DrawRay(ray.origin,ray.direction * 1500,Color.red); //获取射线的碰撞结果 RaycastHit2D hit2D; hit2D = Physics2D.Raycast(ray.origin,ray.direction); if(hit2D){ Debug.Log(hit2D.collider.name); } //如果射线击中玩家并且玩家未处于被攻击状态,说明刚被击中,触发玩家的被干扰事件 if(hit2D.collider.TryGetComponent(out MyPlayer trash) ){ // player.OnInAnnoying(); isAnnoyingPlayer = true; } //如果没有击中玩家,但是玩家处于被攻击状态,说明玩家脱离了攻击,触发玩家解除干扰事件 else if(!hit2D.collider.TryGetComponent(out MyPlayer trash1)){ //player.OnOutAnnoying(); isAnnoyingPlayer = false; annoyingToHitTimeLeft = annoyingToHitTime; } } if(isAnnoyingPlayer){ annoyingToHitTimeLeft -= Time.deltaTime; if(annoyingToHitTimeLeft <= 0){ //告诉玩家,你被攻击了 player.OnBeHit(owner.ATK, ((transform.position.x - player.transform.position.x) > 0) ? 1 : -1);//通过自身位置和玩家位置的比较来返回玩家本次的受击方向 //恢复CD annoyingToHitTimeLeft = annoyingToHitTime; } } } // _ _ _ // | \ | | | | // | \| | ___ _ __ _ __ ___ __ _| | // | . ` |/ _ \| '__| '_ ` _ \ / _` | | // | |\ | (_) | | | | | | | | (_| | | // |_| \_|\___/|_| |_| |_| |_|\__,_|_| /// /// 介于Tweener的特性,经常需要重新创建钟浮动的动画 /// private void RestartFloat(){ if(floatTweener != null){ floatTweener.Kill(); } Tweener tweener = transform.DOShakePosition(5f,0.3f,1,90,false,false); tweener.SetLoops(-1); tweener.SetEase(Ease.InQuad); floatTweener = tweener; } // ______ _ // | ____| | | // | |____ _____ _ __ | |_ // | __\ \ / / _ \ '_ \| __| // | |___\ V / __/ | | | |_ // |______\_/ \___|_| |_|\__| /// /// 从主人那里得到攻击指令后触发 /// public void ATK(MyPlayer player){ //指定一下攻击目标 this.player = player; //创建和执行上浮动画 Tweener tweener = transform.DOLocalMoveY( transform.position.y + upDistance, upTime ); //创建并加入上浮动画结束事件 TweenCallback action = () => { //标记自己开始攻击 isAtking = true; //重启浮动动画 RestartFloat(); //等待攻击结束 StartCoroutine(WaitAndTurnDownThebutton()); }; tweener.OnComplete(action); } /// /// 上浮动画结束的时候触发 /// /// private IEnumerator WaitAndTurnDownThebutton(){ //等待攻击时长结束 yield return new WaitForSeconds(atkTime); //标记攻击结束 isAtking = false; //触发自身攻击结束功能 ATKEnd(); } /// /// 攻击结束的时候触发 /// private void ATKEnd() { bellShader.isBell = false; bellShader.Remake = true; particleObj.SetActive(false); //如果玩家仍处于被干扰状态,解除干扰 if(player.isAnnoying) player.OnOutAnnoying(); annoyingToHitTimeLeft = annoyingToHitTime; isAnnoyingPlayer = false; //创建动画让钟回去 Tweener tweener = //transform.DOMoveY(transform.position.y - upDistance,upTime); transform.DOMove(startPositon,upTime); //创建和添加结束事件 TweenCallback action = () => { //重启浮动动画 RestartFloat(); //告诉主人,攻击结束,开始下一个轮回 owner.ATKEnd(); }; tweener.OnComplete(action); } }