using System.Collections; using System.Collections.Generic; using UnityEngine; using DG.Tweening; using Sirenix.OdinInspector; /// /// 普通怪物类,三关都有的那个 /// public class NormalEnemy : Enemy { // _____ _ _ _ // | __ \ | | | (_) // | |__) | _| |__ | |_ ___ // | ___/ | | | '_ \| | |/ __| // | | | |_| | |_) | | | (__ // |_| \__,_|_.__/|_|_|\___| [Header("被攻击后击飞的力度调整值")][FoldoutGroup("其他",false,0)] public Vector2 hitToflyParameter; [FoldoutGroup("其他",false,0)][Header("怪物死后旋转速度的随机区间")] public float deadRotationRangeMax; [FoldoutGroup("其他",false,0)] public float deadRotationRangeMin; // _____ _ _ // | __ \ (_) | | // | |__) | __ ___ ____ _| |_ ___ // | ___/ '__| \ \ / / _` | __/ _ \ // | | | | | |\ V / (_| | || __/ // |_| |_| |_| \_/ \__,_|\__\___| protected Rigidbody2D m_rigidbody; /// /// 死的时候的受击朝向 /// protected int deadDir; /// /// 记录一下游戏开始时怪物的位置,方便被击飞后怪物重新回到巡逻起点 /// protected Vector3 sourcePosition; protected DOTweenPath doTweenPath; [SerializeField][ReadOnly][FoldoutGroup("状态")] protected bool inPath = true; /// /// 现在正在执行的动画,在受击中断的时候用 /// protected Tween tweenNow; // _____ _ _ ____ _ // / ____| | | | _ \ | | // | | __ _| | | |_) | __ _ ___| | __ // | | / _` | | | _ < / _` |/ __| |/ / // | |___| (_| | | | |_) | (_| | (__| < // \_____\__,_|_|_|____/ \__,_|\___|_|\_\ void Start(){Init();} // _ _ _ // | \ | | | | // | \| | ___ _ __ _ __ ___ __ _| | // | . ` |/ _ \| '__| '_ ` _ \ / _` | | // | |\ | (_) | | | | | | | | (_| | | // |_| \_|\___/|_| |_| |_| |_|\__,_|_| protected virtual void Init(){ //生命值初始化为满 HPLeft = HP; //Get插件 doTweenPath = GetComponent(); m_rigidbody = GetComponent(); sourcePosition = transform.position; //初始话目前播放的Tween动画为巡逻 tweenNow = doTweenPath.tween; } /// /// 协程用,删除自己这个游戏物体 /// protected void Dead(){Destroy(gameObject);} /// /// 被击飞的击飞效果处理 /// /// 被击方向 public void BeHitToFly(int dir){ m_rigidbody.velocity += new Vector2( //给予自身一个 -1 * dir * hitToflyParameter.x,//X方向为力度系数乘以受击方向 hitToflyParameter.y//Y方向为力度系数 //的绝对的速度 ); } // ______ _ // | ____| | | // | |____ _____ _ __ | |_ // | __\ \ / / _ \ '_ \| __| // | |___\ V / __/ | | | |_ // |______\_/ \___|_| |_|\__| protected override void OnTouchThePlayer(MyPlayer player){ //告诉玩家,你被攻击了 player.OnBeHit(ATK, ((transform.position.x - player.transform.position.x) > 0) ? 1 : -1);//通过自身位置和玩家位置的比较来返回玩家本次的受击方向 } public override void OnBeHit(MyPlayer.AtkMethod hitMethod, int hitDir){ //结束当前动画 tweenNow.Pause(); //让自己被击飞 BeHitToFly(hitDir); //修改标志表示自己当前不在Path中 inPath = false; //结算生命值 HPLeft -= MyPlayer.atkMethodMagnification[hitMethod]; //看下死了没 //死了就记录下死亡时候的面部朝向,用来做死亡翻滚效果,然后再Call一下死亡事件 if(CheckDead()) {deadDir = hitDir;OnDead();} //被打飞了在着地前都不会挨打了 canBeHit = false; } protected override void OnRetouchedTheGround(){ if(!inPath){//如果此时怪物没在巡逻且着地了,说明时被击飞然后着地了 //新建一个动画,让怪物回到初始记录位置 Tween tween = transform.DOMove(sourcePosition, Mathf.Abs(sourcePosition.x - transform.position.x) / speed, false); //设置该动画插值方式为线性 tween.SetEase(Ease.Linear); //更改记录的此时正在执行的动画 tweenNow = tween; //写一个委托,插入这个新动画的结束事件 TweenCallback myCallBack = () => //结束说明回到了初始点,此时让怪物重新开始巡逻,同时更改记录中的正在执行的动画为巡逻 {doTweenPath.DORestart(); tweenNow = doTweenPath.tween;}; //插入写的委托 tween.OnComplete(myCallBack); //标记自身重新回到巡逻动画 inPath = true; //矫正一下faceDir的问题 transform.rotation = Quaternion. Euler (transform.rotation.x, ((sourcePosition.x - transform.position.x > 0) ? 0:-180), transform.rotation.z); } canBeHit = true; } protected override void OnDead() { //标记当前状态为死亡 state = State.dead; //加一个扭矩,营造死亡的效果 m_rigidbody.AddTorque(Random.Range(deadRotationRangeMin,deadRotationRangeMax) * deadDir); //关掉自己的碰撞体 GetComponent().enabled = false; //两秒后自己毁灭 Invoke("Dead",2f); } }