using Spine.Unity; using Spine; using System.Collections; using System.Collections.Generic; using UnityEngine; using Base.Common; using UnityEditor.SceneManagement; public enum TargetType { None = 0, Demonic = 1, Tower = 2, Player = 3, Enemy = 4, EnemyTower = 5, Boss = 6, Portal = 7, } public enum SearchState { NoTarget = 0, //搜索范围内没有目标 InSearchScope = 1, //在搜索范围内发现目标,但不在攻击范围内 InAttackScope = 2, //目标在攻击范围内 } public class Enemy : MoveCharacter { [Header("敌方单位属性")] public int id; public int baseSortingOrder; int sortingOrder = 0; public bool isBack = false; //往反方向走 public float flyHeight; public float flyUpSpeed = 10; public float jumpSpeed = 10; public float maxMoveSpeed, minMoveSpeed; public float runSpeed; [Header("击飞、屏幕反弹")] public bool isBeBlownUp; //被击飞 public bool isBeReboundedX; //X方向被反弹 public bool isBeReboundedY; //Y方向被反弹 private bool hasBeReboundedX; private bool hasBeReboundedY; public float reboundXSpeed; public float reboundYSpeed; public int wallDamage; [Header("落地眩晕")] public bool willBeComa; public float willComaTime; public int comaDamage; [Header("敌方英灵")] public Spirits.SpiritType type; [Header("敌方单位组件")] public SearchState searchState; [Header("攻击")] public float attackDistance; public float maxAttackDis, minAttackDis; public bool needToChange; public float attackRatio; [Header("掉落魂")] public int dropSoulMax = 3; public int dropSoulMin = 1; public float dropSoulAngle = 60f; [Header("冲刺攻击")] public GameObject aimEffect; public DashEffect dashEffect; [HideInInspector] public bool noOnSearchState; [HideInInspector] public bool isFindingPlayer; [HideInInspector] public bool isFindPlayer; public float hateDistance; [HideInInspector] public float distance; [HideInInspector] public Vector3 rushEndPos; public float aimDistance; public float rushTime; public float rushSpeed; [HideInInspector] public float time; public float readyCD; [HideInInspector] public Vector3 targetDir; public bool haveDownRush; //冲刺结束后是否可以接落地斩 public bool rushHaveAttack; //冲刺是否带伤害 public float downRushTime; public float finishRushTime; [Header("验证功能开关")] public bool upFirstAfterWeaknessOrNot; //虚弱结束后是否先升高 private void Awake() { aimDistance = rushTime * rushSpeed / 2; } private void Start() { if (needToChange) { attackDistance = Random.Range(minAttackDis, maxAttackDis); } } private void OnEnable() { Init(); } public void OnDisable() { EnemyCreater.instance.OnEnemyRecycle(this); } public override void Init() { base.Init(); moveSpeed = Random.Range(minMoveSpeed, maxMoveSpeed); ChangeSearchState(SearchState.NoTarget); } public override void FixedUpdate() { if (!noOnSearchState) { OnSearchState(); } OnState(); } public override Vector3 GetMoveDir() { Vector3 moveDir = Vector3.zero; if (canMove) { switch (searchState) { case SearchState.NoTarget: if (TowerMap.myTowers.Count == 0) { moveDir = Vector3.right; break; } float minDistance = Mathf.Infinity; int id = -1; for (int i = 0; i < TowerMap.myTowers.Count; i++) { Tower myTower = TowerMap.myTowers[i].GetComponent(); if (transform.position.y > myTower.transform.position.y + myTower.height) { continue; } float distance = Vector3.Distance(transform.position, TowerMap.myTowers[i].transform.position); if (distance < minDistance) { minDistance = distance; id = i; } } if (id == -1) { moveDir = Vector3.right; break; } if (bodyTrans.position.x > TowerMap.myTowers[id].transform.position.x) { moveDir = Vector3.left; } else { moveDir = Vector3.right; } break; case SearchState.InSearchScope: if (targetCharacter) { if (targetCharacter.transform.position.x - transform.position.x < 0) { moveDir = Vector3.left; } else { moveDir = Vector3.right; } } else { moveDir = Vector3.zero; } break; case SearchState.InAttackScope: if (targetCharacter) { if (targetCharacter.transform.position.x - transform.position.x < 0) { moveDir = Vector3.left; } else { moveDir = Vector3.right; } } else { moveDir = Vector3.zero; } break; default: break; } } if (!isBack) { return moveDir; } return -moveDir; } public bool GetAttack() { if (searchState == SearchState.InAttackScope) { return true; } return false; } public bool GetJump() { return false; } public bool AdjustHeight() { if (canFly) { if (transform.position.y - flyHeight > 0.1f) { Vector3 pos = transform.position; pos.y -= flyUpSpeed * Time.deltaTime; transform.position = pos; return false; } else if (transform.position.y - flyHeight < -0.1f) { Vector3 pos = transform.position; pos.y += flyUpSpeed * Time.deltaTime; transform.position = pos; return false; } } return true; } public override void OnState() { base.OnState(); //hurtKeepTime -= Time.deltaTime; dieKeepTime -= Time.deltaTime; invincibleTime -= Time.deltaTime; weakTime -= Time.deltaTime; beRepelValue += Time.deltaTime; Vector3 leftDir = GetMoveDir(); bool isAttack = GetAttack(); switch (state) { case CharacterState.Idle: if (isAttack) { Attack_march(); break; } if (!foot.TrigGround && !canFly) { if (rb.velocity.y > 0) { ChangeState(CharacterState.Rise); break; } else { ChangeState(CharacterState.Fall); break; } } if (leftDir.x > 0.3f || leftDir.x < -0.3f) { ChangeState(CharacterState.Run); break; } //rb.velocity = Vector3.zero; if (!upFirstAfterWeaknessOrNot) { if (canFly) { rb.constraints = RigidbodyConstraints.FreezeRotation | RigidbodyConstraints.FreezePositionZ | RigidbodyConstraints.FreezePositionY; rb.useGravity = false; AdjustHeight(); } } break; case CharacterState.Run: if (isAttack) { Attack_march(); break; } if (!foot.TrigGround && !canFly) { if (rb.velocity.y > 0) { ChangeState(CharacterState.Rise); break; } else { ChangeState(CharacterState.Fall); break; } } if (leftDir.x < 0.3f && leftDir.x > -0.3f) { ChangeState(CharacterState.Idle); break; } if (leftDir.x > 0.3f) { rb.velocity = Vector3.right * moveSpeed; if (bodyTrans.localScale.x > 0) { Turn(); } } else if (leftDir.x < -0.3f) { rb.velocity = Vector3.left * moveSpeed; if (bodyTrans.localScale.x < 0) { Turn(); } } if (!upFirstAfterWeaknessOrNot) { if (canFly) { rb.constraints = RigidbodyConstraints.FreezeRotation | RigidbodyConstraints.FreezePositionZ | RigidbodyConstraints.FreezePositionY; rb.useGravity = false; AdjustHeight(); } } break; case CharacterState.Rush: if (isAttack) { Attack_march(); break; } if (!foot.TrigGround && !canFly) { if (rb.velocity.y > 0) { ChangeState(CharacterState.Rise); break; } else { ChangeState(CharacterState.Fall); break; } } if (leftDir.x < 0.3f && leftDir.x > -0.3f) { ChangeState(CharacterState.Idle); break; } if (leftDir.x > 0.3f) { //rb.velocity += Vector3.right * moveAcc * Time.deltaTime; rb.velocity = Vector3.right * runSpeed; //if (rb.velocity.x > maxMoveSpeed) //{ // rb.velocity = new Vector3(maxMoveSpeed, rb.velocity.y, rb.velocity.z); //} if (bodyTrans.localScale.x > 0) { Turn(); } } else if (leftDir.x < -0.3f) { //rb.velocity -= Vector3.right * moveAcc * Time.deltaTime; rb.velocity = Vector3.left * runSpeed; //if (rb.velocity.x < -maxMoveSpeed) //{ // rb.velocity = new Vector3(-maxMoveSpeed, rb.velocity.y, rb.velocity.z); //} if (bodyTrans.localScale.x < 0) { Turn(); } } //AdjustHeight(); break; case CharacterState.Rise: if (rb.velocity.y <= 0) { ChangeState(CharacterState.Fall); break; } rb.velocity += Vector3.up * extraRiseGravity * Time.deltaTime; break; case CharacterState.Fall: if (foot.TrigGround || canFly) { if (isFindingPlayer) { ChangeState(CharacterState.FindPlayer); } else if (willBeComa) { comaTime = willComaTime; ChangeState(CharacterState.Coma); } else { ChangeState(CharacterState.Idle); } break; } Vector3 velocity = rb.velocity; velocity.y += extraFallGravity * Time.deltaTime; if (leftDir.x > 0.3f) { velocity.x = moveSpeed; if (bodyTrans.localScale.x > 0) { Turn(); } } else if (leftDir.x < -0.3f) { velocity.x = -moveSpeed; if (bodyTrans.localScale.x < 0) { Turn(); } } rb.velocity = velocity; break; case CharacterState.Attack: attackTime -= Time.deltaTime; attackKeyCount += Time.deltaTime; if (!isAttackTriggerOn && attackKeyCount >= nextStartKeyTime && attackKeyCount <= nextEndKeyTime) { isAttackTriggerOn = true; foreach (AttackTrigger at in attackTriggers) { at.gameObject.SetActive(true); } } else if (isAttackTriggerOn && attackKeyCount >= nextEndKeyTime) { isAttackTriggerOn = false; foreach (AttackTrigger at in attackTriggers) { at.gameObject.SetActive(false); } SetNextKeyTimes(); } if (attackTime <= 0) { ChangeState(CharacterState.Idle); break; } break; case CharacterState.Die: if (dieKeepTime <= 0) { gameObject.SetActive(false); break; } break; case CharacterState.Weak: if (rb.velocity.magnitude > 1) { if (!isBeBlownUp) { isBeBlownUp = true; ani.Play("hitted", 0, 0); } Vector3 vel = rb.velocity; if (foot.TrigGround && vel.y <= 0) { vel = Vector3.zero; } else { if (!hasBeReboundedX) { vel.x -= vel.x * decelerationRatio * Time.deltaTime; if (!hasBeReboundedX && isBeReboundedX) { hasBeReboundedX = true; vel.x = 0; } } if (!hasBeReboundedY) { vel.y += extraFallGravity * Time.deltaTime; if (!hasBeReboundedY && isBeReboundedY) { hasBeReboundedY = true; vel.y = 0; } } } //vel.y = vel.y * (1 - decelerationRatio * Time.deltaTime); //vel.x = vel.x * (1 - decelerationRatio * Time.deltaTime); rb.velocity = vel; } else { if (isBeBlownUp) { isBeBlownUp = false; isBeReboundedX = false; isBeReboundedY = false; hasBeReboundedX = false; hasBeReboundedY = false; } if (weakTime <= -0.1) { if (upFirstAfterWeaknessOrNot) { if (canFly) { rb.constraints = RigidbodyConstraints.FreezeRotation | RigidbodyConstraints.FreezePositionZ | RigidbodyConstraints.FreezePositionY; rb.useGravity = false; } if (AdjustHeight()) { ChangeState(CharacterState.Idle); } else { if (ani.GetCurrentAnimatorClipInfo(0)[0].clip.name != "walk") { ani.Play("walk", 0, 0); } } } else { ChangeState(CharacterState.Idle); } break; } else { if (ani.GetCurrentAnimatorClipInfo(0)[0].clip.name != "weak") { ani.Play("weak", 0, 0); rb.velocity = Vector3.zero; } } } break; case CharacterState.Coma: pastComaTime += Time.deltaTime; if (pastComaTime >= comaTime) { ChangeState(CharacterState.Idle); } break; case CharacterState.FindPlayer: if (!isFindPlayer) { if (!foot.TrigGround && !canFly) { if (rb.velocity.y > 0) { ChangeState(CharacterState.Rise); break; } else { ChangeState(CharacterState.Fall); break; } } if (targetCharacter == null) { ChosePlayer(); if (targetCharacter == null) { ChangeState(CharacterState.FinishRush); time = finishRushTime; break; } } else { if (targetCharacter.isRevive || targetCharacter.GetComponent().isBaseBtnOut) { targetCharacter = null; break; } } if (Mathf.Abs(transform.position.x - targetCharacter.transform.position.x) < hateDistance) { rushEndPos = targetCharacter.transform.position; isFindPlayer = true; break; } if (targetCharacter.transform.position.x > transform.position.x) { rb.velocity = Vector3.right * moveSpeed; if (bodyTrans.localScale.x > 0) { Turn(); } } if (targetCharacter.transform.position.x < transform.position.x) { rb.velocity = Vector3.left * moveSpeed; if (bodyTrans.localScale.x < 0) { Turn(); } } } break; case CharacterState.ReadyToRush: time += Time.deltaTime; if (time >= readyCD) { time = 0; if (rushHaveAttack) { ChangeState(CharacterState.RushAttack); } else { ChangeState(CharacterState.Rush); } } break; case CharacterState.RushAttack: time += Time.deltaTime; dashEffect.canHit = true; Rush(); if (time >= rushTime) { time = 0; if (haveDownRush) { if (foot.TrigGround) { ChangeState(CharacterState.FinishRush); } else { ChangeState(CharacterState.ReadyToDownRush); } } else { ChangeState(CharacterState.FinishRush); } } break; case CharacterState.ReadyToDownRush: time += Time.deltaTime; if (time >= downRushTime) { time = 0; ChangeState(CharacterState.DownRush); } break; case CharacterState.DownRush: if (transform.position.y > 0) { dashEffect.canHit = true; Rush(); } if (foot.TrigGround || transform.position.y <= -1) { ChangeState(CharacterState.FinishRush); } break; case CharacterState.FinishRush: time += Time.deltaTime; if (time > finishRushTime) { time = 0; ChangeState(CharacterState.Idle); } break; default: break; } } public override void ChangeState(CharacterState newState) { if (state == newState) { return; } switch (state) { case CharacterState.Idle: break; case CharacterState.Run: rb.velocity = Vector3.zero; break; case CharacterState.Rush: rb.velocity = Vector3.zero; break; case CharacterState.Rise: if (!canFly) { bodyCollider.SetActive(true); } break; case CharacterState.Fall: rb.velocity = Vector3.zero; break; //case CharacterState.Hurt: // break; case CharacterState.Attack: break; case CharacterState.Die: isDie = false; break; case CharacterState.Weak: beRepelValue = totalBeRepelValue; newTotalWeakTime = totalWeakTime; if (isBeBlownUp) { isBeBlownUp = false; isBeReboundedX = false; isBeReboundedY = false; hasBeReboundedX = false; hasBeReboundedY = false; } break; case CharacterState.Float: canMove = true; break; case CharacterState.Coma: ani.Play("idle", 0, 0); if (canFly) { rb.constraints = RigidbodyConstraints.FreezeRotation | RigidbodyConstraints.FreezePositionZ | RigidbodyConstraints.FreezePositionY; rb.useGravity = false; } canMove = true; break; case CharacterState.FindPlayer: noOnSearchState = false; rb.velocity = Vector3.zero; isFindPlayer = false; break; case CharacterState.ReadyToRush: time = 0; aimEffect.SetActive(false); aimEffect.transform.localScale = Vector3.zero; rb.constraints = RigidbodyConstraints.FreezePositionZ | RigidbodyConstraints.FreezeRotation; break; case CharacterState.RushAttack: time = 0; dashEffect.canHit = false; rb.velocity = Vector3.zero; bodyTrans.rotation = Quaternion.Euler(Vector3.zero); break; case CharacterState.ReadyToDownRush: time = 0; rb.constraints = RigidbodyConstraints.FreezePositionZ | RigidbodyConstraints.FreezeRotation; break; case CharacterState.DownRush: dashEffect.canHit = false; rb.velocity = Vector3.zero; bodyTrans.rotation = Quaternion.Euler(Vector3.zero); if (foot.trigGroundList.Count == 0) { transform.position = new Vector3(transform.position.x, -1, 0); } else { transform.position = new Vector3(transform.position.x, foot.trigGroundList[0].transform.position.y, 0); } break; case CharacterState.FinishRush: time = 0; searchState = SearchState.NoTarget; noOnSearchState = false; ani.Play("idle", 0, 0); break; default: break; } CharacterState oldState = state; state = newState; switch (newState) { case CharacterState.Idle: ani.Play("idle", 0, 0); rb.velocity = Vector3.zero; //animalAni.SetInteger("state", (int)PlayerState.Idle); break; case CharacterState.Run: ani.Play("walk", 0, 0); //animalAni.SetInteger("state", (int)PlayerState.Walk); break; case CharacterState.Rush: ani.Play("rush", 0, 0); break; case CharacterState.Float: canMove = false; break; case CharacterState.Coma: if (willBeComa) { BeHit(comaDamage, Vector3.zero, false, 0); } //ani.Play("Coma", 0, 0); ani.Play("weak", 0, 0); rb.velocity = Vector3.zero; pastComaTime = 0; if (canFly) { rb.constraints = RigidbodyConstraints.FreezeRotation | RigidbodyConstraints.FreezePositionZ; rb.useGravity = true; } break; case CharacterState.Attack: break; case CharacterState.Die: ani.Play("die", 0, 0); isDie = true; dieKeepTime = totalDieKeepTime; DropSouls(); if (linked) { PlayersInput.instance[0].sprintLinkTrigger.linkedEnemy.Remove(this); PlayersInput.instance[0].playerRope.gameObject.SetActive(false); } break; case CharacterState.Weak: switch (oldState) { case CharacterState.ReadyToRush: case CharacterState.RushAttack: case CharacterState.ReadyToDownRush: case CharacterState.DownRush: case CharacterState.Rush: state = oldState; beRepelValue = totalBeRepelValue; break; default: weakTime = newTotalWeakTime; rb.AddForce(weakForce); if (canFly) { rb.constraints = RigidbodyConstraints.FreezeRotation | RigidbodyConstraints.FreezePositionZ; rb.useGravity = true; } //hurtKeepTime = minHurtKeepTime; break; } break; case CharacterState.FindPlayer: isFindPlayer = false; isFindingPlayer = true; noOnSearchState = true; ChosePlayer(); ani.Play("walk", 0, 0); break; case CharacterState.ReadyToRush: time = 0; canNotChangeHurt = true; ani.Play("charge", 0, 0); aimEffect.SetActive(true); rb.constraints = RigidbodyConstraints.FreezeAll; ReadyToDash(rushEndPos + Vector3.up, transform.position + Vector3.up); break; case CharacterState.RushAttack: targetDir = (rushEndPos - transform.position).normalized; ani.Play("rush_attack", 0, 0); break; case CharacterState.ReadyToDownRush: time = 0; rb.constraints = RigidbodyConstraints.FreezeAll; ani.Play("charge", 0, 0); break; case CharacterState.DownRush: time = 0; targetDir = Vector3.down; ani.Play("rush_attack", 0, 0); break; case CharacterState.FinishRush: time = 0; if (oldState == CharacterState.DownRush) { ani.Play("fall_end", 0, 0); } else { ani.Play("idle", 0, 0); } canNotChangeHurt = false; break; default: break; } } public void DropSouls() { int dropSoulNum = Random.Range(dropSoulMin, dropSoulMax + 1); if (dropSoulNum > 1) { for (int i = 0; i < dropSoulNum; i++) { float angleInterval = dropSoulAngle / (float)(dropSoulNum - 1); float angle = 90 + ((float)i - (float)(dropSoulNum - 1) / 2) * angleInterval; angle = angle / 180 * Mathf.PI; GameObject soulObj = PoolManager.Instantiate(soulPrefab, transform.position); Vector3 dir = new Vector3(Mathf.Cos(angle), Mathf.Sin(angle), 0); Soul soul = soulObj.GetComponent(); soul.Burst(dir * soulStartSpeed); soul.type = type; } } else { GameObject soulObj = PoolManager.Instantiate(soulPrefab, transform.position); Vector3 dir = Vector3.up; Soul soul = soulObj.GetComponent(); soul.Burst(dir * soulStartSpeed); soul.type = type; } } public void Jump() { SetUpSpeed(jumpSpeed); ani.Play("jump", 0, 0); } public void SetUpSpeed(float speed) { ChangeState(CharacterState.Rise); Vector3 velocity = rb.velocity; Vector3 leftDir = GetMoveDir(); if (leftDir.x > 0.3f) { if (bodyTrans.localScale.x > 0) { Turn(); } } else if (leftDir.x < -0.3f) { if (bodyTrans.localScale.x < 0) { Turn(); } } velocity.y = speed; rb.velocity = velocity; //animalAni.SetInteger("state", (int)PlayerState.Rise); } public void ChangeSearchState(SearchState newState) { switch (searchState) { case SearchState.NoTarget: break; case SearchState.InSearchScope: break; case SearchState.InAttackScope: break; default: break; } searchState = newState; switch (searchState) { case SearchState.NoTarget: Character character0 = PlayersInput.instance[0]; Character character1 = PlayersInput.instance[1]; if (character0 && character0.beTargetCharacter.Exists(t => t == this)) { character0.beTargetCharacter.Remove(this); } if (character1 && character1.beTargetCharacter.Exists(t => t == this)) { character1.beTargetCharacter.Remove(this); } targetCharacter = null; break; case SearchState.InSearchScope: break; case SearchState.InAttackScope: break; default: break; } } public bool SearchTarget() { targetCharacter = searchTrigger.GetMinDisTarget(targetTypes, canHitFly); if (targetCharacter != null) { Character character0 = PlayersInput.instance[0]; Character character1 = PlayersInput.instance[1]; if (targetCharacter == character0 && !character0.beTargetCharacter.Exists(t => t == this)) { character0.beTargetCharacter.Add(this); } if (targetCharacter == character1 && !character1.beTargetCharacter.Exists(t => t == this)) { character1.beTargetCharacter.Add(this); } return true; } else { return false; } } public void OnSearchState() { switch (searchState) { case SearchState.NoTarget: if (SearchTarget()) { ChangeSearchState(SearchState.InSearchScope); break; } //向玩家基地移动 break; case SearchState.InSearchScope: if (!SearchTarget()) { targetCharacter = null; ChangeSearchState(SearchState.NoTarget); break; } if (targetCharacter != null && Mathf.Abs(targetCharacter.transform.position.x - transform.position.x) <= attackDistance) { ChangeSearchState(SearchState.InAttackScope); break; } break; case SearchState.InAttackScope: if (targetCharacter != null) { if (!targetCharacter.gameObject.activeInHierarchy || targetCharacter.isDie || Mathf.Abs(targetCharacter.transform.position.x - transform.position.x) > attackDistance) { ChangeSearchState(SearchState.NoTarget); } } else { ChangeSearchState(SearchState.NoTarget); } break; default: break; } } public override void Attack_summon() { base.Attack_summon(); attackTarget = targetCharacter; } public override void Attack_march() { base.Attack_march(); attackTarget = targetCharacter; } public void ChosePlayer() { float distance0 = Mathf.Infinity; float distance1 = Mathf.Infinity; PlayerController player0 = PlayersInput.instance[0]; PlayerController player1 = PlayersInput.instance[1]; if (player0 != null && !player0.isRevive && !player0.isBaseBtnOut) { distance0 = Mathf.Abs(player0.transform.position.x - transform.position.x); } if (player1 != null && !player1.isRevive && !player1.isBaseBtnOut) { distance1 = Mathf.Abs(player1.transform.position.x - transform.position.x); } if (distance0 == Mathf.Infinity && distance1 == Mathf.Infinity) { targetCharacter = null; return; } if (distance0 <= distance1) { targetCharacter = player0; if (!player0.beTargetCharacter.Exists(t => t == this)) { player0.beTargetCharacter.Add(this); } distance = distance0; } else { targetCharacter = player1; if (!player1.beTargetCharacter.Exists(t => t == this)) { player1.beTargetCharacter.Add(this); } distance = distance1; } } public void ReadyToDash(Vector3 pos0, Vector3 pos1) { Vector3 target = (pos0 - pos1).normalized; float distance = aimDistance; aimEffect.transform.localScale = new Vector3(distance, 1, 1); targetDir = pos0 - pos1; float k = Mathf.Atan2(targetDir.y, targetDir.x) * Mathf.Rad2Deg; if (targetDir.x < 0) { aimEffect.transform.rotation = Quaternion.Euler(new Vector3(0, 0, k)); if (bodyTrans.localScale.x < 0) { bodyTrans.localScale = new Vector3(-bodyTrans.localScale.x, bodyTrans.localScale.y, bodyTrans.localScale.z); } } else { aimEffect.transform.rotation = Quaternion.Euler(new Vector3(0, 0, k)); if (bodyTrans.localScale.x > 0) { bodyTrans.localScale = new Vector3(-bodyTrans.localScale.x, bodyTrans.localScale.y, bodyTrans.localScale.z); } } } private void Rush() { float k = Mathf.Atan2(targetDir.y, targetDir.x) * Mathf.Rad2Deg; if (targetDir.x < 0) { dashEffect.offset = 1; if (bodyTrans.localScale.x < 0) { bodyTrans.localScale = new Vector3(-bodyTrans.localScale.x, bodyTrans.localScale.y, bodyTrans.localScale.z); } bodyTrans.rotation = Quaternion.Euler(new Vector3(0, 0, k - 180)); } else { if (bodyTrans.localScale.x > 0) { bodyTrans.localScale = new Vector3(-bodyTrans.localScale.x, bodyTrans.localScale.y, bodyTrans.localScale.z); } dashEffect.offset = -1; bodyTrans.rotation = Quaternion.Euler(new Vector3(0, 0, k)); } rb.velocity = targetDir * rushSpeed; } }