Skip to content

Instantly share code, notes, and snippets.

@superspacehero
Created May 3, 2018 06:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save superspacehero/85b301ce6b3f209c79fb1ec6cfab0a39 to your computer and use it in GitHub Desktop.
Save superspacehero/85b301ce6b3f209c79fb1ec6cfab0a39 to your computer and use it in GitHub Desktop.
Group-Based AI
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