Godot Version
4.4 stable
Does anyone know how to reference a script so I can disable movement in a Area2D. I need the player to hold still because the player moving is overriding the velocity my Area2D is providing. I have the player scene instantiated in all scenes. I am trying to use set_process() but I don’t even know if thats what I’m supposed to do.
This is level_4.gd
extends Node2D
var has_player_fallen = false
func _process(_delta: float) -> void:
if has_player_fallen == true:
$Player.velocity += transform.y * 980
$Player.velocity += transform.x * -5000
$MovingPlatform/AnimationPlayer.play("Platform")
$MovingPlatform2/AnimationPlayer.play("Platform")
$MovingPlatform3/AnimationPlayer.play("Platform")
func _on_return_2_start_body_entered(_body: CharacterBody2D) -> void:
has_player_fallen = true
func _on_return_2_start_body_exited(_body: CharacterBody2D) -> void:
has_player_fallen = false
And this is Player.gd
extends CharacterBody2D
var jump_count = 0
var speed = 600
var jump_velocity = -600
var can_climb = false
var gravity_toggle = false
func _ready() -> void:
$LightHolder/LightBeam.visible = false
func _process(_delta: float) -> void:
$LightHolder.look_at(get_global_mouse_position())
$Pupil/EyeAnimations.play("Looking")
if Input.is_action_pressed("ui_accept") and can_climb == true:
gravity_toggle = true
PhysicsServer2D.area_set_param(get_viewport().find_world_2d().space, PhysicsServer2D.AREA_PARAM_GRAVITY, -280)
else:
gravity_toggle = false
PhysicsServer2D.area_set_param(get_viewport().find_world_2d().space, PhysicsServer2D.AREA_PARAM_GRAVITY, 980)
if Input.is_action_pressed("LeftClick"):
$LightHolder/LightBeam.visible = true
if Input.is_action_just_pressed("LeftClick"):
$FlashlightToggle.play()
elif Input.is_action_just_released("LeftClick"):
$LightHolder/LightBeam.visible = false
$FlashlightToggle.play()
func _physics_process(delta: float) -> void:
# Add the gravity.
if not is_on_floor():
velocity += get_gravity() * delta
if Input.is_action_pressed("ui_accept") and is_on_floor(): #Jump
velocity.y = jump_velocity
jump_count = 1
elif Input.is_action_just_pressed("ui_accept") and jump_count == 1: # Double Jump
velocity.y = jump_velocity
jump_count = 0
var direction := Input.get_axis("ui_left", "ui_right")
if direction:
velocity.x = direction * speed
else:
velocity.x = move_toward(velocity.x, 0, speed)
if Input.is_action_pressed("ui_left"):
$PlayerAnimations.play("Left")
elif Input.is_action_pressed("ui_right"):
$PlayerAnimations.play("Right")
else:
$PlayerAnimations.stop(false)
move_and_slide()
func _on_climb_collision_body_entered(_body: StaticBody2D) -> void:
can_climb = true
func _on_climb_collision_body_exited(_body: StaticBody2D) -> void:
can_climb = false
set_process
only enables/disables the _process
function, maybe you also want to use set_physics_process
which disables _physics_process
. If you want to keep some effects like gravity, creating a new variable can be used to read inputs.
var player_locked: bool = false
func _physics_process(delta: float) -> void:
var direction := Input.get_axis("ui_left", "ui_right")
if direction and player_locked == false:
velocity.x = direction * speed
I know but I want to do it from level_5.gd (Ideally from the signal _on_return_2_start_body_entered/exited) because that way I don’t have to create a new node for every scene to avoid getting an error from godot not being able to find the node
Not sure I follow, you can edit the player variable as you would any other property or method.
func _on_return_2_start_body_entered(body: CharacterBody2D) -> void:
if body.name == "Player": # better to use `is` and a class_name
body.player_locked = true
So godot doesn’t like it when i reference something in my script that isnt in every scene that the player script is in so i would need to put this area 2
d node or level_5.gd in every scene
I don’t think you would have to put the area3d in every scene, the sample I provided does not reference any other nodes, only getting the player through collisions by name. Notice I did not use the shorthand $
nor get_node
?
Can you explain this a little more thouroghly I don’t know about that ( and also there is no area 3d i meant 2d)
I can’t explain much better because I’m not sure about the question, I don’t see any references to an Area2D in your code or mine. Where in the code do you believe requires an Area2D to be present in every scene?
I recommend you put all your input code into _input() and then turn processing for that off when you don’t want the player to be able to move. They will still be affected by gravity, physics, etc. They just will have lost inputs.
That’s what I want but how would I go about implementing this?
From the documentation: set_process_input
.
Ok this didn’t work but maybe I did it wrong so here is my updated code
Player.gd
var jump_count = 0
var speed = 600
var jump_velocity = -600
var can_climb = false
var gravity_toggle = false
func _ready() -> void:
$LightHolder/LightBeam.visible = false
func _process(_delta: float) -> void:
$LightHolder.look_at(get_global_mouse_position())
$Pupil/EyeAnimations.play("Looking")
if Input.is_action_pressed("ui_accept") and can_climb == true:
gravity_toggle = true
PhysicsServer2D.area_set_param(get_viewport().find_world_2d().space, PhysicsServer2D.AREA_PARAM_GRAVITY, -580)
else:
gravity_toggle = false
PhysicsServer2D.area_set_param(get_viewport().find_world_2d().space, PhysicsServer2D.AREA_PARAM_GRAVITY, 980)
if Input.is_action_pressed("LeftClick"):
$LightHolder/LightBeam.visible = true
if Input.is_action_just_pressed("LeftClick"):
$FlashlightToggle.play()
elif Input.is_action_just_released("LeftClick"):
$LightHolder/LightBeam.visible = false
$FlashlightToggle.play()
func _physics_process(delta: float) -> void:
# Add the gravity.
if not is_on_floor():
velocity += get_gravity() * delta
if Input.is_action_pressed("ui_accept") and is_on_floor(): #Jump
velocity.y = jump_velocity
jump_count = 1
elif Input.is_action_just_pressed("ui_accept") and jump_count == 1: # Double Jump
velocity.y = jump_velocity
jump_count = 0
var direction := Input.get_axis("ui_left", "ui_right")
if direction:
velocity.x = direction * speed
else:
velocity.x = move_toward(velocity.x, 0, speed)
if Input.is_action_pressed("ui_left"):
$PlayerAnimations.play("Left")
elif Input.is_action_pressed("ui_right"):
$PlayerAnimations.play("Right")
else:
$PlayerAnimations.stop(false)
move_and_slide()
func _on_climb_collision_body_entered(_body: StaticBody2D) -> void:
can_climb = true
func _on_climb_collision_body_exited(_body: StaticBody2D) -> void:
can_climb = false
level_4.gd
var has_player_fallen = false
func _process(_delta: float) -> void:
if has_player_fallen == true:
$Player.velocity += transform.y * 980
$Player.velocity += transform.x * -5000
$MovingPlatform/AnimationPlayer.play("Platform")
$MovingPlatform2/AnimationPlayer.play("Platform")
$MovingPlatform3/AnimationPlayer.play("Platform")
func _on_return_2_start_body_entered(_body: CharacterBody2D) -> void:
$Player.set_process_input(false)
has_player_fallen = true
func _on_return_2_start_body_exited(_body: CharacterBody2D) -> void:
$Player.set_process_input(true)
has_player_fallen = false
and if I reuse the same script for every scene and I reference a node from one scene the script will change in the other scenes too. Godot won’t be able to find the referenced node if it is not in that scene
similar to set_process
, set_process_input
only disables the _input
function, which you did not define, so it does nothing.
Which script are you reusing? It looks like your player is fine to instanciate in other scenes. Your level_4.gd
seems very purpose built, like you wouldn’t want to reuse it for a level without 3 MovingPlatforms, but that is not related to the input issue.
I posted an example of getting the player by collision, without using node paths. Even this does not break if the Player isn’t in the scene nor a direct child.
1 Like