Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unity editor Bake functions differently to scripted break. #41

Closed
darthmorf opened this issue Feb 15, 2021 · 7 comments
Closed

Unity editor Bake functions differently to scripted break. #41

darthmorf opened this issue Feb 15, 2021 · 7 comments
Assignees
Labels
bug Something isn't working

Comments

@darthmorf
Copy link

I'm developing some 2D isometric world generation logic using NavMeshSurface2d and NavMeshModifer scripts. So far, all the tile colliders have worked ok when baked with the script (calling NavMeshSurface2d.BuildNavMesh).

However, when adding a GameObject to the mix which has it's own polygon collider, the script call to bake the mesh does not include the gameobjects' colliders. When I generate the world, then press bake from the UI the colliders are baked fine.

Is there a reason it would work from the GUI but not scripted? Could it be a timing issue? Do I need to 'construct' the colliders somehow?

@h8man
Copy link
Owner

h8man commented Feb 15, 2021

Hello @darthmorf

There are a lot of #if UNITY_EDITOR declarations in scripts that I took form Unity's NavMeshSurface repo. So yes, it definitely can affect, probably, I don't know.

You can put break point or add logs to catch what sources are collected (also print polygon points to be sure):
line 169 - private static void CollectSources(List<NavMeshBuildSource> sources, NavMeshModifier modifier, int area, NavMeshBuilder2dWrapper builder)
Also be aware that colliders are taken only from child object to NavMesh or Grid (this feature are not implemented properly).
switch (CollectObjects)
{
case CollectObjects2d.Children: return new[] { parent };
case CollectObjects2d.Volume:
case CollectObjects2d.All:
default:
return new[] { GameObject.FindObjectOfType<Grid>().gameObject };
}

That is pretty much all I can advice in troubleshooting. But feel free to ask any related questions on further troubleshooting

@h8man h8man self-assigned this Feb 15, 2021
@h8man h8man added the bug Something isn't working label Feb 15, 2021
@GitFlip
Copy link

GitFlip commented Feb 16, 2021

Hi @h8man

I'm working with @darthmorf. About this point:

Also be aware that colliders are taken only from child object to NavMesh or Grid (this feature are not implemented properly).

Yeah, we found that out reading the forum post - it's not a problem for us in the end.

Now, I'd like to add some additional information to see if you have any more thoughts:

I actually noticed that this issue is not so much related to the fact that we're using a collider on a GameObject instead of a Tilemap, but rather it's based on how the sources are collected (or not collected) when we change the "Use Geometry " Setting of the NavMeshSurface2d.

Essentially, if we have it set to Render Meshes and apply a custom outline to our sprite, we get the correct number of Sources when we programmatically call BuildNavMesh();
On the contrast, if we have it set to Use Geometry, apply a custom physic shape to our sprite, add a collider, the object is not included in the Sources when we programmatically call BuildNavhMesh().

As Darthmorf said though, if we use the Bake button on the NavMeshSurface2d component it works correctly regardless of Render Meshes or Use Geometry set.

We'll try to work on getting that specific information you said as well:

You can put break point or add logs to catch what sources are collected (also print polygon points to be sure):
line 169 - private static void CollectSources(List sources, NavMeshModifier modifier, int area, NavMeshBuilder2dWrapper builder)

@GitFlip
Copy link

GitFlip commented Feb 16, 2021

I've got some more information after some debugging - sadly not sure yet what could be causing the problem.

First I'd like to correct a statement I had made:

Essentially, if we have it set to Render Meshes and apply a custom outline to our sprite, we get the correct number of Sources when we programmatically call BuildNavMesh();
On the contrast, if we have it set to Use Geometry, apply a custom physic shape to our sprite, add a collider, the object is not included in the Sources when we programmatically call BuildNavhMesh().

I don't think this was accurate. I do think we get the correct number of sources regardless of doing Render Meshes or Use Geometry, it's just that the Render Meshes generates more sources because it doesn't make use of the composite collider.

So, I tried to create a more simple use case and so this is what I have in my Hierarchy:

Grid Game Object
|-- Game Object with NavMeshSurface2D Component
|-- Tilmap Game Object with Tilemap Collider 2D, Rigidibody 2D, Composite Collider 2D, NavMeshModifier
|-- Tilemap Game Object (just using this as a parent for some Game Objects)
   |-- Game Object with Sprite Renderer, Polygon Collider 2D, NavMeshModifier
   |-- Game Object with same as above

Now, when I programmatically try to build the NavMesh via BuildNavMesh() This is what one of the Sources looks like from that method:
image

Instead, when I try to build the NavMesh via the Bake button, I noticed it fires off the UpdateNavMesh() method and this is what that same exact Source looks like:
image

There are clearly some discrepancies between the two, but you'll notice that the count of Sources is the same: 5 and the number of Vertices is the same for this Mesh I'm showing, but the points are different 🤔

Thanks if you're able to help us decipher what this means! 😅

@GitFlip
Copy link

GitFlip commented Feb 16, 2021

Ah okay, I may have just figured it out. When we programmatically call BuildNavMesh our Collider's bounds seem to be not set correctly:
image

While when it's called via the Bake button they are:
image

So if you agree that this could be causing the problem we're seeing, then maybe there is not bug in NavMeshPlus, but rather in the fact that our collider isn't "setup" correctly yet when we call BuildNavMesh

@h8man
Copy link
Owner

h8man commented Feb 16, 2021

Hello @GitFlip

There is one more place to take a look

line 44 - internal Mesh GetMesh(Collider2D collider)
line 55 - collider.CreateMesh(false, false)

It may return NULL without warnings. On this case we can ask directly to MelvMay on what is happening.

If you add delay between map generation and baking, does it help?

@GitFlip
Copy link

GitFlip commented Feb 17, 2021

Thanks for the suggestions @h8man.

I decided to take the approach of understanding why the collider is getting updated correctly at a later point and time, and ran into some good documentation about the collider's bounds not getting updated to match the transform until LateUpdate() is called.

How we were generating things was instantiating the prefab, setting the transform of this new game object, and eventually programmatically baking. This all happened then before LateUpdate() was called and so the collider's bounds were never updated even though the transform of the game object was.

To remedy this I simply forced the update by calling Physics2D.SyncTransforms() before calling BuildNavMesh().

FYI: https://docs.unity3d.com/ScriptReference/Physics2D.SyncTransforms.html

So I think that this issue can be closed, but maybe this info is worth mentioning somewhere? Not sure if you really need to though as it's a fundamental part of Unity Physics not NavMeshPlus.

Thanks again!

@h8man
Copy link
Owner

h8man commented Feb 17, 2021

@GitFlip ,

You certainly right. I getting more and more question about baking at runtime, so many other users may encounter this.
I will add this info to wiki

Wiki updated

Issue 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants