Attention | Topic was automatically imported from the old Question2Answer platform. | |
Asked By | timothyp |
I’m new to Godot and I am trying to figure out what to handle where.
Please consider the following script:
extends StaticBody
onready var camera = get_node("/root/Spatial/Camera")
onready var raycast = get_node("/root/Spatial/RayCast")
var selected_object = null
var left_mouse_clicked = true
func _ready():
pass
func _process(_delta):
pass
func change_rigidbody_color(body, color):
var mesh = body.get_node("MeshInstance")
var material = mesh.get_surface_material(0)
material.albedo_color = color
func _physics_process(_delta):
if left_mouse_clicked:
left_mouse_clicked = false
if (raycast.is_colliding()):
var other = raycast.get_collider()
if other is RigidBody:
other.apply_impulse(Vector3.ZERO, Vector3(0,5,0))
change_rigidbody_color(other, Color(0.2, 1, 0.2))
if selected_object != null and selected_object != other:
change_rigidbody_color(selected_object, Color(0.5, 0.5, 0.5))
selected_object = other
func _input(event):
if event is InputEventMouseButton and event.button_index == BUTTON_LEFT and event.pressed:
var from = camera.project_ray_origin(event.position)
var to = from + camera.project_ray_normal(event.position) * 1000;
raycast.translation = from;
raycast.cast_to = to;
left_mouse_clicked = true
The idea is that I check whether or not the user has clicked a rigidbody
with the left mouse button and then perform the following tasks:
- Change the
color
of therigidbody
- Assign the
rigidbody
to theselected_object
variable - Make the
rigidbody
jump a little
And the script does all of that but is this really the way to handle it?
I process the event
in _input(event)
.
If the mouse button is pressed I update the raycast
and set the left_mouse_clicked
flag.
In _physics_process(_delta):
I check that flag
and if it is set I check raycast.is_colliding())
.
Basic idea:
- Update the
raycast
in_input(event)
- Query the
raycast
infunc _physics_process(_delta)
I had another version before:
- Set the
left_mouse_clicked
flag in_input(event)_
- Update the
raycast
infunc _physics_process(_delta)
- Query the
raycast
infunc _physics_process(_delta)
The problem with this was that the query would often return the
cached value because the raycast
did not get time to
update it’s position and vector yet.
To solve that issue I had to call force_raycast_update()
before raycast.is_colliding()
at which point I could even
set raycast.enabled
to false
Next up I wanted to handle other inputs like:
if Input.is_action_pressed("ui_up")
which some samples seem to handle in _physics_process(_delta)
which,
in the script on this page, would mean I’d be handling input in two different functions.
(Also, coming from Unity, I feel like _phycis_process(_delta)
might not be the correct place to handle input)
So (when) should input be handled in _process(_delta)
, _physics_process(_delta)
or _input(event)
Should the raycast
be updated in _input(event)
or in _physics_process(_delta)
The tutorial in the docs ends like this:
const ray_length = 1000
func _input(event):
if event is InputEventMouseButton and event.pressed and event.button_index == 1:
var camera = $Camera
var from = camera.project_ray_origin(event.position)
var to = from + camera.project_ray_normal(event.position) * ray_length
Remember that during _input(), the space may be locked, so in practice this query should be run in _physics_process().
but it feels to me like there’s some information missing, information that is probably very obvious to the trained mind but not so much to newcomers.
Generally speaking, you want to handle input based on what you do with it.
if it needs to do some physics stuff(like walking) when it goes to the _physics_process
(or process if it just moving without collision detection)… if you want to do something exactly when something happens(like a first person camera controller or touch input stuff) then you want to go to the _input
call.
rustyStriker | 2020-04-14 16:56