-
-
Save superspacehero/85b301ce6b3f209c79fb1ec6cfab0a39 to your computer and use it in GitHub Desktop.
Group-Based AI
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using UnityEngine.AI; | |
using System.Collections; | |
public class Enemy : MonoBehaviour | |
{ | |
private EnemyManager enemyManager; | |
private GameObject player; | |
private Vector3 target; | |
private NavMeshAgent agent; | |
private float timer; | |
public bool roam; | |
public float roamRadius = 6; | |
private float roamTime; | |
public float roamWaitTime = 3; | |
private float speed; | |
public GameObject[] Waypoints; | |
public float[] WaypointWaitTimes; | |
private int CurrentWaypoint; | |
private SphereCollider col; | |
public float viewDistance = 8; | |
public float fovAngle = 90; | |
public float chaseFovAngle = 180; | |
private float originalFovAngle; | |
public bool canSeePlayer; | |
public LayerMask viewMask; | |
private Vector3 PreviousLocation; | |
private float originalStoppingDistance; | |
public float attackRange = 2; | |
private GameObject sprite; | |
private Quaternion spriteRotation; | |
public bool patrol; | |
private bool targeted; | |
public bool suspicious; | |
private float angle; | |
private AudioSource voice; | |
private bool talk; | |
public AudioClip enemySighted; | |
public AudioClip overThere; | |
public AudioClip huh; | |
public AudioClip whatsThat; | |
public AudioClip eh; | |
// Use this for initialization | |
void OnEnable() | |
{ | |
agent = GetComponent<NavMeshAgent>(); | |
target = transform.position; | |
timer = WaypointWaitTimes[CurrentWaypoint]; | |
sprite = GetComponentInChildren<SpriteRenderer>().gameObject; | |
spriteRotation = sprite.transform.rotation; | |
originalFovAngle = fovAngle; | |
voice = GetComponent<AudioSource>(); | |
enemyManager = GetComponentInParent<EnemyManager>(); | |
speed = agent.speed; | |
originalStoppingDistance = agent.stoppingDistance; | |
transform.rotation = Quaternion.Euler(new Vector3(0, 90 * Random.Range(0, 3))); | |
player = FindObjectOfType<PlayerMovement>().gameObject; | |
} | |
bool CanSeePlayer() | |
{ | |
if (Vector3.Distance(transform.position, player.transform.position) < viewDistance) | |
{ | |
Vector3 direction = (player.transform.position - transform.position); | |
angle = Vector3.Angle(direction, transform.forward); | |
if (angle <= fovAngle / 2) | |
{ | |
RaycastHit hit; | |
if (Physics.Raycast(transform.position + Vector3.up, direction.normalized, out hit, viewDistance, -1, QueryTriggerInteraction.Ignore) && hit.collider.gameObject == player) | |
{ | |
if (roam && !enemyManager.canSeePlayer && !enemyManager.alerting) | |
{ | |
voice.clip = overThere; | |
voice.Play(); | |
agent.isStopped = false; | |
enemyManager.alerting = true; | |
} | |
enemyManager.canSeePlayer = true; | |
enemyManager.playerLocationSeen = player.transform.position; | |
if (enemyManager.alert && enemyManager.currentAlertTime > 0) | |
enemyManager.currentAlertTime = enemyManager.alertTime; | |
roam = false; | |
suspicious = false; | |
canSeePlayer = true; | |
return true; | |
} | |
else | |
canSeePlayer = false; | |
} | |
} | |
return false; | |
} | |
void Update() | |
{ | |
agent.SetDestination(target); | |
CanSeePlayer(); | |
if (canSeePlayer && !enemyManager.alert) | |
{ | |
patrol = false; | |
target = enemyManager.playerLocationSeen; | |
agent.isStopped = true; | |
if (!voice.isPlaying && !voice.clip == enemySighted) | |
{ | |
voice.clip = enemySighted; | |
voice.Play(); | |
} | |
if (!voice.isPlaying) | |
{ | |
voice.clip = null; | |
agent.isStopped = false; | |
enemyManager.currentAlertTime = enemyManager.alertTime; | |
enemyManager.alert = true; | |
} | |
} | |
if (enemyManager.alert) | |
{ | |
agent.speed = speed; | |
if (patrol) | |
patrol = false; | |
fovAngle = chaseFovAngle; | |
agent.stoppingDistance = attackRange; | |
if (enemyManager.canSeePlayer) | |
{ | |
targeted = false; | |
target = enemyManager.playerLocationSeen; | |
} | |
else | |
{ | |
if (!targeted) | |
{ | |
target = enemyManager.playerLocationSeen; | |
if (agent.remainingDistance <= agent.stoppingDistance) | |
targeted = true; | |
} | |
else | |
Roam(); | |
} | |
} | |
else | |
{ | |
Patrol(); | |
} | |
if (suspicious && (patrol || roam)) | |
{ | |
if (voice.clip == huh && voice.isPlaying) | |
{ | |
roamTime = 0; | |
PreviousLocation = transform.position; | |
} | |
else | |
{ | |
if (!talk) | |
{ | |
voice.clip = whatsThat; | |
voice.Play(); | |
agent.isStopped = false; | |
talk = true; | |
} | |
if (agent.remainingDistance <= agent.stoppingDistance) | |
{ | |
roamTime += Time.deltaTime; | |
if (roamTime >= roamWaitTime) | |
{ | |
voice.clip = eh; | |
voice.Play(); | |
target = PreviousLocation; | |
roamTime = 0; | |
if (agent.remainingDistance <= agent.stoppingDistance) | |
{ | |
talk = false; | |
suspicious = false; | |
} | |
} | |
} | |
} | |
} | |
sprite.transform.position = new Vector3(transform.position.x, 0, transform.position.z - 0.25f); | |
sprite.transform.rotation = spriteRotation; | |
} | |
void OnTriggerEnter(Collider other) | |
{ | |
if ((patrol || roam) && other.tag == "Ping" && !suspicious) | |
{ | |
suspicious = true; | |
agent.isStopped = true; | |
voice.clip = huh; | |
voice.Play(); | |
target = other.transform.position; | |
} | |
} | |
void Patrol() | |
{ | |
agent.stoppingDistance = originalStoppingDistance; | |
agent.speed = speed * 0.75f; | |
fovAngle = originalFovAngle; | |
if (Waypoints.Length > 0) | |
{ | |
if (patrol && !suspicious) | |
{ | |
target = Waypoints[CurrentWaypoint].transform.position; | |
if (agent.remainingDistance <= agent.stoppingDistance) | |
timer += Time.deltaTime; | |
if (timer >= WaypointWaitTimes[CurrentWaypoint]) | |
{ | |
if (CurrentWaypoint == Waypoints.Length - 1) | |
CurrentWaypoint = 0; | |
else | |
CurrentWaypoint++; | |
timer = 0; | |
} | |
} | |
} | |
else | |
{ | |
if (!patrol) | |
{ | |
roamTime = 0; | |
patrol = true; | |
} | |
if (patrol && !suspicious) | |
{ | |
roamTime += Time.deltaTime; | |
if (roamTime >= roamWaitTime) | |
{ | |
Vector3 newPos = RandomNavSphere(transform.position, roamRadius, -1); | |
target = newPos; | |
roamTime = 0; | |
} | |
} | |
} | |
} | |
void Roam() | |
{ | |
fovAngle = originalFovAngle; | |
if (!roam && agent.remainingDistance <= agent.stoppingDistance) | |
{ | |
roamTime = roamWaitTime; | |
roam = true; | |
} | |
if (roam && !suspicious) | |
{ | |
roamTime += Time.deltaTime; | |
if (roamTime >= roamWaitTime) | |
{ | |
Vector3 newPos = RandomNavSphere(transform.position, roamRadius, -1); | |
target = newPos; | |
roamTime = 0; | |
} | |
} | |
} | |
public static Vector3 RandomNavSphere(Vector3 origin, float dist, int layermask) | |
{ | |
Vector3 randDirection = Random.insideUnitSphere * dist; | |
randDirection += origin; | |
NavMeshHit navHit; | |
NavMesh.SamplePosition(randDirection, out navHit, dist, layermask); | |
return navHit.position; | |
} | |
void OnCollisionEnter(Collision collision) | |
{ | |
if (collision.gameObject.tag == "Player") | |
{ | |
fovAngle = 360; | |
enemyManager.playerLocationSeen = collision.transform.position; | |
} | |
} | |
void OnDrawGizmos() | |
{ | |
Gizmos.color = Color.red; | |
Gizmos.DrawRay(transform.position + Vector3.up, ((transform.rotation * Vector3.forward) * viewDistance)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment