How to stop NavMeshAgent separating from Animator? - unity3d

I am working on a research project that uses a NavMeshAgent. I currently have a very simple scene where an agent is spawn at the start, walks through an "entrance" trigger collider, an "exit" trigger collider, then ultimately collides with a "destroyer" trigger collider with a script that ends the scene. Nothing complex, no physics collisions should be occurring.
I've been running some simulations both in the editor and in -batchmode -nographics via an executable that logs a basic runtime statistic when the scene ends. I found that in both the Unity editor and the CLI execution that occasionally the scene's execution time would spike. I finally caught what was happening in action- the NavMeshAgent component was becoming detached from my agent and floating out in front of it.
In this picture you can see the two colliders on the agent (one very small through his body for physics and one larger one for his "personal space",) the exit trigger collider (the giant red box on the right,) and floating between the two is a capsule-shaped NavMeshAgent component.
I used this unity page detailing how to use NavMeshAgents with animators, but after recreating their recommended setup, I am still having the issue.
Does anyone have any solutions for anchoring the NavMeshAgent to the agent itself?

I met exactly the same problem, where making the NavMeshAgent component a child and setting the NavMeshAgent's local position in every frame solved the problem.
private NavMeshAgent agent;
void Awake()
{
agent = gameObject.GetComponentInChildren<NavMeshAgent>();
anim = gameObject.GetComponent<Animator> ();
}
private void Update()
{
agent.transform.localPosition = Vector3.zero;
// todo:
// set animator
}
void OnAnimatorMove ()
{
// Update position to agent position
transform.position = agent.nextPosition;
}

For those of you who stumbled here, but for whom the accepted answer did not work. Make sure that navMeshAgent.updatePosition is set to true or that it is not changed within a script. This could be the cause of the separation.
NavMeshAgent navMeshAgent;
// This may cause the agent to separate
navMeshAgent.updatePosition = false;
// This will make sure it is synced
navMeshAgent.updatePosition = true;
This works as of version 2022.1 of the Unity API. Here are the docs for the function : https://docs.unity3d.com/ScriptReference/AI.NavMeshAgent-updatePosition.html

Related

Why 'Is Kinematics' works different on HoloLens?

Overview
I wanted to have a cube, that I can drag around the scene with the components Collider, Rigidbody and ObjectManipulator. In play mode everything works fine, but running it on the hololens, the cube starts flying around after dragging it a few time.
Steps to reproduce (All components are set via editor, not via code)
Create new project and set it up for AR/HoloLens
Import MRTK 2.4
Create cube with a Box Collider. Set Is Trigger = true
Add Rigidbody to cube. Set Use Gravity = false and Is Kinematic = true
Add Object Manipulator to cube. I have a method getting called after On Manipulation Ended, but don't know if thats important.
Expected behavior
The rigidbody is set to Is Kinematic = true and Use Gravity = false, so that the cube stays still/stops moving after releasing dragging it. This works while trying it inside the unity play mode. But running it on the hololens, the cube behaves like Is Kinematic = false and starts flying around after interacting with it. Sometimes after the second drag and sometimes after the third time drag.
Error
Before updating this post, I didnt noticed the development console in left corner of my hololens. At the beginng of the scene I get the message [Physics.PhysX] BV4 midphase only supported on intel platforms but at that moment everything is fine. As the cube begins to fly around I get the a NullReferenceExeption: Object reference not set to an instance of an object.
I fixed my issue. I know the approximate cause, but I do not fully understand it. The method, getting called after OnManipulationEnded caused that.
I have a list, getting filled and drained by OnTriggerEnter/-Exit (exit looks the same, except add→remove):
private void OnTriggerEnter(Collider other){
if (other.gameObject.layer != 31) return;
_objectsCollidingWith.Add(other.gameObject);}
OnManipulationEnded triggered this method:
private int GetMeshes(List<KeyValuePair<Transform, Mesh>> transMeshes){
foreach (GameObject go in _objectsCollidingWith)
{
transMeshes.Add(new KeyValuePair<Transform, Mesh>(go.transform , go.GetComponent<MeshFilter>().mesh));
}
return transMeshes.Count;}
So I got alot of nullreferences from GetMeshes, because some gameobject in the list _objectsCollidingWith were null. Thats because the mesh is getting updated every once in a while. That caused a lot of nullreferences until the cube just flew away.
I used the whole time the logging provider via the device portal and couldnt see what is causing this errors. But after running the project via holographic emulation I could see in the console where they were coming from.
How did I fixed my problem?
I found this post because I realized that my OnTriggerExit didn't get called and cased having null objects and some spatial meshes with the same name triggered OnTriggerEnter very often. Also I added this line in the foreach loop in GetMeshes because once in a while there is still a null object:
if (go == null)
continue;
PS: Please forgive the strange code formatting, somehow the editor here on so does not allow me to place the brackets somewhere else

Unity: OnCollisionEnter fires only on NEW entry, but not on NEW entry on different object with same name

I am building a platformer with appearing boxes. The box gets rendered as soon as the player hits it hitbox. This works just fine like so:
public class AppearingBoxes : MonoBehaviour
{
public GameObject Block, RageFace;
bool showBlock = false;
void Start()
{
showBlock = false;
}
void OnCollisionEnter(Collision2D col)
{
if (col.gameObject.name == "Birdy")
{
showBlock = true;
}
}
void FixedUpdate()
{
Block.GetComponent<Renderer>().enabled = showBlock;
RageFace.GetComponent<Renderer>().enabled = showBlock;
}
}
This script is attached to all of those boxes. Each box is an individual box but all with the same script and properties and name:
But here comes the issue. Only the first HIT triggers a box. As you can imagine, the player jumps on top of those invisble boxes and then triggers the one he hits. The player now moves forward over the other boxes that are still invisble and enters there hitboxes. However they dont appear. I believe this is due to the fact that the player is still in the "same" hitbox even though it is a different prefab object. If I jump ontop of the invisible platform and then fall back down to it (i left and then reentered the trigger) the box on which I land immeadiately appears as it should.
So what can I do to get the box to appear as soon as the player touched it even though he is has not left the hitbox of the box before?
Thank you! :)
Try to change the boxes colliders to isTrigger and use instead OnTriggerEnter2D
Or maybe it's because you use OnCollisionEnter instead of OnCollisionEnter2D ?
There is a problem in your code. I don't know if you missed that or it is a typo but you can not use OnCollisionEnter with a Collision2D parameter. Your game would run but it must be giving you this error message:
Script error: OnCollisionEnter
This message parameter has to be of type: Collision
The message will be ignored.
Use OnCollisionEnter2D instead
void OnCollisionEnter2D(Collision2D col)
{
if (col.gameObject.name == "Birdy")
{
showBlock = true;
}
}
Everyone, I did find a "workaround" It sill doesnt really explain the issue but alreast works...
What I did was to increase the size of the BoxCollider for every box just a little bit more. Like 3 pixels bigger than the actual box the player stands on. This solved the issue but makes me wonder: If the player didnt "really" collide with the collider in the first place he wouldve fallen through. But he didnt. Now the colliders a slightly bigger and everything gets triggered just perfect. Maybe a bug in the engine?
Thanks for all your help
He didn't fall because the collider isn't Trigger that's all.

Add particles on button click in unity

I am new to unity 3d, I have to do some enhancement in exiting project.. if user choose correct option then I have to show some particles around the button at runtime.
My code for adding particles is below ..not working:
ParticleSystem ps = GetComponent<ParticleSystem>();
ps.Play ();
I have also added particles component from unity editor..
Thanks in advance
Edit :
as #kardux suggested:
declaration :
[SerializeField] private ParticleSystem ps;
on method :
ps.Play()
Screenshot from inspector:
Error:
I/Unity (23313): NullReferenceException
I/Unity (23313): at UnityEngine.ParticleSystem.<Play>m__0 (UnityEngine.ParticleSystem ps) [0x00001] in /Users/builduser/buildslave/unity/build/artifacts/generated/common/modules/ParticleSystem/ParticleSystemBindings.gen.cs:3666
I/Unity (23313): at UnityEngine.ParticleSystem.IterateParticleSystems (Boolean recurse, UnityEngine.IteratorDelegate func) [0x00003] in /Users/builduser/buildslave/unity/build/artifacts/generated/common/modules/ParticleSystem/ParticleSystemBindings.gen.cs:3780
I/Unity (23313): at UnityEngine.ParticleSystem.Play (Boolean withChildren) [0x00020] in /Users/builduser/buildslave/unity/build/artifacts/generated/common/modules/ParticleSystem/ParticleSystemBindings.gen.cs:3666
I/Unity (23313): at UnityEngine.ParticleSystem.Play () [0x00005] in /Users/builduser/buildslave/unity/build/artifacts/generated/common/modules/ParticleSystem/ParticleSystemBindings.gen.cs:3661
First of all if you're using particles inside Unity UI I highly advise you looking to UIParticleSystem.cs script from Unity UI Extension repository: this is a community gathering of many useful UI tools :)
(simply don't forget to add the UI/Particles/Hidden shader that you can find here)
You can change the sprite you want to use here:
Also keep in mind when using this script that you will have to scale your particles according to your screen (particles are initialized at a size of 1 because that's 1 meter in Unity 3D world: but now you will probably be in canvas space which will be something like 1920x1080px so 1px will be very small). You can find some base settings below:
Now coming to your scrip I suspect you simply have to call Stop() before Play() like this (note I used a burst emission type in my particle system settings):
ParticleSystem ps = GetComponent<ParticleSystem>();
ps.Stop ();
ps.Play ();
P.-S. Please note that if you use UIParticleSystem script you will have to consider your particles system as an UI item (will be rendered on top of other items based on hierarchy order)
Hope this helps,
EDIT:
You have two ways of setting up your GameObjects:
you have all component on the same GameObject (ParticleSystem, UIParticleSystem and YOUR_SCRIPT): this way you can get the ParticleSystem reference by calling GetComponent<ParticleSystem>() inside your script
you have one particle GameObject (with ParticleSystem and UIParticleSystem) and YOUR_SCRIPT is on another GameObject: you can't call GetComponent<ParticleSystem>() in your script since it will search on the components of this GameObject so you declare a ParticleSystem ps; variable (either public or [SerializeField] private) that you assign through the Inspector by dragging your particle GameObject to it.
Note that implicitly, GetComponent<ParticleSystem>() equals this.gameObject.GetComponent<ParticleSystem>(): that's why it will search components from the current GameObject.
EDIT 2:
Not sure why your script throw this NullReference exception: I just tried with a very short script and it works perfectly...
public class TestScript: MonoBehaviour
{
[SerializeField]
private ParticleSystem ps;
void Start()
{
// This one is not even needed
ps.Stop();
}
public void PlayParticles()
{
ps.Stop();
ps.Play();
}
}
Provided you have a particle system on the same gameObject as the script that is calling it, it should be fine.
Are you using a UI button? If so, have a look here..
http://answers.unity3d.com/questions/852397/particle-system-in-46-ui.html
It's old but still relevant.
Are you using the New Unity UI System or GUI, Is the UI worldspace?
Create a empty gameobject - attach the particle to that.
Whenever you want emit particles call Gameobject.SetActive(true);
Make sure Play on Awake option is checked in the particle system.
Set the position of the particle according to your UI.
public GameObject particle;
//include the particle in the gameobject
void Start() {
particle.SetActive(false);
}
void button() {
particle.SetActive(true);
}
//this works.

How do I use SteamVR_LoadLevel to fade between scenes in unity3d?

I've got this at the top,
public GameObject mainCamera
and then I've got this within an if statement,
SteamVR_LoadLevel tempload = mainCamera.GetComponent<SteamVR_LoadLevel>();
tempload.fadeOutTime = 1f;
tempload.fadeInTime = 1f;
tempload.Trigger();
but I'm getting this error when triggering the if statement,
Coroutine 'LoadLevel' couldn't be started because the the game object 'Camera (head)' is inactive!
Edit 1. I figured it out, I should have made the mainCamera variable of type SteamVR_Camera and I should have nullchecked it as well as tested for it being active and enabled.
Check state game object "Camera (head)" in hierarchy window and active him

How to disable a collider when the trigger of another collider has been entered?

I am building a game where the player runs on a path. When the player triggers a collider, 2 enemy objects will spawn.
What I want is when the first collider trigger has been entered, I want the second collider, which is at a certain distance from the first collider, to get disabled for a certain time. How to achieve this?
If you'd like to disable the colliders so they won't hit or rebound off the wall, for example, then you can change your collider's "isTrigger" variable to true, to change it into a trigger volume instead of a solid collider. This has the effect of disabling it - in that it won't cause other objects to stop or rebound if they hit it.
For example:
function Update() {
if (Input.GetKeyDown(KeyCode.X)) {
collider.isTrigger = true;
}
}
Note that things like MouseOver still work.
If you want to disable that completely, you can try collider.enabled = false. I'm not sure if that works or not. If it doesn't, you can always scale down your collider:
var myOldSize:Vector3;
function DisableBoxCollider(myCollider:BoxCollider)
{
//actually just resizes it
myOldSize=myCollider.size;
myCollider.size=Vector3(0,0,0);
}
function EnableBoxCollider(myCollider:BoxCollider)
{
if(myOldSize!=Vector3(0,0,0))
myCollider.size=myOldSize;
}
You can use the above code to integrate it in your own project. I'm not going to spill out all of the code for you because else we'd miss the point of learning to program and post on Stackoverflow in general. But it should help you to get on your way. Try and play some with the code, and if you have questions, get back here and ask them, providing the question with some code to show what you have tried.