Facepunch / sbox-issues

175 stars 12 forks source link

Add a Navgen system/component to Scene (So we can use ModelColliders for navgen instead of a Map Instance) #4315

Closed CarsonKompon closed 7 months ago

CarsonKompon commented 8 months ago

For?

S&Box

What can't you do?

I'm unable to build a world out of ModelRenderers and ModelColliders while using a Navmesh. I can seemingly only use the Map Instance component when using a Navmesh.

How would you like it to work?

It would be nice if there was one component that allowed you to specify either a tag or series of tags and will generate a navmesh based on those objects and have helper functions to interface with it directly (and even update it in real-time if we wanted)

What have you tried?

I tried creating the following component which runs Scene.PhysicsWorld.SetupPhysicsFromModel on all ModelColliders tagged with "navmesh":

public sealed class NavmeshComponent : Component
{
    public static NavmeshComponent Instance { get; private set; }
    public NavigationMesh NavMesh { get; private set; }

    protected override void OnStart()
    {
        Instance = this;

        if ( !Scene.Active || !Scene.PhysicsWorld.IsValid() )
            return;

        GenerateMesh();
    }

        protected override void OnUpdate()
    {
        if ( NavMesh is null ) return;

        using ( Gizmo.Scope( "navmesh" ) )
        {
            Gizmo.Draw.Color = Color.Blue;
            Gizmo.Draw.LineNavigationMesh( NavMesh );
        }
    }

    void GenerateMesh()
    {
        foreach ( var modelCollider in Scene.Components.GetAll<ModelCollider>( FindMode.EnabledInSelfAndDescendants ) )
        {
            if ( !modelCollider.Tags.Has( "navmesh" ) ) continue;

            Scene.PhysicsWorld.SetupPhysicsFromModel( modelCollider.Model, modelCollider.Transform.World, PhysicsMotionType.Static );

        }

        NavMesh = new();
        NavMesh.Generate( Scene.PhysicsWorld );
        Log.Info( $"Generated navmesh... Node count: {NavMesh.Nodes.Count}" );
    }

    public List<NavigationPath.Segment> GeneratePath( Vector3 point1, Vector3 point2 )
    {
        if ( NavMesh is null )
        {
            GenerateMesh();
        }

        var path = new NavigationPath( NavMesh );
        path.StartPoint = point1;
        path.EndPoint = point2;
        path.Build();

        return path.Segments;
    }
}

This runs successfully, but the Gizmo drawn in the OnUpdate only shows a navmesh generated for one of the colliders in the hierarchy (or a weird combination of them all? It's hard to tell since some do not line up with the colliders they display...)

The following screenshot shows all 3 ModelColliders selected in the inspector (drawn in green) with the generated navmesh being drawn in Blue (only showing over ground_center_02) image

Additional context

No response

CarsonKompon commented 8 months ago

Was torn between making this a feature request and a bug report. I think a navgen component would be much nicer are be more intuitive to use, but if I'm simply encountering a bug with navgen generation with multiple meshes then I can live with writing a custom navgen component for all my games.

dch-GH commented 8 months ago

When I modify my NavmeshComponent test to include ModelColliders like you have, calling

Scene.PhysicsWorld.SetupPhysicsFromModel( m.Model, m.Transform.World, PhysicsMotionType.Static );

actually causes sbox to hang for a while. :c Does that happen for you as well? It does eventually become responsive again though. This is with only 1 ModelCollider in the entire scene by the way, not dozens or hundreds.

CarsonKompon commented 8 months ago

When I modify my NavmeshComponent test to include ModelColliders like you have, calling

Scene.PhysicsWorld.SetupPhysicsFromModel( m.Model, m.Transform.World, PhysicsMotionType.Static );

actually causes sbox to hang for a while. :c Does that happen for you as well? It does eventually become responsive again though. This is with only 1 ModelCollider in the entire scene by the way, not dozens or hundreds.

This is not the case for me. It only hangs for less than a second for me. I tried messing with your navmesh test repo a bit before I made this post. If you make any progress let me know :)

garrynewman commented 8 months ago

I'm gonna completely re-make the navigation system quite soon.. so will keep this in mind when I do that.