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; // _____ _ _ // | __ \ (_) | | // | |__) | __ ___ ____ _| |_ ___ // | ___/ '__| \ \ / / _` | __/ _ \ // | | | | | |\ V / (_| | || __/ // |_| |_| |_| \_/ \__,_|\__\___| /// /// 返回类型为协程、参数为空的委托类型 /// private delegate IEnumerator Action(); /// /// 开关,控制此时木马是否在移动 /// [SerializeField][Header("此时木马是否在移动")][FoldoutGroup("状态")][ReadOnly] private 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(){ //找到必须的组件和物体 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(){ 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; //等待喷射炸弹时间间隔 yield return new WaitForSeconds(sprayBoomerTime); } 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 / __/ | | | |_ // |______\_/ \___|_| |_|\__| /// /// 当玩家进入监视范围(前期调试,后期可能需要安排演出) /// /// protected override void OnFindThePlayer(Transform target){ if(state == State.wander){ //修改状态为发现玩家 state = State.atk; //开始攻击 StartCoroutine(StartAATK()); //开始屏幕震动 FindObjectOfType().HorseShake(); //开始向右移动 isMove = true; } } /// /// 攻击结束的时候触发,重新开始新一轮攻击 /// public void ATKEnd(){StartCoroutine(StartAATK());} protected override void OnTouchThePlayer(MyPlayer player){ //当创到玩家,让玩家受伤 //告诉玩家,你被攻击了 player.OnBeHit(ATK, ((transform.position.x - player.transform.position.x) > 0) ? 1 : -1);//通过自身位置和玩家位置的比较来返回玩家本次的受击方向 } // _____ _ __ // |_ _| | | / _| // | | _ __ | |_ ___ _ __| |_ __ _ ___ ___ // | | | '_ \| __/ _ \ '__| _/ _` |/ __/ _ \ // _| |_| | | | || __/ | | || (_| | (_| __/ // |_____|_| |_|\__\___|_| |_| \__,_|\___\___| public void BeBoomed(float atk, int dir, Boomer boomer){ if(boomer.isThisCanBeReturned){ OnBeHit(MyPlayer.AtkMethod.反弹炸弹,dir); wasInterupt = true; } } public Transform ObjTransform(){return transform;} }