Certain Logic Studios has been working on an Open-Sourced Navigation framework. The package allows users to:
Generate and edit navigation grids on arbitrary geometry
Save generated navigation grids to a file
Load these saved grids to a PathMaster and allow Path Finding Game Agents to pathfind across the generated grids
We were going to roll our own locomotion engine for this… but I took a second look at UnitySteer 2.0 and to be honest this system is far more robust than anything that we could have come up with in the short term. Arges has outdone himself and darn near perfected the system for Unity users (a huge thanks to him for that of course!.. if you haven’t seen this project before please do check it out – http://forum.unity3d.com/threads/64292-UnitySteer-2.0-released?highlight=unitysteer+2.0)
I have only just scratched the surface of what UnitySteer can do, but I’ve managed to pull together an extremely crude demo of the framework in it’s current state. Figured I’d post a video to let people see.
Check it out, this framework is available… but there are still many changes to do. Expect the system to change quite a bit in the near future… and the documentation will also be evolving. I’m releasing it early in case anyone wanted a peek at the code and wanted to tinker with it.
We’ll be offering updates as they arrive through our twitter if you wish to keep an eye on the progress of the package. The link is in my signature. We will also post updates here.
This looks very promising since I’m currently searching for a pathfinding solution to work with UnitySteer. Seems you’ve done the work for me!
In my application, I’m developing level geometry procedurally; how easy is it to generate the navmeshes at runtime, and do you have any examples of this in practice.
i try to make Tower Defence enemy AI . Enemy behave like RTS games. It decide how target closest me and change the target. Also it is my graduation project from university. Please tell me any options or suggestions…
I use A* pathfinding system and try to modify the AIFollow.cs but i did not sucessful.There are two functions. GetEnemies() create an array which includes “Target” tag of GameObjects. But it is not working.
Here is my code:
using UnityEngine;
using System.Collections;
public class AIFollow : MonoBehaviour {
//[RequireComponent (typeof(CharacterController))]
public float speed = 3.0F;
public float rotationSpeed = 5.0F;
public float pickNextWaypointDistance = 3.0F;
public float SearchWaypointFrequency = 0.2F;
public float maxStop = 3;
public bool continousTargetSearch = false;
public float targetSearchFrequency = 1.0F;
private bool canSearchAgain = true;
public Command command = Command.Stay;
public Transform target;
private CharacterController controller;
private AIAnimation animator;
private Seeker seeker;
public Vector3 myPosition;
public Transform[] enemies;
public float distance;
// Make sure there is always a character controller
public enum Command {
Stay,
Walk
}
public IEnumerator Start () { //public IEnumerator Start ()
waypointPosition = transform.position;
command = Command.Stay;
controller = GetComponent (typeof(CharacterController)) as CharacterController;
Object anim = GetComponent (typeof(AIAnimation));
animator = anim != null ? anim as AIAnimation : null;
seeker = GetComponent (typeof(Seeker)) as Seeker;
StartCoroutine (Patrol());
yield return new WaitForSeconds (Random.value*0.5F);
if (continousTargetSearch) {
StartCoroutine (SearchPlayer());
}
[COLOR="red"]//here is the start array operations[/COLOR]
GetEnemies();
myPosition = transform.position;
target = FindClosest(enemies);
distance=Vector3.Distance(target.position,transform.position);
while (true) {
FindPoint (curpoint);
yield return new WaitForSeconds (SearchWaypointFrequency);
}
}
private Vector3 waypointPosition;
//private bool continuous = false;
private Vector3[] points;
private int curpoint = 0;
public void Update () {
//Debug.color = Color.blue;
Debug.DrawLine (transform.position, waypointPosition, Color.blue);
//Stop();
Start();
/*GetEnemies();
myPosition = transform.position;
target = FindClosest(enemies);
distance=Vector3.Distance(target.position,transform.position);*/
}
public IEnumerator SearchPlayer () {
yield return 0;
while (true) {
yield return 0;
while (!canSearchAgain) {
yield return 0;
}
if (continousTargetSearch) {
canSearchAgain = false;
seeker.StartPath (transform.position,target.position);
}
yield return new WaitForSeconds (targetSearchFrequency);
}
}
public void PathComplete (Vector3[] newPoints) {
canSearchAgain = true;
points = newPoints;
FindPoint (0);
command = Command.Walk;
}
public void PathError () {
canSearchAgain = true;
}
public bool HasReachedTarget () {
return curpoint >= points.Length;
}
public void FindPoint (int cpoint) {
curpoint = cpoint;
if (points == null || points.Length == 0 || curpoint >= points.Length) {
waypointPosition = transform.position;
Stop ();
return;
}
if (points.Length == 1) {
waypointPosition = points[0];
command = Command.Walk;
return;
}
command = Command.Walk;
waypointPosition = points[curpoint];
Vector3 p = waypointPosition;
p.y = transform.position.y;
if (curpoint < points.Length - 1) {
if ((transform.position-p).sqrMagnitude < pickNextWaypointDistance*pickNextWaypointDistance) {
curpoint++;
FindPoint (curpoint);
}
} else {
if ((transform.position-p).sqrMagnitude < maxStop*maxStop) {
curpoint++;
FindPoint (curpoint);
}
}
}
public IEnumerator Patrol () {
while (true) {
if (command == Command.Walk) {
MoveTowards(waypointPosition);
}
yield return 0;
}
}
public void Stop () {
command = Command.Stay;
if (animator != null) {
animator.SetSpeed (0.0F);
}
}
public void RotateTowards (Vector3 position) {
if (animator != null) {
animator.SetSpeed (0.0F);
}
Vector3 direction = position - transform.position;
direction.y = 0;
if (curpoint == points.Length - 1 direction.sqrMagnitude < maxStop*maxStop) {
FindPoint (curpoint);
return;
}
if (direction.sqrMagnitude < 0.1F*0.1F) {
return;
}
// Rotate towards the target
transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Time.deltaTime);
transform.eulerAngles = new Vector3(0, transform.eulerAngles.y, 0);
}
public void MoveTowards (Vector3 position) {
Vector3 direction = position - transform.position;
direction.y = 0;
if (direction.sqrMagnitude < 0.2F*0.2F) {
Stop ();
return;
}
// Rotate towards the target
transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Time.deltaTime);
transform.eulerAngles = new Vector3(0, transform.eulerAngles.y, 0);
// Modify speed so we slow down when we are not facing the target
Vector3 forward = transform.TransformDirection(Vector3.forward);
float speedModifier = Vector3.Dot(forward, direction.normalized);
speedModifier = Mathf.Clamp01(speedModifier);
// Move the character
if (controller) {
direction = forward * speed * speedModifier*speedModifier;
controller.SimpleMove(direction);
} else {
direction = forward * speed * speedModifier*speedModifier;
transform.Translate (direction*Time.deltaTime,Space.World);
}
if (animator != null) {
animator.SetSpeed (speed * speedModifier);
}
}
public void GetEnemies(){ [COLOR="red"]// Get enemies from the Scene [/COLOR]
GameObject[] enemyObjects = GameObject.FindGameObjectsWithTag("Target");
Transform[] enemies = new Transform[enemyObjects.Length];
for (int i = 0; i < enemyObjects.Length; i++)
{
enemies[i] = enemyObjects[i].transform;
Debug.Log("GetEnemies() : count = " + i );
}
Debug.Log("GetEnemies() : enemy count = " + enemies.Length);
}
public Transform FindClosest(Transform[] targets) [COLOR="red"]// Find Closest enemy[/COLOR]
{
Debug.Log("FindClosest() : ---------------> " +targets.Length);
GameObject[] enemyObjects = GameObject.FindGameObjectsWithTag("Target");
float closestDistance = (enemies[0].position-myPosition).sqrMagnitude;
int targetNumber=0;
for(int i=1; i<targets.Length ;i++)
{
float thisDisatance = (enemies[i].position-myPosition).sqrMagnitude;
if(thisDisatance<closestDistance)
{
closestDistance=thisDisatance;
targetNumber=i;
}
}
return enemies[targetNumber];
}
}
Shortly, i try to collect the “Targets”(Transform) in array and Enemy must find to closest “Target” which destroyed by enemies. Enemy behave like RTS games. Also it is my graduation project in university . Please tell me any options or suggestions…
Odd… this thread didn’t highlight for me! My apologies on missing this post. To get the mesh loading at run time is extremely easy… just look into how we currently “load” the meshes. And simply execute the “GenerateMesh()” function in a Start() function. This is a good idea for a feature I think… to allow the user to select if they want to precalculate the mesh, or generate at runtime. I hadn’t considered procedural geometry for some reason! Thanks for the heads up.
Hello, I’d like to help but I don’t really understand what the issue is at the moment. Maybe I can get at the issue if you can answer a few questions for me…
Are you using the CertainLogic Opensource Navigation Framework?
When you say “it doesn’t work”, what do you mean? What specifically is not working?
From the error it sounds like no navigation map is actually being loaded and registered. When you generated your navigation map… did you actually see the green grid form properly? If so did you save it at this point? I’m wondering if the error is arising form a null map being saved/loaded. Also in your PathMaster Inpsector did you add your map file to the registered list so that it loads?
i loaded the map from the file which saved in your example path in project. When i press the play button and click to Pathmaster in hierarchy , there is no mesh in pathmaster. ı do not understant, i saved it and loaded it. But it did not work.In addition there is no green nodes or lines when playing. I did everything in your youtube tutorial.I saved it before clear the mesh.
Are there any folder preparation in project for navmes?
Sorry I think I’m misunderstanding… did you load a pre-existing map? Or did you first generate the map file based on your arbitrary geometry (level) and then load that? I’ll get to the bottom of this lol, I’m just trying to figure out at what part something isn’t working.
i loaded it by using Pathmaster. Especially i generated my own mesh, then i save it. However , i clear the mesh before saving umm i am not sure , maybe i am the source of this problem anyway, i will check my steps in 30 minutes and i will write here again
The shape doesn’t matter for our system. Currently our grid system is generated statically… but if you retooled your own mechanism to add/remove nodes as you wish, that’s certainly possible and the pathing will certainly work on a dynamic field as at any given search call the grid will be “static”.
So in short, yes the system will certainly handle what you need, but not out of the box, you’ll need to of course code something to manage the added/removed nodes from the BaseNavMesh.