瀏覽代碼

Fix NavigationObstacle2D/3D get_global_transform() error

Fixes NavigationObstacle2D/3D reporting a 'get_global_transform: Condition "!is_inside_tree()" error when estimating the agent radius.

The collisionshapes that are lower in the SceneTree order than the obstacle node are not loaded in the SceneTree yet so the global_transform function fails.

Also adds warning message when this happens.

(cherry picked from commit cc707412e909f117ad53ebe53e19bad43acf086a)
smix8 3 年之前
父節點
當前提交
847fab6272
共有 2 個文件被更改,包括 12 次插入6 次删除
  1. 6 3
      scene/2d/navigation_obstacle_2d.cpp
  2. 6 3
      scene/3d/navigation_obstacle.cpp

+ 6 - 3
scene/2d/navigation_obstacle_2d.cpp

@@ -92,7 +92,7 @@ void NavigationObstacle2D::_notification(int p_what) {
 			parent_node2d = nullptr;
 		} break;
 		case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
-			if (parent_node2d) {
+			if (parent_node2d && parent_node2d->is_inside_tree()) {
 				Navigation2DServer::get_singleton()->agent_set_position(agent, parent_node2d->get_global_transform().get_origin());
 			}
 
@@ -155,13 +155,13 @@ void NavigationObstacle2D::reevaluate_agent_radius() {
 }
 
 real_t NavigationObstacle2D::estimate_agent_radius() const {
-	if (parent_node2d) {
+	if (parent_node2d && parent_node2d->is_inside_tree()) {
 		// Estimate the radius of this physics body
 		real_t radius = 0.0;
 		for (int i(0); i < parent_node2d->get_child_count(); i++) {
 			// For each collision shape
 			CollisionShape2D *cs = Object::cast_to<CollisionShape2D>(parent_node2d->get_child(i));
-			if (cs) {
+			if (cs && cs->is_inside_tree()) {
 				// Take the distance between the Body center to the shape center
 				real_t r = cs->get_transform().get_origin().length();
 				if (cs->get_shape().is_valid()) {
@@ -172,6 +172,9 @@ real_t NavigationObstacle2D::estimate_agent_radius() const {
 				r *= MAX(s.x, s.y);
 				// Takes the biggest radius
 				radius = MAX(radius, r);
+			} else if (cs && !cs->is_inside_tree()) {
+				WARN_PRINT("A CollisionShape2D of the NavigationObstacle2D parent node was not inside the SceneTree when estimating the obstacle radius."
+						   "\nMove the NavigationObstacle2D to a child position below any CollisionShape2D node of the parent node so the CollisionShape2D is already inside the SceneTree.");
 			}
 		}
 		Vector2 s = parent_node2d->get_global_transform().get_scale();

+ 6 - 3
scene/3d/navigation_obstacle.cpp

@@ -92,7 +92,7 @@ void NavigationObstacle::_notification(int p_what) {
 			parent_spatial = nullptr;
 		} break;
 		case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
-			if (parent_spatial) {
+			if (parent_spatial && parent_spatial->is_inside_tree()) {
 				NavigationServer::get_singleton()->agent_set_position(agent, parent_spatial->get_global_transform().origin);
 			}
 
@@ -162,13 +162,13 @@ void NavigationObstacle::reevaluate_agent_radius() {
 }
 
 real_t NavigationObstacle::estimate_agent_radius() const {
-	if (parent_spatial) {
+	if (parent_spatial && parent_spatial->is_inside_tree()) {
 		// Estimate the radius of this physics body
 		real_t radius = 0.0;
 		for (int i(0); i < parent_spatial->get_child_count(); i++) {
 			// For each collision shape
 			CollisionShape *cs = Object::cast_to<CollisionShape>(parent_spatial->get_child(i));
-			if (cs) {
+			if (cs && cs->is_inside_tree()) {
 				// Take the distance between the Body center to the shape center
 				real_t r = cs->get_transform().origin.length();
 				if (cs->get_shape().is_valid()) {
@@ -179,6 +179,9 @@ real_t NavigationObstacle::estimate_agent_radius() const {
 				r *= MAX(s.x, MAX(s.y, s.z));
 				// Takes the biggest radius
 				radius = MAX(radius, r);
+			} else if (cs && !cs->is_inside_tree()) {
+				WARN_PRINT("A CollisionShape of the NavigationObstacle parent node was not inside the SceneTree when estimating the obstacle radius."
+						   "\nMove the NavigationObstacle to a child position below any CollisionShape node of the parent node so the CollisionShape is already inside the SceneTree.");
 			}
 		}
 		Vector3 s = parent_spatial->get_global_transform().basis.get_scale();