mirror of
https://github.com/Relintai/godot-steering-ai-framework.git
synced 2024-11-14 04:57:19 +01:00
Replace body with WeakRef of body to fix crashes
When a physics body was freed by queue_free or free, it was possible for the physics update to still happen on the specialized agent. The Null body then caused a crash.
This commit is contained in:
parent
68b85bb234
commit
fbb92e3593
11
CHANGELOG.md
11
CHANGELOG.md
@ -2,6 +2,17 @@
|
|||||||
|
|
||||||
This document lists new features, improvements, changes, and bug fixes in every release of the add-on.
|
This document lists new features, improvements, changes, and bug fixes in every release of the add-on.
|
||||||
|
|
||||||
|
## Godot Steering AI Framework 2.1.1 ##
|
||||||
|
|
||||||
|
### Changes ###
|
||||||
|
|
||||||
|
- Unused and undocumented variable `_body_type` has been removed from `SpecializedAgent`
|
||||||
|
|
||||||
|
### Bug fixes ###
|
||||||
|
|
||||||
|
- The specialized agents now use WeakRef internally to prevent crashes when their `body` is freed.
|
||||||
|
- `RigidBody2DAgent` now properly connects to physics updates.
|
||||||
|
|
||||||
## Godot Steering AI Framework 2.1.0 ##
|
## Godot Steering AI Framework 2.1.0 ##
|
||||||
|
|
||||||
### Features ###
|
### Features ###
|
||||||
|
@ -15,17 +15,18 @@ var body: KinematicBody2D setget _set_body
|
|||||||
var movement_type: int
|
var movement_type: int
|
||||||
|
|
||||||
var _last_position: Vector2
|
var _last_position: Vector2
|
||||||
|
var _body_ref: WeakRef
|
||||||
|
|
||||||
|
|
||||||
func _init(_body: KinematicBody2D, _movement_type: int = MovementType.SLIDE) -> void:
|
func _init(_body: KinematicBody2D, _movement_type: int = MovementType.SLIDE) -> void:
|
||||||
if not _body.is_inside_tree():
|
if not _body.is_inside_tree():
|
||||||
yield(_body, "ready")
|
yield(_body, "ready")
|
||||||
|
|
||||||
self.body = _body
|
_body_ref = weakref(_body)
|
||||||
self.movement_type = _movement_type
|
self.movement_type = _movement_type
|
||||||
|
|
||||||
# warning-ignore:return_value_discarded
|
# warning-ignore:return_value_discarded
|
||||||
body.get_tree().connect("physics_frame", self, "_on_SceneTree_physics_frame")
|
_body.get_tree().connect("physics_frame", self, "_on_SceneTree_physics_frame")
|
||||||
|
|
||||||
|
|
||||||
# Moves the agent's `body` by target `acceleration`.
|
# Moves the agent's `body` by target `acceleration`.
|
||||||
@ -44,55 +45,75 @@ func _apply_steering(acceleration: GSAITargetAcceleration, delta: float) -> void
|
|||||||
|
|
||||||
|
|
||||||
func _apply_sliding_steering(accel: Vector3) -> void:
|
func _apply_sliding_steering(accel: Vector3) -> void:
|
||||||
|
var _body: KinematicBody2D = _body_ref.get_ref()
|
||||||
|
if not _body:
|
||||||
|
return
|
||||||
|
|
||||||
var velocity := GSAIUtils.to_vector2(linear_velocity + accel).clamped(linear_speed_max)
|
var velocity := GSAIUtils.to_vector2(linear_velocity + accel).clamped(linear_speed_max)
|
||||||
if apply_linear_drag:
|
if apply_linear_drag:
|
||||||
velocity = velocity.linear_interpolate(Vector2.ZERO, linear_drag_percentage)
|
velocity = velocity.linear_interpolate(Vector2.ZERO, linear_drag_percentage)
|
||||||
velocity = body.move_and_slide(velocity)
|
velocity = _body.move_and_slide(velocity)
|
||||||
if calculate_velocities:
|
if calculate_velocities:
|
||||||
linear_velocity = GSAIUtils.to_vector3(velocity)
|
linear_velocity = GSAIUtils.to_vector3(velocity)
|
||||||
|
|
||||||
|
|
||||||
func _apply_collide_steering(accel: Vector3, delta: float) -> void:
|
func _apply_collide_steering(accel: Vector3, delta: float) -> void:
|
||||||
|
var _body: KinematicBody2D = _body_ref.get_ref()
|
||||||
|
if not _body:
|
||||||
|
return
|
||||||
|
|
||||||
var velocity := GSAIUtils.clampedv3(linear_velocity + accel, linear_speed_max)
|
var velocity := GSAIUtils.clampedv3(linear_velocity + accel, linear_speed_max)
|
||||||
if apply_linear_drag:
|
if apply_linear_drag:
|
||||||
velocity = velocity.linear_interpolate(Vector3.ZERO, linear_drag_percentage)
|
velocity = velocity.linear_interpolate(Vector3.ZERO, linear_drag_percentage)
|
||||||
# warning-ignore:return_value_discarded
|
# warning-ignore:return_value_discarded
|
||||||
body.move_and_collide(GSAIUtils.to_vector2(velocity) * delta)
|
_body.move_and_collide(GSAIUtils.to_vector2(velocity) * delta)
|
||||||
if calculate_velocities:
|
if calculate_velocities:
|
||||||
linear_velocity = velocity
|
linear_velocity = velocity
|
||||||
|
|
||||||
|
|
||||||
func _apply_position_steering(accel: Vector3, delta: float) -> void:
|
func _apply_position_steering(accel: Vector3, delta: float) -> void:
|
||||||
|
var _body: KinematicBody2D = _body_ref.get_ref()
|
||||||
|
if not _body:
|
||||||
|
return
|
||||||
|
|
||||||
var velocity := GSAIUtils.clampedv3(linear_velocity + accel, linear_speed_max)
|
var velocity := GSAIUtils.clampedv3(linear_velocity + accel, linear_speed_max)
|
||||||
if apply_linear_drag:
|
if apply_linear_drag:
|
||||||
velocity = velocity.linear_interpolate(Vector3.ZERO, linear_drag_percentage)
|
velocity = velocity.linear_interpolate(Vector3.ZERO, linear_drag_percentage)
|
||||||
body.global_position += GSAIUtils.to_vector2(velocity) * delta
|
_body.global_position += GSAIUtils.to_vector2(velocity) * delta
|
||||||
if calculate_velocities:
|
if calculate_velocities:
|
||||||
linear_velocity = velocity
|
linear_velocity = velocity
|
||||||
|
|
||||||
|
|
||||||
func _apply_orientation_steering(angular_acceleration: float, delta: float) -> void:
|
func _apply_orientation_steering(angular_acceleration: float, delta: float) -> void:
|
||||||
|
var _body: KinematicBody2D = _body_ref.get_ref()
|
||||||
|
if not _body:
|
||||||
|
return
|
||||||
|
|
||||||
var velocity = angular_velocity + angular_acceleration
|
var velocity = angular_velocity + angular_acceleration
|
||||||
if apply_angular_drag:
|
if apply_angular_drag:
|
||||||
velocity = lerp(velocity, 0, angular_drag_percentage)
|
velocity = lerp(velocity, 0, angular_drag_percentage)
|
||||||
body.rotation += velocity * delta
|
_body.rotation += velocity * delta
|
||||||
if calculate_velocities:
|
if calculate_velocities:
|
||||||
angular_velocity = velocity
|
angular_velocity = velocity
|
||||||
|
|
||||||
|
|
||||||
func _set_body(value: KinematicBody2D) -> void:
|
func _set_body(value: KinematicBody2D) -> void:
|
||||||
body = value
|
_body_ref = weakref(body)
|
||||||
|
|
||||||
_last_position = body.global_position
|
_last_position = value.global_position
|
||||||
_last_orientation = body.rotation
|
_last_orientation = value.rotation
|
||||||
|
|
||||||
position = GSAIUtils.to_vector3(_last_position)
|
position = GSAIUtils.to_vector3(_last_position)
|
||||||
orientation = _last_orientation
|
orientation = _last_orientation
|
||||||
|
|
||||||
|
|
||||||
func _on_SceneTree_physics_frame() -> void:
|
func _on_SceneTree_physics_frame() -> void:
|
||||||
var current_position := body.global_position
|
var _body: KinematicBody2D = _body_ref.get_ref()
|
||||||
var current_orientation := body.rotation
|
if not _body:
|
||||||
|
return
|
||||||
|
|
||||||
|
var current_position := _body.global_position
|
||||||
|
var current_orientation := _body.rotation
|
||||||
|
|
||||||
position = GSAIUtils.to_vector3(current_position)
|
position = GSAIUtils.to_vector3(current_position)
|
||||||
orientation = current_orientation
|
orientation = current_orientation
|
||||||
|
@ -15,17 +15,18 @@ var body: KinematicBody setget _set_body
|
|||||||
var movement_type: int
|
var movement_type: int
|
||||||
|
|
||||||
var _last_position: Vector3
|
var _last_position: Vector3
|
||||||
|
var _body_ref: WeakRef
|
||||||
|
|
||||||
|
|
||||||
func _init(_body: KinematicBody, _movement_type: int = MovementType.SLIDE) -> void:
|
func _init(_body: KinematicBody, _movement_type: int = MovementType.SLIDE) -> void:
|
||||||
if not _body.is_inside_tree():
|
if not _body.is_inside_tree():
|
||||||
yield(_body, "ready")
|
yield(_body, "ready")
|
||||||
|
|
||||||
self.body = _body
|
self._body_ref = weakref(_body)
|
||||||
self.movement_type = _movement_type
|
self.movement_type = _movement_type
|
||||||
|
|
||||||
# warning-ignore:return_value_discarded
|
# warning-ignore:return_value_discarded
|
||||||
self.body.get_tree().connect("physics_frame", self, "_on_SceneTree_physics_frame")
|
_body.get_tree().connect("physics_frame", self, "_on_SceneTree_physics_frame")
|
||||||
|
|
||||||
|
|
||||||
# Moves the agent's `body` by target `acceleration`.
|
# Moves the agent's `body` by target `acceleration`.
|
||||||
@ -44,55 +45,75 @@ func _apply_steering(acceleration: GSAITargetAcceleration, delta: float) -> void
|
|||||||
|
|
||||||
|
|
||||||
func _apply_sliding_steering(accel: Vector3) -> void:
|
func _apply_sliding_steering(accel: Vector3) -> void:
|
||||||
|
var _body: KinematicBody = _body_ref.get_ref()
|
||||||
|
if not _body:
|
||||||
|
return
|
||||||
|
|
||||||
var velocity := GSAIUtils.clampedv3(linear_velocity + accel, linear_speed_max)
|
var velocity := GSAIUtils.clampedv3(linear_velocity + accel, linear_speed_max)
|
||||||
if apply_linear_drag:
|
if apply_linear_drag:
|
||||||
velocity = velocity.linear_interpolate(Vector3.ZERO, linear_drag_percentage)
|
velocity = velocity.linear_interpolate(Vector3.ZERO, linear_drag_percentage)
|
||||||
velocity = body.move_and_slide(velocity)
|
velocity = _body.move_and_slide(velocity)
|
||||||
if calculate_velocities:
|
if calculate_velocities:
|
||||||
linear_velocity = velocity
|
linear_velocity = velocity
|
||||||
|
|
||||||
|
|
||||||
func _apply_collide_steering(accel: Vector3, delta: float) -> void:
|
func _apply_collide_steering(accel: Vector3, delta: float) -> void:
|
||||||
|
var _body: KinematicBody = _body_ref.get_ref()
|
||||||
|
if not _body:
|
||||||
|
return
|
||||||
|
|
||||||
var velocity := GSAIUtils.clampedv3(linear_velocity + accel, linear_speed_max)
|
var velocity := GSAIUtils.clampedv3(linear_velocity + accel, linear_speed_max)
|
||||||
if apply_linear_drag:
|
if apply_linear_drag:
|
||||||
velocity = velocity.linear_interpolate(Vector3.ZERO, linear_drag_percentage)
|
velocity = velocity.linear_interpolate(Vector3.ZERO, linear_drag_percentage)
|
||||||
# warning-ignore:return_value_discarded
|
# warning-ignore:return_value_discarded
|
||||||
body.move_and_collide(velocity * delta)
|
_body.move_and_collide(velocity * delta)
|
||||||
if calculate_velocities:
|
if calculate_velocities:
|
||||||
linear_velocity = velocity
|
linear_velocity = velocity
|
||||||
|
|
||||||
|
|
||||||
func _apply_position_steering(accel: Vector3, delta: float) -> void:
|
func _apply_position_steering(accel: Vector3, delta: float) -> void:
|
||||||
|
var _body: KinematicBody = _body_ref.get_ref()
|
||||||
|
if not _body:
|
||||||
|
return
|
||||||
|
|
||||||
var velocity := GSAIUtils.clampedv3(linear_velocity + accel, linear_speed_max)
|
var velocity := GSAIUtils.clampedv3(linear_velocity + accel, linear_speed_max)
|
||||||
if apply_linear_drag:
|
if apply_linear_drag:
|
||||||
velocity = velocity.linear_interpolate(Vector3.ZERO, linear_drag_percentage)
|
velocity = velocity.linear_interpolate(Vector3.ZERO, linear_drag_percentage)
|
||||||
body.global_position += velocity * delta
|
_body.global_position += velocity * delta
|
||||||
if calculate_velocities:
|
if calculate_velocities:
|
||||||
linear_velocity = velocity
|
linear_velocity = velocity
|
||||||
|
|
||||||
|
|
||||||
func _apply_orientation_steering(angular_acceleration: float, delta: float) -> void:
|
func _apply_orientation_steering(angular_acceleration: float, delta: float) -> void:
|
||||||
|
var _body: KinematicBody = _body_ref.get_ref()
|
||||||
|
if not _body:
|
||||||
|
return
|
||||||
|
|
||||||
var velocity = angular_velocity + angular_acceleration
|
var velocity = angular_velocity + angular_acceleration
|
||||||
if apply_angular_drag:
|
if apply_angular_drag:
|
||||||
velocity = lerp(velocity, 0, angular_drag_percentage)
|
velocity = lerp(velocity, 0, angular_drag_percentage)
|
||||||
body.rotation.y += velocity * delta
|
_body.rotation.y += velocity * delta
|
||||||
if calculate_velocities:
|
if calculate_velocities:
|
||||||
angular_velocity = velocity
|
angular_velocity = velocity
|
||||||
|
|
||||||
|
|
||||||
func _set_body(value: KinematicBody) -> void:
|
func _set_body(value: KinematicBody) -> void:
|
||||||
body = value
|
_body_ref = weakref(value)
|
||||||
|
|
||||||
_last_position = body.transform.origin
|
_last_position = value.transform.origin
|
||||||
_last_orientation = body.rotation.y
|
_last_orientation = value.rotation.y
|
||||||
|
|
||||||
position = _last_position
|
position = _last_position
|
||||||
orientation = _last_orientation
|
orientation = _last_orientation
|
||||||
|
|
||||||
|
|
||||||
func _on_SceneTree_physics_frame() -> void:
|
func _on_SceneTree_physics_frame() -> void:
|
||||||
var current_position := body.transform.origin
|
var _body: KinematicBody = _body_ref.get_ref()
|
||||||
var current_orientation := body.rotation.y
|
if not _body:
|
||||||
|
return
|
||||||
|
|
||||||
|
var current_position := _body.transform.origin
|
||||||
|
var current_orientation := _body.rotation.y
|
||||||
|
|
||||||
position = current_position
|
position = current_position
|
||||||
orientation = current_orientation
|
orientation = current_orientation
|
||||||
|
@ -7,43 +7,48 @@ class_name GSAIRigidBody2DAgent
|
|||||||
var body: RigidBody2D setget _set_body
|
var body: RigidBody2D setget _set_body
|
||||||
|
|
||||||
var _last_position: Vector2
|
var _last_position: Vector2
|
||||||
|
var _body_ref: WeakRef
|
||||||
|
|
||||||
|
|
||||||
func _init(_body: RigidBody2D) -> void:
|
func _init(_body: RigidBody2D) -> void:
|
||||||
if not _body.is_inside_tree():
|
if not _body.is_inside_tree():
|
||||||
yield(_body, "ready")
|
yield(_body, "ready")
|
||||||
|
|
||||||
self.body = _body
|
_body_ref = weakref(_body)
|
||||||
|
# warning-ignore:return_value_discarded
|
||||||
|
_body.get_tree().connect("physics_frame", self, "_on_SceneTree_frame")
|
||||||
|
|
||||||
|
|
||||||
# Moves the agent's `body` by target `acceleration`.
|
# Moves the agent's `body` by target `acceleration`.
|
||||||
# tags: virtual
|
# tags: virtual
|
||||||
func _apply_steering(acceleration: GSAITargetAcceleration, _delta: float) -> void:
|
func _apply_steering(acceleration: GSAITargetAcceleration, _delta: float) -> void:
|
||||||
|
var _body: RigidBody2D = _body_ref.get_ref()
|
||||||
|
if not _body:
|
||||||
|
return
|
||||||
|
|
||||||
_applied_steering = true
|
_applied_steering = true
|
||||||
body.apply_central_impulse(GSAIUtils.to_vector2(acceleration.linear))
|
_body.apply_central_impulse(GSAIUtils.to_vector2(acceleration.linear))
|
||||||
body.apply_torque_impulse(acceleration.angular)
|
_body.apply_torque_impulse(acceleration.angular)
|
||||||
if calculate_velocities:
|
if calculate_velocities:
|
||||||
linear_velocity = GSAIUtils.to_vector3(body.linear_velocity)
|
linear_velocity = GSAIUtils.to_vector3(_body.linear_velocity)
|
||||||
angular_velocity = body.angular_velocity
|
angular_velocity = _body.angular_velocity
|
||||||
|
|
||||||
|
|
||||||
func _set_body(value: RigidBody2D) -> void:
|
func _set_body(value: RigidBody2D) -> void:
|
||||||
body = value
|
_body_ref = weakref(value)
|
||||||
|
|
||||||
_last_position = body.global_position
|
_last_position = value.global_position
|
||||||
_last_orientation = body.rotation
|
_last_orientation = value.rotation
|
||||||
|
|
||||||
position = GSAIUtils.to_vector3(_last_position)
|
position = GSAIUtils.to_vector3(_last_position)
|
||||||
orientation = _last_orientation
|
orientation = _last_orientation
|
||||||
|
|
||||||
|
|
||||||
func _on_body_ready() -> void:
|
|
||||||
# warning-ignore:return_value_discarded
|
|
||||||
body.get_tree().connect("physics_frame", self, "_on_SceneTree_frame")
|
|
||||||
_set_body(body)
|
|
||||||
|
|
||||||
|
|
||||||
func _on_SceneTree_frame() -> void:
|
func _on_SceneTree_frame() -> void:
|
||||||
|
var _body: RigidBody2D = _body_ref.get_ref()
|
||||||
|
if not _body:
|
||||||
|
return
|
||||||
|
|
||||||
var current_position := body.global_position
|
var current_position := body.global_position
|
||||||
var current_orientation := body.rotation
|
var current_orientation := body.rotation
|
||||||
|
|
||||||
|
@ -7,47 +7,49 @@ class_name GSAIRigidBody3DAgent
|
|||||||
var body: RigidBody setget _set_body
|
var body: RigidBody setget _set_body
|
||||||
|
|
||||||
var _last_position: Vector3
|
var _last_position: Vector3
|
||||||
|
var _body_ref: WeakRef
|
||||||
|
|
||||||
func _init(_body: RigidBody) -> void:
|
func _init(_body: RigidBody) -> void:
|
||||||
if not _body.is_inside_tree():
|
if not _body.is_inside_tree():
|
||||||
yield(_body, "ready")
|
yield(_body, "ready")
|
||||||
|
|
||||||
self.body = _body
|
_body_ref = weakref(_body)
|
||||||
# warning-ignore:return_value_discarded
|
# warning-ignore:return_value_discarded
|
||||||
self.body.get_tree().connect("physics_frame", self, "_on_SceneTree_frame")
|
_body.get_tree().connect("physics_frame", self, "_on_SceneTree_frame")
|
||||||
|
|
||||||
|
|
||||||
# Moves the agent's `body` by target `acceleration`.
|
# Moves the agent's `body` by target `acceleration`.
|
||||||
# tags: virtual
|
# tags: virtual
|
||||||
func _apply_steering(acceleration: GSAITargetAcceleration, _delta: float) -> void:
|
func _apply_steering(acceleration: GSAITargetAcceleration, _delta: float) -> void:
|
||||||
|
var _body: RigidBody = _body_ref.get_ref()
|
||||||
|
if not _body:
|
||||||
|
return
|
||||||
|
|
||||||
_applied_steering = true
|
_applied_steering = true
|
||||||
body.apply_central_impulse(acceleration.linear)
|
_body.apply_central_impulse(acceleration.linear)
|
||||||
body.apply_torque_impulse(Vector3.UP * acceleration.angular)
|
_body.apply_torque_impulse(Vector3.UP * acceleration.angular)
|
||||||
if calculate_velocities:
|
if calculate_velocities:
|
||||||
linear_velocity = body.linear_velocity
|
linear_velocity = _body.linear_velocity
|
||||||
angular_velocity = body.angular_velocity.y
|
angular_velocity = _body.angular_velocity.y
|
||||||
|
|
||||||
|
|
||||||
func _set_body(value: RigidBody) -> void:
|
func _set_body(value: RigidBody) -> void:
|
||||||
body = value
|
_body_ref = weakref(value)
|
||||||
|
|
||||||
_last_position = body.transform.origin
|
_last_position = value.transform.origin
|
||||||
_last_orientation = body.rotation.y
|
_last_orientation = value.rotation.y
|
||||||
|
|
||||||
position = _last_position
|
position = _last_position
|
||||||
orientation = _last_orientation
|
orientation = _last_orientation
|
||||||
|
|
||||||
|
|
||||||
func _on_body_ready() -> void:
|
|
||||||
# warning-ignore:return_value_discarded
|
|
||||||
body.get_tree().connect("physics_frame", self, "_on_SceneTree_frame")
|
|
||||||
_set_body(body)
|
|
||||||
|
|
||||||
|
|
||||||
func _on_SceneTree_frame() -> void:
|
func _on_SceneTree_frame() -> void:
|
||||||
var current_position := body.transform.origin
|
var _body: RigidBody = _body_ref.get_ref()
|
||||||
var current_orientation := body.rotation.y
|
if not _body:
|
||||||
|
return
|
||||||
|
|
||||||
|
var current_position := _body.transform.origin
|
||||||
|
var current_orientation := _body.rotation.y
|
||||||
|
|
||||||
position = current_position
|
position = current_position
|
||||||
orientation = current_orientation
|
orientation = current_orientation
|
||||||
@ -56,5 +58,5 @@ func _on_SceneTree_frame() -> void:
|
|||||||
if _applied_steering:
|
if _applied_steering:
|
||||||
_applied_steering = false
|
_applied_steering = false
|
||||||
else:
|
else:
|
||||||
linear_velocity = body.linear_velocity
|
linear_velocity = _body.linear_velocity
|
||||||
angular_velocity = body.angular_velocity.y
|
angular_velocity = _body.angular_velocity.y
|
||||||
|
@ -29,7 +29,6 @@ var linear_drag_percentage := 0.0
|
|||||||
var angular_drag_percentage := 0.0
|
var angular_drag_percentage := 0.0
|
||||||
|
|
||||||
var _last_orientation: float
|
var _last_orientation: float
|
||||||
var _body_type: int
|
|
||||||
var _applied_steering := false
|
var _applied_steering := false
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user