Post by ashyb on Jun 5, 2017 6:19:41 GMT
Invector the waypoint system is pretty cool.
I was wondering how to set it up at runtime, but it was surprisingly easy to do
Suggestion, on the v_AIController. If you spawn waypoints at runtime and assign them to the AI, if one of those waypoints happens to be inside another object, or inside a hill for example, the AI tries to walk to it but because it can never reach the waypoint, it just stands there doing nothing. If the waypoint spawns above ground tho, it seems to work well. The AI will walk to the ground point beneath the waypoint so its all good
I made this bit of code, it checks every 10s or so if the Ai can reach the waypoint, if not it sets current waypoint to null which forces the AI to choose another one to walk to. Works well. waypointblocker is default or whatever your ground and buildings are.
Now I just spawn my AI and waypoints at runtime and they look cool when they try to walk to a point and realize a crate is blocking them so they change direction and walk around it to another spot.
If anyone else is interested, also found a way to make the AI "call for help". Snippets here if anyone interested.
On the AI, put this script, replaces the v_AIController
Then on a child object of the AI, put this script and a sphere collider trigger (the AI will call to other AI inside the sphere)
Might need a bit of tweakin. Works well, shoot at one of them and it will call out to any nearby AI, then they all start running at you :D
Just thought I'd post it so invector can have an insight into what other people might be using his stuff for and for any new comers who might be interested in doing something similar.
I was wondering how to set it up at runtime, but it was surprisingly easy to do
Suggestion, on the v_AIController. If you spawn waypoints at runtime and assign them to the AI, if one of those waypoints happens to be inside another object, or inside a hill for example, the AI tries to walk to it but because it can never reach the waypoint, it just stands there doing nothing. If the waypoint spawns above ground tho, it seems to work well. The AI will walk to the ground point beneath the waypoint so its all good
I made this bit of code, it checks every 10s or so if the Ai can reach the waypoint, if not it sets current waypoint to null which forces the AI to choose another one to walk to. Works well. waypointblocker is default or whatever your ground and buildings are.
IEnumerator CheckWaypointValid()
{
while (this.enabled)
{
while (currentState != AIStates.PatrolWaypoints)
{
yield return null;
}
yield return new WaitForSeconds(checkWaypointValidIteration);
currentWaypointTargetGood = true;
var pos = new Vector3(transform.position.x, transform.position.y + 0.9f, transform.position.z);
RaycastHit hit;
if (Physics.Linecast(pos, targetWaypoint.position, out hit, waypointBlocker))
{
Debug.Log("can't reach waypoint, trying a different one instead. Object blocking path: " + hit.transform.name);
targetWaypoint = null;
currentWaypointTargetGood = false;
}
}
}
Now I just spawn my AI and waypoints at runtime and they look cool when they try to walk to a point and realize a crate is blocking them so they change direction and walk around it to another spot.
If anyone else is interested, also found a way to make the AI "call for help". Snippets here if anyone interested.
On the AI, put this script, replaces the v_AIController
public class ash_vAiController : Invector.v_AIController
{
[SerializeField]
float checkWaypointValidIteration = 10f;
[SerializeField]
bool currentWaypointTargetGood;
[Tooltip("Select the layers you want to check for collisions against to make the AI select a different waypoint.")]
[SerializeField]
LayerMask waypointBlocker;
protected override void Start()
{
base.Start();
StartCoroutine(CheckWaypointValid());
}
public void SetAssistTarget(Transform t)
{
// if told to attack the same current target, ignore it so we don't have unnecessary state changes?
if (target == t || t == null) return;
agressiveAtFirstSight = true;
target = t;
SetTarget();
currentState = AIStates.Chase;
}
public Transform GetTarget()
{
return target;
}
IEnumerator CheckWaypointValid()
{
while (this.enabled)
{
while (currentState != AIStates.PatrolWaypoints)
{
yield return null;
}
yield return new WaitForSeconds(checkWaypointValidIteration);
currentWaypointTargetGood = true;
var pos = new Vector3(transform.position.x, transform.position.y + 0.9f, transform.position.z);
RaycastHit hit;
if (Physics.Linecast(pos, targetWaypoint.position, out hit, waypointBlocker))
{
Debug.Log("can't reach waypoint, trying a different one instead. Object blocking path: " + hit.transform.name);
targetWaypoint = null;
currentWaypointTargetGood = false;
}
}
}
}
Then on a child object of the AI, put this script and a sphere collider trigger (the AI will call to other AI inside the sphere)
public class ash_AiCallForHelp : MonoBehaviour
{
ash_vAiController thisController;
[SerializeField]
float minCallWaitTime = 0f;
[SerializeField]
float maxCallWaitTime = 10f;
[Tooltip("Other AI characters in range to call for help.")]
public List<ash_vAiController> AiCharacters = new List<ash_vAiController>();
private void Awake()
{
thisController = GetComponentInParent<ash_vAiController>();
if (!thisController) Debug.LogError("You need to use this on an AI Controller: " + gameObject.name);
}
// called by the AI state change to chase
public void CallForHelp()
{
StartCoroutine(CallingForHelp());
}
IEnumerator CallingForHelp()
{
yield return new WaitForSeconds(Random.Range(minCallWaitTime, maxCallWaitTime));
// Debug.Log("calling for help");
foreach (var a in AiCharacters)
{
a.SetAssistTarget(thisController.GetTarget());
}
}
private void OnTriggerEnter(Collider other)
{
ash_vAiController controller;
if (other.GetComponent<ash_vAiController>() != null)
{
controller = other.GetComponent<ash_vAiController>();
if (controller == thisController) return;
// don't add the same thing twice, though i suppose it doesn't really matter since we're just gonna set the player as the target and call aggressiveAtFirstSight = true
foreach (var a in AiCharacters)
{
if (a == controller) return;
}
AiCharacters.Add(other.GetComponent<ash_vAiController>());
}
}
private void OnTriggerExit(Collider other)
{
ash_vAiController controller;
if (other.GetComponent<ash_vAiController>() != null)
{
controller = other.GetComponent<ash_vAiController>();
if (controller == thisController) return;
foreach (var a in AiCharacters)
{
if (a == controller)
{
AiCharacters.Remove(a);
return;
}
}
}
}
}
Might need a bit of tweakin. Works well, shoot at one of them and it will call out to any nearby AI, then they all start running at you :D
Just thought I'd post it so invector can have an insight into what other people might be using his stuff for and for any new comers who might be interested in doing something similar.