Smarter Enemy (take cover(SIMPLE))

Hi again!

As I am trying to get my bullet tracer working… I decided to try something else as I wait for more suggestions. I have an enemy script below that makes the enemy shoot at the player when in range and all that good stuff. But I want more. I want the enemy to take cover but very simply. I want them to take cover when they go into combat (get shot, player comes into range, ect…) I was thinking raycasting the enemy to find the closest object (Mabey with a certain tag) and go and hide behinde it (Mabey an empty gameobject attected to the wall) or go to that empty gameobject. Then, every 2 secs. or whatever they poke out to fire for 2 secs. then hide again and stop firing. The more simpler the better because I would like to make it myself where they go to a different gameobject every 15 secs. I dont want you guys having all the fun! :slight_smile: Any suggestions, tips, or even scripts will help! Thanks in advance! You guys at unity answers have been awsome to me!

Use Physics.OverlapSphere instead of Raycast. Except that, if you have a good working state machine, it shouldn’t too difficult.

I’m working on zombie AI at the moment and came across this looking for ways to scan for my different triggers. Not sure what the two have related. Anyways, my AI is based off of behaviors that cycle under different circumstances, rather than solid loop code. The global behavior is always scanning for targets, and general animations. By default, the AI is also in IDLE behavior. If it obtains a target while in this behavior, it jumps to chase behavior to path to the closest target. If it gets close enough, it moves into attack behavior and swipes at the player. If I were to modify this code for a behavior on looking for cover, it would be based on weather or not the AI took much damage while in chase. I would then create empty-objects within the map that are adequate hiding spots. Once this was done, the cover behavior would sphere scan all ducking positions in proximity, match each to the player with some relative formula about the safety of each (something along the lines of distance to travel, player line of sight on cover, etc), sort for best choice and move, then swap to ranged attack behavior or something.

If your maps are designed on-the-go, you would add these locations to the objects (rather than the level) and delete lost locations (due to debris).

[AI.cs] - to be attached to object that needs intelligence
	BehaviorManager Behavior = new BehaviorManager();
	public List<Transform> targets = new List<Transform>();


	// Use this for initialization
	void Start () {
		// load profiles
		Behavior = new BehaviorManager();
		Behavior.AddState("Idle", new Idle(Behavior, this));
		Behavior.AddState("Chase", new Chase(Behavior, this));
		Behavior.AddState("Attack1", new AttackPatern1(Behavior, this));
		Behavior.ChangeState("Idle");
	}

	void Update () {
		Behavior.onUpdate();
	}
	// Loop for passive actions
	void LateUpdate() {
		Behavior.onLateUpdate();
	}
	// Loop for important actions
	void FixedUpdate() {
		Behavior.onFixedUpdate();
	}

[BehaviorManager.cs] - manages behavior states
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class BehaviorManager {
	Dictionary<string, Behavior> _states = new Dictionary<string, Behavior>();
	string _currentStateID;
	Behavior _currentState;// = null;
	bool Loaded;// = false;
	
	// Use this for initialization
	void Start () {
		Behavior _currentState = null;
		bool Loaded = false;
	}
	
	public void onLoad() {
	    try
        {
            if (_currentState == null)
                return; //nothing to load
            if (!Loaded)
            {
                _currentState.onLoad();
                Loaded = true;
            }
        }
        catch (Exception e)
        {
            Debug.Log("onLoad() Error! " + e.ToString() + ".");
        }
	}
	
    public void onUpdate()
    {
        try
        {
            if (_currentState == null)
                return;//nothing to update

            _currentState.onUpdate();
        }
        catch (Exception e)
        {
            Debug.Log("onUpdate() Error! " + e.ToString() + ".");
        }
    }
	public void onLateUpdate() 
	{
        try
        {
            if (_currentState == null)
                return;//nothing to update

            _currentState.onLateUpdate();
        }
        catch (Exception e)
        {
            Debug.Log("onLateUpdate() Error! " + e.ToString() + ".");
        }
	}
	public void onFixedUpdate() 
	{
        try
        {
            if (_currentState == null)
                return;//nothing to update

            _currentState.onFixedUpdate();
        }
        catch (Exception e)
        {
            Debug.Log("onLateUpdate() Error! " + e.ToString() + ".");
        }
	}
    public void AddState(string stateId, Behavior state)
    {
        //System.Diagnostics.Debug.Assert(Exists(stateId) == false);
		if (_states.ContainsKey(stateId)) {
			_states.Remove(stateId);
	        Debug.Log (stateId + " being replaced.");
		}
        _states.Add(stateId, state);
        //Debug.Log (stateId + " added to States");
    }
    public void ChangeState(string stateId)
    {
		// prevent same state reload
		if (stateId == _currentStateID)
			return;
        //System.Diagnostics.Debug.Assert(Exists(stateId));
		if (!_states.ContainsKey(stateId)) {
	        Debug.Log (stateId + " state not found.");
			return;
		}
        Loaded = false;
        _currentState = _states[stateId];
		_currentStateID = stateId;
        onLoad();
        Debug.Log("Changed to "+stateId);
    }
	public Behavior current() {
		return _currentState;
	}
	public string GetStateID() {
		return _currentStateID;
	}
}

[Behavior.cs] - creates an event-like behavior
using UnityEngine;
using System.Collections;

public interface Behavior
{
	void onLateUpdate();
    void onUpdate();
	void onFixedUpdate();
    void onLoad();
}

[Idle.cs] - example of Idle Behavior
using UnityEngine;
using System.Collections;

public class Idle : Behavior {
	BehaviorManager _state;
	ZombieAI_1 parent;
	public Idle(BehaviorManager state, ZombieAI_1 parent) {
		_state = state;
		this.parent = parent;
	}
	// Use this for initialization
	public void onLoad () {
	
	}
	
	public void onLateUpdate()
	{
	}
	// Update is called once per frame
	public void onUpdate () {
		if (parent.targets.Count > 0) {
			_state.ChangeState("Chase");
		}
		// pick pathing coordinates
		
		// done
	}
	public void onFixedUpdate() {
	}
	
	public void ChangeTarget(Transform trgt) {
	}
}

Should be everything you need to shuffle away from solid-logistic coding, and move towards circumstantially event-driven behavior.

Lemme know if you find anything on registerring sounds given a location, I’d like to avoid creating temporary objects whenever I want to play a sound that might alert my AI.

You can use Physics.OverlapSphere as previously said by Berenger, of X units radius, add all the colliders present inside the X unit area, randomly select any colliders(thats how I did it), and set the destination of the enemy to that collider. Somethng like this:

if(state == “hideSpot”)
{
Debug.Log(“state is hideSpot” );

		var colliders : Collider[] = Physics.OverlapSphere(transform.position, 10f) ;
		var colliderLength : int = colliders.Length ;
		var range : int = Random.Range(0, colliderLength) ;
		
		var i : int ;
		for( i = 0 ; i <= colliderLength ; i++)
		{
			Debug.Log("colliders of "+ colliders*) ;*

_ if((colliders*.gameObject.tag == “Wall”))_
_
{_
_
if(i == (range))_
_
{_
_
nav.Resume() ;_
_ Debug.Log(colliders.gameObject.tag) ;
Debug.Log(" it is near the gameObject"+colliders) ;
nav.destination = colliders.gameObject.transform.position ;*_

* state = “hide” ;*
* }*
* }*
* }*
* }*
_*The project code can be accessed from here(with animations, music, etc): https://github.com/MohammadWasil/Unity-Soldier-AI-With-Animations-.git*_