using System.Collections; using System.Collections.Generic; using UnityEngine; using Sirenix.OdinInspector; using DG.Tweening; /// /// 木马类 /// public class TrojanHorse : Enemy, Boomer.I_CanBeBoomedObj { // _____ _ _ _ // | __ \ | | | (_) // | |__) | _| |__ | |_ ___ // | ___/ | | | '_ \| | |/ __| // | | | |_| | |_) | | | (__ // |_| \__,_|_.__/|_|_|\___| /// /// 攻击之间的间隔时间 /// [Header("攻击之间的间隔时间")][FoldoutGroup("木马")] public float timeBetweenAttacks; /// /// 伊斯兰小怪的预制体 /// [Header("伊斯兰小怪的预制体")][FoldoutGroup("预制体")] public GameObject yiSiLan; /// /// 召唤小怪攻击中,生成小怪之间间隔的最短时间 /// [Header("召唤小怪攻击中,生成小怪之间间隔的最短时间")][FoldoutGroup("木马")] public float yiSiLanMinTime; // /// 召唤小怪攻击中,生成小怪之间间隔的最长时间 /// [Header("召唤小怪攻击中,生成小怪之间间隔的最长时间")][FoldoutGroup("木马")] public float yiSiLanMaxTime; /// /// 炸弹的预制体,用来喷射的那种 /// [Header("炸弹的预制体,用来喷射的那种")][FoldoutGroup("预制体")] public GameObject sprayBoomer; /// /// 喷射炸弹的时间间隔 /// [Header("喷射炸弹的时间间隔")][FoldoutGroup("木马")] public float sprayBoomerTime; /// /// 喷射炸弹的方向 /// [Header("喷射炸弹的方向")][FoldoutGroup("木马")] public Vector2 sprayBoomerDir; /// /// 喷射炸弹的力度倍数 /// [Header("喷射炸弹的力度倍数")][FoldoutGroup("木马")] public float sprayBoomerMultiple; /// /// 召唤炸弹攻击,炸弹从天而降的初速度 /// [Header("召唤炸弹攻击,炸弹从天而降的初速度")][FoldoutGroup("木马")] public Vector2 callBoomStartVelocity; [Header("召唤炸弹攻击,炸弹从天而降的初速度")] [FoldoutGroup("木马")] public List trojanHorseParticleSystems; // _____ _ _ // | __ \ (_) | | // | |__) | __ ___ ____ _| |_ ___ // | ___/ '__| \ \ / / _` | __/ _ \ // | | | | | |\ V / (_| | || __/ // |_| |_| |_| \_/ \__,_|\__\___| /// /// 返回类型为协程、参数为空的委托类型 /// private delegate IEnumerator Action(); /// /// 开关,控制此时木马是否在移动 /// [SerializeField][Header("此时木马是否在移动")][FoldoutGroup("状态")][ReadOnly] public bool isMove = false; /// /// 召唤伊斯兰小怪的初始位置 /// private Transform callYiSiLanPosition; /// /// 喷射炸弹的起点 /// private Transform sprayBoomerPosition; /// /// 召唤炸弹攻击的最左边 /// private Transform callBoomerPositonLeft; /// /// 召唤炸弹攻击的最右边 /// private Transform callBoomerPositonRight; /// /// 此时是否被打断?主要用来停止喷射攻击 /// [Header("此时是否被打断")][SerializeField][FoldoutGroup("状态")][ReadOnly] private bool wasInterupt = false; // _____ _ _ ____ _ // / ____| | | | _ \ | | // | | __ _| | | |_) | __ _ ___| | __ // | | / _` | | | _ < / _` |/ __| |/ / // | |___| (_| | | | |_) | (_| | (__| < // \_____\__,_|_|_|____/ \__,_|\___|_|\_\ void Start(){Init();} void Update(){ //如果开关开着,则移动 if(isMove) Move(); } // _ _ _ // | \ | | | | // | \| | ___ _ __ _ __ ___ __ _| | // | . ` |/ _ \| '__| '_ ` _ \ / _` | | // | |\ | (_) | | | | | | | | (_| | | // |_| \_|\___/|_| |_| |_| |_|\__,_|_| private void Init(){ //开启粒子 for (int i = 0; i < trojanHorseParticleSystems.Count; i++) { trojanHorseParticleSystems[i].Play(); } //初始化生命值 HPLeft = HP; //找到必须的组件和物体 callYiSiLanPosition = transform.Find("小怪召唤点"); sprayBoomerPosition = transform.Find("喷射炸弹点"); callBoomerPositonLeft = transform.Find("召唤炸弹攻击最左点"); callBoomerPositonRight = transform.Find("召唤炸弹攻击最右点"); } /// /// 执行一次攻击 /// private IEnumerator StartAATK(){ //等待攻击间隔 yield return new WaitForSeconds(timeBetweenAttacks); //决定行动 Action action = DecideAAction(); //开始行动 StartCoroutine(action()); } /// /// 决定行动的函数 /// private Action DecideAAction(){ Action action; ///从0、1、2中随机生成一种 int r = Random.Range(0,3); if(r == 0) action = CallYiSiLan; else if(r == 1) action = SprayBoomer; else action = CallBoomer; return SprayBoomer; } /// /// 攻击方式:召唤小怪 /// private IEnumerator CallYiSiLan(){ Debug.Log("正在使用:召唤伊斯兰"); //循环若干次(这里先硬编码成3次) for(int i = 0; i < 3; i++){ //实例化预制体 YiSiLan yi = Instantiate( yiSiLan, callYiSiLanPosition.position, Quaternion.identity ).GetComponent(); //等待范围内的随机时间 yield return new WaitForSeconds( Random.Range(yiSiLanMinTime,yiSiLanMaxTime) ); } ATKEnd(); } /// /// 攻击方式:喷射炸弹💣 /// /// private IEnumerator SprayBoomer(){ //开始喷射动画 GetComponent().SetBool("isSpray",true); yield return new WaitForSeconds(1f); Debug.Log("正在使用:喷射炸弹"); //循环若干次(这里先硬编码成3次) for(int i = 0; i < 3; i++){ if(wasInterupt) break; //实例化预制体 Boomer boomer = Instantiate( sprayBoomer, sprayBoomerPosition.position, Quaternion.identity ).GetComponent(); //初始化喷出的炸弹 //给予初始的速度 yield return new WaitForEndOfFrame(); boomer.m_rigidbody.velocity = sprayBoomerDir * (i + 1) * sprayBoomerMultiple; boomer.isThisCanBeReturned = true; boomer.GetComponent().Play(); //给予炸弹扭矩 boomer.m_rigidbody.angularVelocity = 500f; //等待喷射炸弹时间间隔 yield return new WaitForSeconds(sprayBoomerTime); } //结束喷射动画 yield return new WaitForSeconds(2f); GetComponent().SetBool("isSpray",false); wasInterupt = false; ATKEnd(); } /// /// 攻击方式:召唤炸弹💣 /// /// private IEnumerator CallBoomer(){ Debug.Log("正在使用:召唤炸弹"); //循环若干次(这里先硬编码成3次) for(int i = 0; i < 3; i++){ //实例化预制体 Boomer boomer = Instantiate( sprayBoomer, new Vector3( //x取余范围内随机 Random.Range(callBoomerPositonLeft.position.x, callBoomerPositonRight.position.x), //yz随起点 callBoomerPositonLeft.position.y, callBoomerPositonLeft.position.z ), Quaternion.identity ).GetComponent(); //初始化喷出的炸弹 //先等待本帧结束,创建炸弹完毕 yield return new WaitForEndOfFrame(); //给予初始的速度 boomer.m_rigidbody.velocity = callBoomStartVelocity; //修改炸弹的落地爆炸时间 boomer.landBoomTime = 1f; //等待喷射炸弹时间间隔 yield return new WaitForSeconds(sprayBoomerTime); } ATKEnd(); } /// /// 木马不停右移的函数,每帧调用一次,有开关控制 /// private void Move(){ //给自身位置加上向右的速度 transform.position += new Vector3( speed * Time.deltaTime,0,0 ); } // ______ _ // | ____| | | // | |____ _____ _ __ | |_ // | __\ \ / / _ \ '_ \| __| // | |___\ V / __/ | | | |_ // |______\_/ \___|_| |_|\__| /// /// 当玩家进入监视范围(前期调试,后期可能需要安排演出) /// /// public override void OnFindThePlayer(Transform target){ if(state == State.wander){ //修改状态为发现玩家 state = State.atk; //开始攻击 StartCoroutine(StartAATK()); //开始屏幕震动 FindObjectOfType().HorseShakeScream(); //开始向右移动 isMove = true; } } /// /// 攻击结束的时候触发,重新开始新一轮攻击 /// public void ATKEnd(){ if(state == State.atk) StartCoroutine(StartAATK()); } protected override void OnTouchThePlayer(MyPlayer player){ // Debug.Log("创到玩家了"); // //当创到玩家,让玩家受伤 //告诉玩家,你被攻击了 player.OnBeHit(ATK, ((transform.position.x - player.transform.position.x) > 0) ? 1 : -1);//通过自身位置和玩家位置的比较来返回玩家本次的受击方向 } public override void OnDead(){ //修改粒子透明度 for (int i = 0; i < trojanHorseParticleSystems.Count; i++) { StartCoroutine(SetParticleColor(trojanHorseParticleSystems[i], 0, 1f)); } //播放死亡动画 GetComponent().SetBool("isDead",true); Debug.Log("啊我死了"); isMove = false; state = State.dead; FindObjectOfType().inHorseStage = false; FindObjectOfType().StopHorseShakeScream(); FindObjectOfType().GetComponent().enabled = true; //上传玩家进度 FindObjectOfType().rate = (int) MyPlayer.Progress.过伊; FindObjectOfType().UpdatePlayerInfo(); } public override void OnBeHit(MyPlayer.AtkMethod hitMethod,int hitDir){ //结算生命值 HPLeft -= MyPlayer.atkMethodMagnification[hitMethod]; } // _____ _ __ // |_ _| | | / _| // | | _ __ | |_ ___ _ __| |_ __ _ ___ ___ // | | | '_ \| __/ _ \ '__| _/ _` |/ __/ _ \ // _| |_| | | | || __/ | | || (_| | (_| __/ // |_____|_| |_|\__\___|_| |_| \__,_|\___\___| public void BeBoomed(float atk, int dir, Boomer boomer){ if(boomer.isThisCanBeReturned){ OnBeHit(MyPlayer.AtkMethod.反弹炸弹,dir); wasInterupt = true; if(CheckDead()) OnDead(); } } public Transform ObjTransform(){return transform;} //修改粒子,使粒子淡出 private IEnumerator SetParticleColor(ParticleSystem particleSystem,float endValue,float speed) { Color color = particleSystem.main.startColor.color; while (particleSystem.main.startColor.color.a>endValue) { yield return new WaitForSeconds(0.15f); color.a -= 0.1f; //解决warming #pragma warning disable 0618 particleSystem.startColor = color; } } }