|
|
|
|
Reply From: |
Marco- |
It is pretty hard to grasp the context from so little code however this time it is enough.
The error message states that you are calling for motion
on body
which does not exist. Why doesn’t it exist? It seems like you have chosen the wrong node for your object. It is a StaticBody2D
which is, as the name states, static. That means it is not intended to move around. Therefor it has no motion
. Try changing its type to a KinematicBody2D instead and try again.
To add more context on the matter, I was using a Node2D on that script I posted and signalled an Area2D to the Node2D to make the function.
This is the full script from Node2D:
extends Node2D
var velocity = 0
var force = 0
var height = 0
var target_height = 0
onready var collision = $Area2D/CollisionShape2D
var index = 0
var motion_factor = 0.02
var collided_with = null
signal splash
func water_update(spring_constant, dampening):
height = position.y
var x = height - target_height
var loss = -dampening * velocity
force = - spring_constant * x + loss
velocity += force
position.y += velocity
pass
func initialize(x_position,id):
height = position.y
target_height = position.y
velocity = 0
position.x = x_position
index = id
func set_collision_width(value):
var extents = collision.shape.get_extents()
var new_extents = Vector2(value/2, extents.y)
collision.shape.set_extents(new_extents)
pass
func _on_Area2D_body_entered(body):
if body == collided_with:
return
collided_with = body
var speed = body.motion.y * motion_factor
emit_signal("splash",index,speed)
pass # Replace with function body.
Problem is, there isn’t any StaticBody2D located in the scene. There’s only Node2D as a root, and inside there’s a Sprite, Area2D and a CollisionShape2D inside the Area2D Child Node.
Is there something else I can do instead? Is there something I should write in the script to fix this?
Sidoku | 2023-03-15 21:03
Ok so you have to look at the Object that is colliding with your Area2D
. That is what is send as body
to your _on_Area2D_body_entered(body)
. Has this object a script attached? Is the property motion
defined?
Marco- | 2023-03-15 21:43
The object I was planning to collide with Area2D is a KinematicBody2D. It has gravity and motion:
extends KinematicBody2D
var gravity = 35
var motion = Vector2.ZERO
var max_speed = 450
func _physics_process(delta):
motion.y += gravity
motion.y = clamp(motion.y, -max_speed, max_speed)
motion = move_and_slide(motion)
func initialize(pos):
global_position = pos
I have some other scripts which is also for the water physics;
This is for the water body:
extends Node2D
export var k = 0.015
export var d = 0.03
export var spread = 0.0002
var springs = []
var passes = 8
export var distance_between_springs = 32
export var spring_number = 6
var water_length = distance_between_springs * spring_number
onready var water_spring = preload("res://physics/water_spring.tscn")
export var depth = 1000
var target_height = global_position.y
var bottom = target_height + depth
onready var water_polygon = $Water_Polygon
onready var water_border = $Water_Border
export var border_thickness = 1.1
func _ready():
water_border.width = border_thickness
spread = spread / 1000
for i in range(spring_number):
var x_position = distance_between_springs * i
var w = water_spring.instance()
add_child(w)
springs.append(w)
w.initialize(x_position, i)
w.set_collision_width(distance_between_springs)
w.connect("splash", self, "splash")
splash(2,5)
func _physics_process(_delta):
for i in springs:
i.water_update(k,d)
var left_deltas = []
var right_deltas = []
for _j in range(passes):
for _i in range (springs.size()):
left_deltas.append(0)
right_deltas.append(0)
pass
for i in range(springs.size()):
if i > 0:
left_deltas[i] = spread * (springs[i].height - springs[i-1].height)
springs[i-1].velocity += left_deltas[i]
if i < springs.size()-1:
right_deltas[i] = spread * (springs[i].height - springs[i+1].height)
springs[i+1].velocity += right_deltas[i]
new_border()
draw_water_body()
func draw_water_body():
var curve = water_border.curve
var points = Array(curve.get_baked_points())
var water_polygon_points = points
var first_index = 0
var last_index = water_polygon_points.size()-1
water_polygon_points.append(Vector2(water_polygon_points[last_index].x, bottom))
water_polygon_points.append(Vector2(water_polygon_points[first_index].x, bottom))
water_polygon_points = PoolVector2Array(water_polygon_points)
water_polygon.set_polygon(water_polygon_points)
pass
func new_border():
var curve = Curve2D.new().duplicate()
var surface_points = []
for i in range(springs.size()):
surface_points.append(springs[i].position)
for i in range(surface_points.size()):
curve.add_point(surface_points[i])
water_border.curve = curve
water_border.smooth(true)
water_border.update()
pass
func splash(index, speed):
if index >= 0 and index < springs.size():
springs[index].velocity += speed
pass
And this is for the Water Line Path:
class_name SmoothPath
extends Path2D
export(float) var spline_length = 100
export(bool) var _smooth setget smooth
export(bool) var _straighten setget straighten
export(Color) var color = Color(1,1,1,1)
export(float) var width = 8
func straighten(value):
if not value: return
for i in range(curve.get_point_count()):
curve.set_point_in(i, Vector2())
curve.set_point_out(i, Vector2())
func smooth(value):
if not value: return
var point_count = curve.get_point_count()
for i in point_count:
var spline = _get_spline(i)
curve.set_point_in(i, -spline)
curve.set_point_out(i, spline)
func _get_spline(i):
var last_point = _get_point(i - 1)
var next_point = _get_point(i + 1)
var spline = last_point.direction_to(next_point) * spline_length
return spline
func _get_point(i):
var point_count = curve.get_point_count()
i = wrapi(i, 0, point_count - 1)
return curve.get_point_position(i)
func _draw():
var points = curve.get_baked_points()
if points:
draw_polyline(points, Color.black, 8, true)
Since the object that I’m colliding with is a KinematicBody2D, should I change it to something else or not? I’m pretty new to this sort of thing so not sure if showing the other scripts help or not.
Sidoku | 2023-03-16 08:05
Ok, the problem is still that the engine is complaining that a colliding body doesn’t have the motion
attribute. Go over your project and look whether there are other bodies or even extra colliders on your player that shouldn’t be there. Also check your collision layers maybe any of your object is set to the wrong layer.
If you still have trouble finding the culprit try printing out the name of the colliding body like this:
func _on_Area2D_body_entered(body):
if body == collided_with:
return
collided_with = body
print(body.name)
var speed = body.motion.y * motion_factor
emit_signal("splash",index,speed)
pass # Replace with function body.
The print should show you the name of the object before the problem occurs.
Marco- | 2023-03-16 21:05
Good News. I figured out where the static body were located. When I wrote “print(body.name)” into the script, then I found where the staticbody was. It was In my other world scene. The water was 1 pixel next to the collison so it became an error. I just pushed it away from the staticbody2d collision and now everything works. Now the water moves when it meets a kinematicbody. Brilliant. Thanks for the help and have a good day!
Sidoku | 2023-03-17 10:04