Hey y’all, so the feature I’m having trouble with is wall climbing. It currently works by setting velocity according to if certain conditions are met and raycasts are colliding but this completely falls apart when I try to climb on a moving wall. For example if the wall is moving towards you it works fine but if it is moving away the character will just fall off obviously because there is no logic in place for this case. Is there a better way to have the character stick to walls as a whole instead of arbitrarily setting velocity, or should I just amend the current way to include this edge case, but then if I do keep it this way and just add to it I’m afraid that certain features won’t work like how Godot adds the velocity of the moving platform you’re on when you jump off. Any suggestions are welcome thank you all
I would create an Area2d, call it “ClimbArea” for instance. Add a signal to detect whevener the player has touched it. Place as many as you want around the map.
In the player set a var to store the current_climb_area. When the area detects the player, set that node as value for current_climb_area.
In the player script, if current_climb_area is not null, then update the player position with climbArea position.
There are many tweaks to make it look fine (like a release button, take into account player size…) but is it a initial posible solution.
This sounds good because I would be able to keep the player inside the area2d even if the wall is moving away except I forgot to mention I’m trying to avoid solutions which involve editing the map itself as I will have randomly generated terrain so I want a solution which can be more flexible
You can use the same approach. Your player has a var attached_to: Node2D, when you ray cast “wall detector” collides, store the result of get_collider() in attached_to.
Then the same, if attached_to not null, player position equals attached_to position.
This is very close, I just had some time to try the code and I found that I tried something very similar to what you suggested but I had gotten stuck and I can’t figure it out. I keep getting errors for position on index ‘nil’. I tried to cast the body variable as things such as PhysicsBody2D, CollisoinObject2D, Node2D, but I’m not sure what to do.
var body : CollisionObject2D
if MiddleLeft.is_colliding():
body = MiddleLeft.get_collider()
elif MiddleRight.is_colliding():
body = MiddleRight.get_collider()
var prev_pos = body.position
var dir = prev_pos - body.position
if dir != Vector2.ZERO:
Player.position += dir
What you need is the collision point so you know where to stick your player. Also you were asuming body has always value.
Small correction to your code. I renamed body to climb_target to be more semantic. If collides, stores the collision point and assign that point to the player every frame.
var climb_target: Vector2
func _physics_process(delta):
if MiddleLeft.is_colliding():
climb_target = MiddleLeft.get_collision_point()
elif MiddleRight.is_colliding():
climb_target = MiddleRight.get_collision_point()
if climb_target:
Player.position = climb_target
Hey sorry its been a while, just got back to this feature. I tried your last suggestion but it makes the player quickly move upwards when on the walls.
I was close to achieving some success earlier by getting the position of the moving wall which the players raycasts are hitting and I use that info to get the prev position to calculate how much it moved and apply the same to the player. With that the player moves with the platform but not following exactly like slightly lagging behind. I’m thinking maybe trying to fetch the position like this might be too slow for what I want.
Code:
func moving_platform_climb() -> void:
for raycast in [$LeftRay, $RightRay]:
raycast.force_raycast_update()
if raycast.is_colliding():
platform_pos = raycast.get_collider().position
if prev_platform_pos:
var dir : Vector2
var dis : Vector2
var vel : Vector2
dir = prev_platform_pos.direction_to(platform_pos)
dis = prev_platform_pos.distance_to(platform_pos)
vel = (dir * dis)
position += vel
prev_platform_pos = platform_pos
I was trying to code again today and I went through a few iterations which were all somewhat similar. I used the raycast to check where it collided on the wall then try to move the player towards that position but it wont work as it doesn’t record any local position data. Also tried to add Marker2D as child to moving platform and use it as target position but still.
I used direction_to multiplied by distance_to mulitplied by delta for the velocity calculation.
I’m trying to achieve a feature where the player will snap to a certain spot on an object’s wall even if is moving.