Godot Version
4.1.1
Question
Hi. I develop 2d top down game. and wants that one of the character has own gravitation to pull other characters to self (just like planet). But it is not working. Checked collisions mask and layers. all nodes are RigidBody2D. But if I add a new RigidBody2D with only sprite and shape. it works. Where can I found what is wrong?
There gravity made by adding Area2D+CollisionShape, set radius and Gravity-Space Override -combine/replace. set max mass and strength of the gravity.
Can you show your character code?
node that has Gravity
extends RigidBody2D
var is_going := false
var speed := 1
@export var move_strength = 1
func _physics_process(_delta):
# if is_going:
self.apply_impulse(move_strength * Vector2(0, -1))
func go():
is_going = true
func _on_area_2d_2_body_entered(body):
if body.has_meta("DreamRealizator"):
queue_free()
else:
calculating_angle()
func calculating_angle():
var rival_body : Node2D
var collision_point
var rid := get_rid()
var state := PhysicsServer2D.body_get_direct_state(rid)
for i in get_contact_count():
collision_point = state.get_contact_collider_position(i)
rival_body = state.get_contact_collider_object(i)
print(rival_body)
var rival_children_array = rival_body.get_children()
var rival_edge_a : Node2D = rival_children_array[0]
var rival_edge_b : Node2D = rival_children_array[1]
var rival_edge_c : Node2D = rival_children_array[2]
var rival_edge_d : Node2D
if rival_body.has_meta("squared"):
rival_edge_d = rival_children_array[3]
if collision_point.distance_to(rival_edge_a.global_position) < 5 or\
collision_point.distance_to(rival_edge_b.global_position) < 5 or\
collision_point.distance_to(rival_edge_c.global_position) < 5:
queue_free()
elif rival_body.has_meta("squared"):
if collision_point.distance_to(rival_edge_d.global_position) < 5:
queue_free()
node that must interact:
extends RigidBody2D
var _squared
var is_going := false
var speed := 50
var collision_point : Vector2
var angle : float
var rival_body : Node2D
@export var move_strength = 1
@onready var edge_a := $EdgeA
@onready var edge_b := $EdgeB
@onready var edge_c := $EdgeC
@onready var edge_d := $EdgeD
@onready var squared_raycast_0C = $"Squared Raycast 0-C"
@onready var squared_raycast_1C = $"Squared Raycast 1-C"
@onready var squared_raycast_2C = $"Squared Raycast 2-C"
@onready var squared_raycast_3C = $"Squared Raycast 3-C"
func _physics_process(_delta):
if is_going:
self.apply_impulse(move_strength * Vector2(0, 1))
func go():
is_going = true
func calculating_angle():
var rival_second_nearest_edge_global_position : Vector2
var is_this_attacking_angle : float
var rid := get_rid()
var state := PhysicsServer2D.body_get_direct_state(rid)
for i in get_contact_count():
rival_body = state.get_contact_collider_object(i)
var rival_children_array = rival_body.get_children()
var rival_edge_a : Node2D = rival_children_array[0]
var rival_edge_b : Node2D = rival_children_array[1]
var rival_edge_c : Node2D = rival_children_array[2]
var rival_edge_d : Node2D
#in inspector at the bottom add metadata
if rival_body.has_meta("squared"):
rival_edge_d = rival_children_array[3]
var rival_secondNearestEdgeArray : Array
var rival_distance_array_A : Array
var rival_distance_array_B : Array
var rival_distance_array_C : Array
var rival_distance_array_D : Array
rival_distance_array_A.append(rival_edge_a.global_position)
rival_distance_array_A.append(collision_point.distance_to(rival_edge_a.global_position))
rival_secondNearestEdgeArray.append(rival_distance_array_A)
rival_distance_array_B.append(rival_edge_b.global_position)
rival_distance_array_B.append(collision_point.distance_to(rival_edge_b.global_position))
rival_secondNearestEdgeArray.append(rival_distance_array_B)
rival_distance_array_C.append(rival_edge_c.global_position)
rival_distance_array_C.append(collision_point.distance_to(rival_edge_c.global_position))
rival_secondNearestEdgeArray.append(rival_distance_array_C)
if rival_body.has_meta("squared"):
rival_distance_array_D.append(rival_edge_d.global_position)
rival_distance_array_D.append(collision_point.distance_to(rival_edge_d.global_position))
rival_secondNearestEdgeArray.append(rival_distance_array_D)
rival_secondNearestEdgeArray.sort_custom(sort_ascending_for_finding_second_nearest_edge)
rival_second_nearest_edge_global_position = rival_secondNearestEdgeArray[1][0]
var rival_angle : float = collision_point.angle_to_point(rival_second_nearest_edge_global_position)
var attacking_angle : float = abs(abs(angle) - abs(rival_angle))
if attacking_angle > PI/2:
is_this_attacking_angle = PI - attacking_angle
if is_this_attacking_angle > PI/6 && is_this_attacking_angle < PI/3:
queue_free()
elif attacking_angle > PI/6 && attacking_angle < PI/3:
queue_free()
func _on_area_2d_body_entered(body):
if !squared_raycast_0C.is_colliding() and !squared_raycast_1C.is_colliding()\
and !squared_raycast_2C.is_colliding() and !squared_raycast_3C.is_colliding():
self_second_nearest_edge_to_collision_point()
calculating_angle()
elif body.has_meta("DreamRealizator"):
queue_free()
func sort_ascending_for_finding_second_nearest_edge(a,b):
if a[1] < b [1]:
return true
return false
func self_second_nearest_edge_to_collision_point():
# get_list_of_the_edges()
var second_nearest_edge_global_position : Vector2
var distanceArrayA : Array
var distanceArrayB : Array
var distanceArrayC : Array
var distanceArrayD : Array
var secondNearestEdgeArray : Array
#find collision point on my shape
# Note: RIDs are only useful during the current session. It won't correspond
# to a similar resource if sent over a network, or loaded from a file at a later time.
var rid := get_rid()
# Get body physics state
var state := PhysicsServer2D.body_get_direct_state(rid)
# For get the position, you need to get the collision index, if you're colliding
# with one body, will be 1, if more, will be the amout of body collisions
# also calculate distance to the edges from the collision point
for i in get_contact_count():
collision_point = state.get_contact_collider_position(i)
distanceArrayA.append(edge_a.global_position)
distanceArrayA.append(collision_point.distance_to(edge_a.global_position))
secondNearestEdgeArray.append(distanceArrayA)
distanceArrayB.append(edge_b.global_position)
distanceArrayB.append(collision_point.distance_to(edge_b.global_position))
secondNearestEdgeArray.append(distanceArrayB)
distanceArrayC.append(edge_c.global_position)
distanceArrayC.append(collision_point.distance_to(edge_c.global_position))
secondNearestEdgeArray.append(distanceArrayC)
distanceArrayD.append(edge_d.global_position)
distanceArrayD.append(collision_point.distance_to(edge_d.global_position))
secondNearestEdgeArray.append(distanceArrayD)
secondNearestEdgeArray.sort_custom(sort_ascending_for_finding_second_nearest_edge)
second_nearest_edge_global_position = secondNearestEdgeArray[1][0]
angle = collision_point.angle_to_point(second_nearest_edge_global_position)
# print(second_nearest_edge_global_position, " coordinates from squared")
# print(secondNearestEdgeArray, " squared")
Is the gravity_point
property of the Area2D enabled? If not, you’ll want to set that to true
.
You may need to adjust gravity_point_center
depending on how your nodes are positioned. You can also adjust gravity_point_unit_distance
to make the pull stronger the closer bodies are to the center of the area’s gravity.
See Using Area2D > Point Gravity.
yes, all these properties turned on. and it works with new created node (RigidBody2D+area2D(for collisions)+Shape+sprite) and don`t work with earlier created.
And have found strange thing. the new node (call it test node) had gravity scale 1. And whole project has 0 due top down orientation. I changed gravity to 0 and it stop to pull to the node with gravity. when I undo gravity scale to 1. it do not pull to Node with gravity, and just falling down.
Solved. Strange thing for me, but to work properly the character with RigidBody2D must has set Gravity Scale (in RigidBody2D - Inspector (window) min 1 (not zero). Whereas the whole top down project set Gravity to 0.