I'm currently creating a function which, when called, calculates the distance to each vector in an array of waypoints and returns the three closest way points.
This is for the Unity Stealth Project.
I thought I had it working but then realised my function always returned the same three waypoints, but occasionally in different orders. The issue I found (by using Debug.Log to show the path corners of each NavMeshPath the function generated) was that all the points in the NavMeshPath were 0, 0, 0.
When I've previously used NavMeshAgent.CalculatePath, I didn't have this issue, in fact I'm successfully using it to make my AI return to their closest patrol point (as opposed to the last patrol waypoint).
Here's the code I'm using:
int FindNearestWaypoints (Vector3 sightingPosition, Transform [] WayPoints)
{
int minDistanceIndex;
float[] distanceToWaypoint = new float [WayPoints.Length];
// An array of floats to store the distances to each of the AI's patrol waypoints.
NavMeshPath [] returnPaths = new NavMeshPath[WayPoints.Length];
// An array of NavMeshPaths, the lengths of which we want to measure.
for (int i = 0; i < distanceToWaypoint.Length; i++)
{
returnPaths [i] = new NavMeshPath();
NavMesh.CalculatePath (sightingPosition, WayPoints[i].position, NavMesh.AllAreas, returnPaths[i]);
Vector3 [] allPoints = new Vector3[returnPaths[i].corners.Length+2];
allPoints [0] = sightingPosition;
allPoints [allPoints.Length-1] = WayPoints[i].position;
for (int j = 0; j < returnPaths[i].corners.Length - 1; j++)
{
allPoints[j+1] = returnPaths[i].corners[j];
}
// Adds the path corners to the array of Vector3s.
for (int k = 0; k < allPoints.Length - 1; k++)
{
distanceToWaypoint [i] += Vector3.Distance (allPoints[k+1],allPoints [k]);
}//Calculates the distance between each point in the Vector3 array and sums it.
}
minDistanceIndex = FindMininumIndex (distanceToWaypoint);
return minDistanceIndex;
}
When I used Debug.Log, I found that all the allpoints values were actually 0, 0, 0.
And yes this is a modified version of the hearing distance script from the tutorial.
↧
Why are NavMeshPath.corners all 0, 0, 0 when generated with NavMesh.CalculatePath?
↧
NavMeshAgent's desiredVelocity and .hasPath falsely returning 0 / false
The following code executes with no errors in my game. the agent correctly moves to the position set in SetDestination, but the log prints 'false' and the desired velocity is 0. Even worse, I have made NO changes since this was working. This is literally Unity 5 example project code with one line of debug inserted. Yes I have tried deleting that line not that it should make a difference.
it's also not a random compilation error. it happens 100% of the time now. What can I do about something like this?
agent.SetDestination( m_ChosenNode.transform.position );
Debug.Log(agent.hasPath);
character.Move(agent.desiredVelocity, false, false);
↧
↧
My NavMeshAgent won't move, I've tried everything
I have 6 NavMesh agents on a terrain with a baked NavMesh. The agents are all prefabs. Their y transform IS on the NavMesh and I have debugged to make sure they are active agents. I get the (seemingly) common error: "SetDestination" can only be called on an active agent placed on a NavMesh. I also get the warning: Failed to create agent because it is not close enough to NavMesh. I have re-baked the NavMesh several times. I also have another scene with the same prefab and a baked NavMesh with the same problems. Please help!
↧
Choking on WaitForSeconds coroutine (solved)
Gents - I have a Navmesh Agent roaming around a map. When the player approaches within a certain distance from the agent, the agent goes into a "suspicious" mode and pauses for 3 seconds. Within that 3-second window, if the player goes outside the bound, then the agent moves on. Otherwise, the agent comes after the player.
Here's the corresponding code:
void Update() {
distanceToPlayer = CheckDistance(); // simply returning distance between the agent & player
if (distanceToPlayer < suspicionDistance) {
agent.Stop(); // make agent appear to be thinking...
feelingSuspicious = true;
StartCoroutine(ResolveSuspicion(3.0f)); // make agent stand still for 3 seconds until next move
if (chasingPlayer) {
agent.destination = player.transform.position; // get the intruder!
} else {
agent.Resume(); // hmm, must've been a rat...
}
....
}
....
}
IEnumerator ResolveSuspicion(float duration) {
yield return new WaitForSeconds(duration);
float distanceToPlayer = CheckDistance();
if (distanceToPlayer < suspicionDistance) {
chasingPlayer = true;
}
}
Everything works as intended, except the agent is supposed to pause for 3 seconds as soon as the player steps inside the 'suspicionDistance' but it doesn't -- it just comes straight to the player without a pause. I double checked the values for the various distance variables and they are all correct.
I'm thinking I must be misusing the WaitForSeconds method, but can't seem to figure out how to go about making it work.
===== **(UPDATE)** =====
For anyone who's interested, here's my solution that seems to work:
IEnumerator ResolveSuspicion(float duration) {
agent.Stop();
feelingSuspicious = true;
yield return new WaitForSeconds(duration);
float distanceToPlayer = CheckDistance();
if (distanceToPlayer < suspicionDistance) {
chasingPlayer = true;
} else {
agent.Resume();
}
}
void Update() {
distanceToPlayer = CheckDistance();
if (distanceToPlayer < suspicionDistance) {
if (!chasingPlayer) {
StartCoroutine(ResolveSuspicion(3.0f));
} else {
agent.destination = player.transform.position;
agent.Resume();
}
....
} else {
if (feelingSuspicious) {
feelingSuspicious = false;
agent.Resume();
}
}
}
↧
NavMesh Agent, model falls over
Navmesh agent help. When ever I add a navmesh agent to my monster models in unity, they just fall over when I demo the game. why is this?
↧
↧
Keeping NavMeshAgent in sync with the object it controls
As of Unity 5, NavMeshAgent seems to ignore the current position of the object it's attached to, instead updating its position based on where it thinks it would be if it was the only thing controlling the object's position by moving it directly.
![alt text][1]
(the cylinder is where NavMeshAgent thinks it is)
This is obviously unworkable for a million different reasons. What can I do about this? Is there some way to reactivate the old behavior from Unity 4 where it calculated its position based on where it actually was, or failing that, some way to set its position manually?
[1]: http://i.imgur.com/miEjYW3.gif
↧
Navigation and Animation
Hello right now im using unity 5 and i have a simple script that uses the velocity of the nav agent to play a different set of animations (Legacy) it works alright, BUT if i bake the nav mesh with a height mesh it stops working.
Here is the code:
void Update ()
{
if (navAgent.velocity.magnitude > 0)
{
anim.CrossFade("Warlock_Run");
}
if (navAgent.velocity.magnitude == 0)
{
anim.CrossFade("Warlock_Standing_Free");
}
}
So i call a debug.log to see what the velocity was without a height mesh and it returns 0 when stoped. (Works right) but it returns a lot of numbers different every frame when baked a height mesh even if the object is stoped, the velocity returns something (high value like 5.2, 4.1, 8.3 etc) So if the agent does stop why the velocity is high.
Also using vector3 distance could fix it but i need to use the speed (will have different set of animations based on the speed)
Is this a bug or im doing something terrible wrong?
↧
NavMeshAgent following path using cardinal directions
So I tried to make a NavMeshAgent follow a path using only the four cardinal directions. To do this, I'm snapping the vector of NavMeshAgent.desiredVelocity to the one cardinal vector it is closest to and then assign it to NavMeshAgent.velocity. It works quite fine.
The problem is going around corners, when desiredVelocity gets close to a 45 degree angle. Then it ends up in a zig-zag movement.
Is there a way to avoid this?
Thanks for your answers ;)
↧
Any way to set NavMeshAgent.walkableMask in script with more than 7 user layers?
Hi,
I have up to 9 NavMeshAgents in a scene. On my NavMesh, each agent walks on a base layer, and one other layer which is specific to that agent, giving each agent a part of the NavMesh which only they can traverse.
My problem comes when trying to apply the NavMeshAgent.walkableMask in script, which needs to be set as a bitmask. Layers 10 and above become impossible to apply in script due to hitting the int ceiling.
For example adding layers 3 & 0 to the layer mask:
Layer 3 = 8, Layer 0 = 1, therefore 8 + 1 = 9, in binary = 1001
navMeshAgent.walkableMask = 1001;
This is fine, but when we reach layer 10 things get a bit tricky:
Layer 10 = 1024, Layer 0 = 1, therefore 1024 + 1 = 1025, in binary = 10000000001
navMeshAgent.walkableMask = 10000000001;
The problem is that 10000000001 is too large for an int, but WalkableMask needs to take an int as a bitmask.
So how does one go about adding a combination layer mask for anything higher than layer 9?
Thanks,
Woody
↧
↧
Mesh as Navmesh?
Is it possible to use a mesh of a moveable object (e.g. platform, spaceship) as navmesh? All I need is a way to put a mesh into an array of local positions so child objects can move like they would on a baked navmesh. I would like to use unitys NavMeshAgent if possible.
↧
Any way to make Nav Mesh Agents not collide?
Hello all.
Firstly, I've been learning how to use Unity for 2 weeks now and I have to say thank you to all of the people who write in this forum. You've already helped me more than you know.
I'm trying to make a game with multiple enemies making their way through a maze. Most of these ignore the player and just go about their business. The thing is that I want them to be able to collide with the player and walls but not with each other.
I've followed the instructions in [this link][1] but it doesn't seem to work. (The link outlines putting objects that you don't want to collide with each other on the same layer and then using the collision matrix to stop them from colliding with each other. It didn't work.)
Does anyone have an answer?
Thank you.
[1]: http://answers.unity3d.com/questions/416498/make-2-object-not-collide.html
↧
Stop Navmeshagent from sliding
Okay, so I've seen that I can sort of stop a Navmeshagent from sliding by giving it a really high acceleration, but it makes the movement of my character look ridiculous. Is there a way I can immediately stop a Navmeshagent? I've tried simply disabling it, but when I do it slides after reactivating. That might be from other Navmeshagents pushing on it, but I'm not sure. Any help would be great. :)
↧
Why does some NavMeshAgents start to move late?
Hi,
I'm trying to move 400 NavMeshAgents at the same time in a game like Galcon.
My problem is that they starts moving in different times even when the command is given out at the same time. Some of them starts to move very late, it looks like they are waiting for something.
![alt text][1]
The "COMMAND: X" show that all the agents received the setDestination command.
**Is there a setting I should change or why does this happen?**
[1]: /storage/temp/45424-game1.png
↧
↧
Can NavMeshAgent navigate tight mazes?
Hello.
I'm using NavMeshAgent to make objects navigate through a maze. I'm having an issue with speed, however. Whenever I increase the speed of the NavMeshAgents I'm finding that rather than slow down to take the corners they just bump and bounce off the walls.
I have searched the forums for an answer and haven't found one. I've tried adjusting the Speed, Angular Speed, Acceleration and Stopping Distance in every permutation I can think of trying to stop the objects from bouncing but to no avail.
Is this a known issue or am I missing something?
Thank you!!
↧
Navmesh Path is shown even between disconnected regions.?
I have taken a sample scene to describe my problem here. I have simply created 2 disconnected regions and my source point is in first region(bigger cube) and destination point is in second region(smaller cube). actually due to wall in between I should not get path between these two points. but when I call navmeshagent.calculatepath, I still get a path between these and also I get navmeshagent.pathStatus true.
have I missed anything. thanks in advance.![alt text][1]
[1]: /storage/temp/45904-screen-shot-2015-05-06-at-40620-pm.png
↧
Player "teleports" on top of NavMeshAgent collider if the Agent is too close
hey guys,
I'm using the Unity NavMesh on Unity 5.0.1f1 and I have the problem that my player (which is controled by a PlayerController) teleports on top of a NavMeshAgent if the agent is too close to the player. I need the agent (my enemy) to be very close to the player, so the attack hits the player.
If the enemy stands still, the player can not walk on top of it. But if the player stands still and the enemy approch the player then the player is teleporteted on top of the enemy collider, regardless of its height. That happens also when the "Slope Limit" and "Step Offset" in the character controller is 0.
The enemy has a kinemetic rigidbody and a static boxcollider attached. The player has the playercontroller attached.
I've also attached a navmesh agent, for testing, to the player but then I can't jump and run across areas that are marked as "not Walkable" for the enemys.
Do you know how to fix this problem?
↧
Player's last location as a Transform
So I have my AI moving around my scene using a NavMesh.
If order for the AI to move around it needs a target that is a Transform.
Obviously the Player is the target, but I would like for the player to have the ability to disappear making the AI search in he players last known location.
I assume this can be done by having the AI raycast save the Vector3 of the gameobject with the tag "player" in a variable, then run a method that would have the AI "scan" in and around said area as my AI "sees" with raycasts.
If I'm right, awesome. I just cannot think of how to do it.
Currently I use these two methods to trick the AI in to stop persuit when it sees a certain tag (I also assume that this is not the best way to do this)
public bool CanSeePlayer()
{
RaycastHit hit;
Vector3 rayDirection = Player.transform.position - transform.position;
if ((Vector3.Angle(rayDirection, transform.forward)) <= fieldOfViewDegrees * 1f)
{
// Detect if player is within the field of view
if (Physics.Raycast(transform.position, rayDirection, out hit))
{
return (hit.transform.CompareTag("Player"));
}
}
return false;
}
public bool CanSeeObject()
{
RaycastHit hit;
Vector3 rayDirection = Player.transform.position - transform.position;
if ((Vector3.Angle(rayDirection, transform.forward)) <= fieldOfViewDegrees * 0.5f)
{
// Detect if player is within the field of view
if (Physics.Raycast(transform.position, rayDirection, out hit))
{
return (hit.transform.CompareTag("Object"));
}
}
return false;
}
So it's implemented as:
//If tag check = Object, transition to search state
if (npc.GetComponent().CanSeeObject())
{
npc.GetComponent().target = null;
Debug.Log("Switch to Search State");
npc.GetComponent().SetTransition(Transition.LostPlayer);
}
And the opposite in other States:
//If player seen, switch to chase.
if (npc.GetComponent().CanSeePlayer())
{
npc.GetComponent().target = player;
Debug.Log("Switch to Chase State");
npc.GetComponent().SetTransition(Transition.SawPlayer);
}
What I want is that if CanSeeObject()becomes true, that the AI would take the Vector3 of what CanSeePlayer() was and move on it's own in a certain area "scanning" with CanSeePlayer() from left to right until it sees the player, of course if Player is not found then I just want the AI to wander around randomly until CanSeePlayer() is true again.
↧
↧
How to let a navMeshAgent detect if path is blocked by an obstacle?
How can I detect if a navMesh agent can reach a destination that is blocked by an Obstacle?
I have a level where it is already baked to a navMesh, I am using navMesh Obstacles as well. I need the obstacles to prevent the agents from going further in the path, when I give an agent a destination that's blocked by an obstacle the agent tries to reach it but it can't. I would like to let the agent detect that its current destination can't be reached so it doesn't even try.
Thanks
↧
Why do my Navmesh Agents pop through the center axis of the mesh?
I have a simple plane that I've generated a mesh for and two capsules with Navmesh agents attached. They move around just fine, but when moving right along the Z-Axis or X-Axis (Which are lined up with the Global Z and X Axis) the capsules will glitch up and down but still move for the most part. Occasionally they will full glitch out.
I get this error on the camera, but I'm not really surprised by this one.
> Screen position out of view frustum> (screen pos 917.000000, 802.000000)> (Camera rect 0 0 982 552)> UnityEngine.Camera:ScreenPointToRay(Vector3)> PlayerController:RotatePlayer(Single,> Single) (at> Assets/Scripts/PlayerController.cs:61)> PlayerController:PlayerMovement(Single,> Single) (at> Assets/Scripts/PlayerController.cs:39)> PlayerController:FixedUpdate() (at> Assets/Scripts/PlayerController.cs:29)
[Here's a video I made to demonstrate what is happening.
][1]
The Capsules have Navmesh Agent components and Rigidbodies. Here is the code I use to move the player.
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour
{
private int jumpState = 0;
public float speedScale = 1f;
public float jumpHeight = 1f;
// public float turnSmoothing = 15f;
private bool isGrounded;
private Rigidbody rb;
// Use this for initialization
void Start ()
{
rb = GetComponent();
}
// Update is called once per frame
void FixedUpdate ()
{
// Horizontal movement
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
PlayerMovement(x, z);
}
void PlayerMovement(float h, float v)
{
if(h != 0f || v != 0f)
{
MovePlayer(h, v);
}
RotatePlayer(h, v);
if(Input.GetButton("Jump") && (jumpState < 10))
Jump();
}
void MovePlayer(float h, float v)
{
Vector3 targetPos = new Vector3(h * speedScale, 0f, v * speedScale);
rb.MovePosition(transform.position + (targetPos * Time.deltaTime));
}
void RotatePlayer(float h, float v)
{
/*
Vector3 targetDirection = new Vector3(h, 0f, v);
Quaternion targetRotation = Quaternion.LookRotation(targetDirection, Vector3.up);
Quaternion smoothedRot = Quaternion.Lerp(rb.rotation, targetRotation, (turnSmoothing * Time.deltaTime));
rb.MoveRotation(smoothedRot);
*/
// Create a ray from the mouse cursor on screen in the direction of the camera.
Ray camRay = Camera.main.ScreenPointToRay (Input.mousePosition);
// Create a RaycastHit variable to store information about what was hit by the ray.
RaycastHit floorHit;
// Perform the raycast and if it hits something on the floor layer...
if(Physics.Raycast (camRay, out floorHit, 300f, 1 << 8))
{
transform.LookAt(new Vector3(floorHit.point.x, transform.position.y, floorHit.point.z));
}
}
void Jump()
{
rb.AddForce(Vector3.up * jumpHeight);
if(!isGrounded)
jumpState++;
}
void OnCollisionEnter(Collision collision)
{
if(collision.gameObject.tag == "Ground")
{
isGrounded = true;
jumpState = 0;
}
}
void OnCollisionExit(Collision collision)
{
if(collision.gameObject.tag == "Ground")
isGrounded = false;
}
}
[1]: https://youtu.be/_fQKIEq9hzg
↧
raycast hit not detecting && Nav mesh agent ai stealth
Hello, I'm trying to make patrol ai that detects a player within its field of view then moves to that players last known position and looses track of player once the player is out of sight. The script I have works fine in pathfinding the waypoints I set when it is searching for the player, but completely ignores the player. The sphere collider is marked trigger and proper public variables are set in the inspector, please help.
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(AudioSource))]
public class StealthAI : MonoBehaviour {
public float fieldOfViewAngle = 110f; // Number of degrees, centred on forward, for the enemy see.
public bool playerInSight = false; // Whether or not the player is currently sighted.
public Vector3 personalLastSighting; // Last place this enemy spotted the player.
public GameObject player; //Player Target
public string tagofcollider = "Player";
public Light lt; //Search Light Attatched to Object
public float dirchangefrequency = Random.Range(3,14); //How often the Ai finds new waypoint when wandering
public Transform waypt1; //Waypoint 1
public Transform waypt2; //Waypoint 2
public Transform waypt3; //Waypoint 3
public Transform waypt4; //Waypoint 4
private NavMeshAgent agent; // Reference to the NavMeshAgent component.
private SphereCollider col; // Reference to the sphere collider trigger component
private float StoppingDistance = 3.5f; //How close till faliure state
private float timetillchange = 0; //timer affected by time.deltatime DO NOT CHANGE VALUE FROM 0
private bool changingdir = false; //Is changedir being called?
private Transform Waypoint; //Current wandering waypoint being set
private float cooldowntime;
void Start () {
player = GameObject.FindWithTag ("Player");
agent = GetComponent ();
lt = GetComponent ();
playerInSight = false;
cooldowntime = dirchangefrequency;
}
void OnTriggerStay (Collider other){
// If the player has entered the trigger sphere...
if(other.gameObject.tag == tagofcollider){
// By default the player is not in sight.
playerInSight = false;
// Create a vector from the enemy to the player and store the angle between it and forward.
Vector3 direction = other.transform.position - transform.position;
float angle = Vector3.Angle(direction, transform.forward);
// If the angle between forward and where the player is, is less than half the angle of view...
if(angle < fieldOfViewAngle * 0.5f){
RaycastHit hit;
// ... and if a raycast towards the player hits something...
if(Physics.Raycast(transform.position - transform.up, direction.normalized, out hit, col.radius)){
// ... and if the raycast hits the player...
if(hit.collider.gameObject.tag == tagofcollider){
// ... the player is in sight.
playerInSight = true;
agent.speed = 8;
// Set the last global sighting is the players current position.
personalLastSighting = player.transform.position;
}
}
}
}
}
void OnTriggerExit (Collider other){
// If the player leaves the trigger zone...
if(other.gameObject.tag == tagofcollider)
// ... the player is not in sight.
playerInSight = false;
}
void Update (){
Vector3 forward = transform.TransformDirection(Vector3.forward) * 45;
Debug.DrawRay(transform.position-transform.up, forward, Color.green);
//check if changin Dir at the moment, if not add to timer
if(!changingdir && playerInSight == false){
timetillchange += Time.deltaTime;
}
//when timer reaches # seconds, call Dir Change function
if(timetillchange >= dirchangefrequency){
StartCoroutine(ChangeDir());
}
float dist = Vector3.Distance(player.transform.position, transform.position);
if (playerInSight = true) {
agent.SetDestination (personalLastSighting);
}
else if (dist < StoppingDistance) {
agent.Stop();
lt.intensity += 2;
GetComponent ().Play ();
Invoke("Restart",1);
}
else if (dist > StoppingDistance)
lt.intensity = 1;
}
void Restart (){
Application.LoadLevel (Application.loadedLevel);
}
IEnumerator ChangeDir(){
changingdir = true;
timetillchange = 0;
int randomPick = Random.Range(0,5);
if(randomPick == 1)
Waypoint = waypt1;
else if(randomPick == 2)
Waypoint = waypt2;
else if(randomPick == 3)
Waypoint = waypt3;
else if(randomPick == 4)
Waypoint = waypt4;
yield return new WaitForSeconds (cooldowntime);
agent.speed = 3;
agent.SetDestination (Waypoint.position);
changingdir = false;
}
}
↧