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

Static navigation obstacles have no height/elevation #84817

Closed
Scony opened this issue Nov 12, 2023 · 0 comments · Fixed by #84830
Closed

Static navigation obstacles have no height/elevation #84817

Scony opened this issue Nov 12, 2023 · 0 comments · Fixed by #84830

Comments

@Scony
Copy link
Contributor

Scony commented Nov 12, 2023

Godot version

4.2.dev [9df6491]

System information

Linux Manjaro

Issue description

In the project I'm working on, I have 2 flat (Y is constant) navigation maps:

  1. terrain (Y=0)
  2. air (Y=1.5)

I've recently added some static obstacles at the navigation map edges that act as "walls" preventing units from leaving the maps:
lampe-games/godot-open-rts@8c3b090

Interestingly, the obstacles work for the terrain map (Y=0) while not for the air map (Y=1.5).

After inspecting the code and writing exploratory test cases, I've concluded that height/elevation is not implemented for static obstacles and therefore it's currently not possible to add static obstacles to my air map (Y=1.5).

Steps to reproduce

Create & run the following test case in tests/servers/test_navigation_server_3d.h using e.g. time scons -j$(nproc) tests=yes debug_symbols=yes optimize=debug && ./bin/godot.linuxbsd.editor.x86_64 --test --test-suite="*Navigation*" command:

	TEST_CASE("[NavigationServer3D] Server should make agents avoid elevated static obstacles when avoidance enabled") {
		NavigationServer3D *navigation_server = NavigationServer3D::get_singleton();

		RID map = navigation_server->map_create();
		RID agent_1 = navigation_server->agent_create();
		RID agent_2 = navigation_server->agent_create();
		RID obstacle_1 = navigation_server->obstacle_create();

		navigation_server->map_set_active(map, true);

		navigation_server->agent_set_map(agent_1, map);
		navigation_server->agent_set_avoidance_enabled(agent_1, true);
		navigation_server->agent_set_position(agent_1, Vector3(0, 10, 0));
		navigation_server->agent_set_radius(agent_1, 1.6); // Have hit the obstacle already.
		navigation_server->agent_set_velocity(agent_1, Vector3(1, 0, 0));
		CallableMock agent_1_avoidance_callback_mock;
		navigation_server->agent_set_avoidance_callback(agent_1, callable_mp(&agent_1_avoidance_callback_mock, &CallableMock::function1));

		navigation_server->agent_set_map(agent_2, map);
		navigation_server->agent_set_avoidance_enabled(agent_2, true);
		navigation_server->agent_set_position(agent_2, Vector3(0, 10, 5));
		navigation_server->agent_set_radius(agent_2, 1.4); // Haven't hit the obstacle yet.
		navigation_server->agent_set_velocity(agent_2, Vector3(1, 0, 0));
		CallableMock agent_2_avoidance_callback_mock;
		navigation_server->agent_set_avoidance_callback(agent_2, callable_mp(&agent_2_avoidance_callback_mock, &CallableMock::function1));

		navigation_server->obstacle_set_map(obstacle_1, map);
		navigation_server->obstacle_set_avoidance_enabled(obstacle_1, true);
		PackedVector3Array obstacle_1_vertices;
		obstacle_1_vertices.push_back(Vector3(1.5, 0, 0.5));
		obstacle_1_vertices.push_back(Vector3(1.5, 0, 4.5));
		navigation_server->obstacle_set_vertices(obstacle_1, obstacle_1_vertices);
		navigation_server->obstacle_set_height(obstacle_1, 999);

		CHECK_EQ(agent_1_avoidance_callback_mock.function1_calls, 0);
		CHECK_EQ(agent_2_avoidance_callback_mock.function1_calls, 0);
		navigation_server->process(0.0); // Give server some cycles to commit.
		CHECK_EQ(agent_1_avoidance_callback_mock.function1_calls, 1);
		CHECK_EQ(agent_2_avoidance_callback_mock.function1_calls, 1);
		Vector3 agent_1_safe_velocity = agent_1_avoidance_callback_mock.function1_latest_arg0;
		Vector3 agent_2_safe_velocity = agent_2_avoidance_callback_mock.function1_latest_arg0;
		CHECK_MESSAGE(agent_1_safe_velocity.x > 0, "agent 1 should move a bit along desired velocity (+X)");
		CHECK_MESSAGE(agent_1_safe_velocity.z < 0, "agent 1 should move a bit to the side so that it avoids obstacle");
		CHECK_MESSAGE(agent_2_safe_velocity.x > 0, "agent 2 should move a bit along desired velocity (+X)");
		CHECK_MESSAGE(agent_2_safe_velocity.z == 0, "agent 2 should not move to the side");

		navigation_server->free(obstacle_1);
		navigation_server->free(agent_2);
		navigation_server->free(agent_1);
		navigation_server->free(map);
	}

Please note that neither navigation_server->obstacle_set_height(obstacle_1, 999); nor making obstacle 3D, vertical wall helps.

Minimal reproduction project

See test case above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants