public void LoadCheckpoint(LevelManager.CheckpointData.EnemyData data) { transform.position = data.worldPosition; transform.rotation = data.worldRotation; transform.parent = data.parent; if (!data.cured) { killed = false; GetComponent <Collider>().enabled = true; enemyAnimations.SetBool("Cured", false); health = data.health; state = State.DEFAULT; attackSubState = AttackSubState.NOT_ATTACKING; searchSubState = SearchSubState.NOT_SEARCHING; defaultSubState = DefaultSubState.NOT_DEFAULT; audioSource.clip = walkSounds; curedEnemies.Remove(this); targeted = false; } else { killed = true; } }
virtual public void Revive() { curedEnemies.Remove(this); targeted = false; health = maxHealth; agent.stoppingDistance = initialStoppingDistance; agent.SetDestination(transform.position); nextPatrolPoint = 0; state = State.DEFAULT; defaultSubState = DefaultSubState.NOT_DEFAULT; attackSubState = AttackSubState.NOT_ATTACKING; searchSubState = SearchSubState.NOT_SEARCHING; isStunned = false; sprite.color = Color.white; canStun = true; audioSource.clip = walkSounds; GetComponent <Collider>().enabled = true; killed = false; enemyAnimations.SetBool("Cured", false); StopAllCoroutines(); }
virtual protected void PerformDefaultPatrol() { nextPosition = Vector3.zero; switch (defaultSubState) { case DefaultSubState.NOT_DEFAULT: //Upon entering sub state machine, move to new random position within wander radius agent.SetDestination(patrolPoints[nextPatrolPoint].position); nextPatrolPoint = (nextPatrolPoint + 1) % patrolPoints.Count; defaultSubState = DefaultSubState.MOVING_TO_NEXT; break; case DefaultSubState.AT_POSITION: //When upon arriving at position, begin waiting to move to next position StartCoroutine(SetDestinationAfter(patrolPoints[nextPatrolPoint].position, timeAtPosition)); nextPatrolPoint = (nextPatrolPoint + 1) % patrolPoints.Count; defaultSubState = DefaultSubState.WAITING; break; case DefaultSubState.WAITING: //When the destination changes, change state to moving to next if (destinationChanged) { defaultSubState = DefaultSubState.MOVING_TO_NEXT; } break; case DefaultSubState.MOVING_TO_NEXT: //When the enemy arrives, set state to at Position if (agent.remainingDistance < agent.stoppingDistance) { defaultSubState = DefaultSubState.AT_POSITION; } break; default: Debug.LogError("Unrecognized Default Substate"); break; } }
virtual protected void PerformDefaultWander() { nextPosition = Vector3.zero; switch (defaultSubState) { case DefaultSubState.NOT_DEFAULT: //Upon entering sub state machine, move to new random position within wander radius nextPosition = new Vector3(Random.Range(-1f, 1f), 0f, Random.Range(-1f, 1f)).normalized *Random.Range(wanderRaduisMin, wanderRaduisMax); agent.SetDestination(initialPosition + nextPosition); defaultSubState = DefaultSubState.MOVING_TO_NEXT; break; case DefaultSubState.AT_POSITION: //When upon arriving at position, begin waiting to move to next position nextPosition = new Vector3(Random.Range(-1f, 1f), 0f, Random.Range(-1f, 1f)).normalized *Random.Range(wanderRaduisMin, wanderRaduisMax); StartCoroutine(SetDestinationAfter(initialPosition + nextPosition, timeAtPosition)); defaultSubState = DefaultSubState.WAITING; break; case DefaultSubState.WAITING: //When the destination changes, change state to moving to next if (destinationChanged) { defaultSubState = DefaultSubState.MOVING_TO_NEXT; } break; case DefaultSubState.MOVING_TO_NEXT: //When the enemy arrives, set state to at Position if (agent.remainingDistance < agent.stoppingDistance) { defaultSubState = DefaultSubState.AT_POSITION; } break; default: Debug.LogError("Unrecognized Default Substate"); break; } }
virtual protected void PerformDefaultStationary() { switch (defaultSubState) { case DefaultSubState.NOT_DEFAULT: //Upon entering sub state machine, move to initial position agent.SetDestination(initialPosition); defaultSubState = DefaultSubState.MOVING_TO_NEXT; break; case DefaultSubState.AT_POSITION: //upon arriving at initial position, begin waiting there if (agent.remainingDistance < agent.stoppingDistance) { defaultSubState = DefaultSubState.WAITING; } break; case DefaultSubState.WAITING: //while waiting for player at initial position, face in initial direction transform.rotation = Quaternion.Slerp(transform.rotation, initialRotation, Time.deltaTime * 5f); break; case DefaultSubState.MOVING_TO_NEXT: if (agent.destination != initialPosition) { agent.SetDestination(initialPosition); } break; default: Debug.LogError("Unrecognized Default Substate"); break; } // if (agent.remainingDistance < agent.stoppingDistance) // { // agent.SetDestination(initialPosition); // transform.rotation = Quaternion.Slerp(transform.rotation, initialRotation, Time.deltaTime * 5f); // } }
override protected IEnumerator Respawn() { foreach (SpriteRenderer sr in GetComponentsInChildren <SpriteRenderer>()) { sr.enabled = false; } health = maxHealth; transform.position = initialPosition; transform.rotation = initialRotation; agent.stoppingDistance = initialStoppingDistance; agent.SetDestination(transform.position); nextPatrolPoint = 0; state = State.DEFAULT; defaultSubState = DefaultSubState.NOT_DEFAULT; attackSubState = AttackSubState.NOT_ATTACKING; searchSubState = SearchSubState.NOT_SEARCHING; isStunned = false; sprite.color = Color.white; canStun = true; audioSource.clip = walkSounds; yield return(new WaitForSeconds(respawnTime)); foreach (SpriteRenderer sr in GetComponentsInChildren <SpriteRenderer>()) { sr.enabled = true; } GetComponent <Collider>().enabled = true; killed = false; enemyAnimations.SetBool("Cured", false); StopAllCoroutines(); }
virtual protected void PerformAILogic() { //Reset stopping distance if enemy is aware of player if (state != State.DEFAULT) { agent.stoppingDistance = initialStoppingDistance; } //Calculate distance to player float distance = Vector3.Distance(playerTransform.position, transform.position); //reset location flags hasLineOfSight = false; inChaseRadius = false; inAgroRadius = false; inAttackRadius = false; //set location flags if (distance <= chaseLimitRadius) { inChaseRadius = true; hasLineOfSight = RaycastToPlayer(); if (distance <= agroRadius && hasLineOfSight) { inAgroRadius = true; if (distance <= attackRaduis) { inAttackRadius = true; } } } if (PlayerManager.instance.isAlive) { //Implementation of highest level state machine switch (state) { case State.DEFAULT: //Exit case: Player enters agro radius if (inAgroRadius) { state = State.AGRO; defaultSubState = DefaultSubState.NOT_DEFAULT; PerformAgroState(); } else { PerformDefaultState(); } break; case State.AGRO: //Exit case: Player enters attack radius if (inAttackRadius) { state = State.ATTACKING; PerformAttackState(); } //Exit case: Player breaks line of sight or leaves chase radius else if (!hasLineOfSight) { state = State.SEARCHING; PerformSearchingState(); } else { PerformAgroState(); } break; case State.ATTACKING: //Exit Case: enemy finished attacking, return to agro if (attackSubState == AttackSubState.DONE) { state = State.AGRO; attackSubState = AttackSubState.NOT_ATTACKING; PerformAgroState(); } else { PerformAttackState(); } break; case State.SEARCHING: //Exit case: Searching concludes without finding player if (searchSubState == SearchSubState.DONE) { state = State.DEFAULT; searchSubState = SearchSubState.NOT_SEARCHING; PerformDefaultState(); } //Exit case: Enemy finds player else if (hasLineOfSight) { state = State.AGRO; searchSubState = SearchSubState.NOT_SEARCHING; } else { PerformSearchingState(); } break; default: Debug.LogError("Unrecognized State"); break; } } else { searchSubState = SearchSubState.NOT_SEARCHING; attackSubState = AttackSubState.NOT_ATTACKING; state = State.DEFAULT; } }