Reputation: 11
I don't Know How to Make The Enemy change speed or not moving after a few second here my code
extends CharacterBody3D
const speed = - 1
func _ready():
pass # Replace with function body.
func _physics_process(delta):
position += transform.basis * Vector3(speed,0, 0) * delta * 0.01
Upvotes: 1
Views: 554
Reputation: 40295
SceneTreeTimer
If you only need this change a few seconds after spawning, creating a timer is useful, in particular an SceneTreeTimer
comes handy:
func _ready() -> void:
var timer := get_tree().create_timer(a_few_seconds)
timer.timeout.connect(func(): velocity = Vector3.ZERO)
Where a_few_seconds
is the amount of time you want to elapse before the change happens.
As you can see I'm using an anonymous method (lambda) to set velocity
to Vector3.ZERO
, you could use multiple lines, or connect a full blown method.
No, you do not need to keep a reference of the SceneTreeTimer
. I'm using a local variable to avoid making the line too long.
By default the SceneTreeTimer
will run even if the game is paused (which you do with get_tree().paused = true
), but you can have it stop when paused like this:
func _ready() -> void:
var timer := get_tree().create_timer(a_few_seconds, false)
timer.timeout.connect(func(): velocity = Vector3.ZERO)
Time.get_ticks_msec()
However, if the time at which you want the change to happen might change, you are better of using a different approach.
My go-to these days is computing the time at which I want it to happen having Time.get_ticks_msec()
as starting point:
var change_msec:int
func _ready() -> void:
change_msec = Time.get_ticks_msec() + int(a_few_seconds * 1000.0)
And then checking in _process
:
func _physics_process(delta:float) -> void:
if Time.get_ticks_msec() > change_msec:
velocity = Vector3.ZERO
A variation of this is using float
, which also allows to encode INF
for something to never happen:
var change_seconds:float
func _ready() -> void:
change_seconds = (Time.get_ticks_msec() / 1000.0) + a_few_seconds
func _physics_process(delta:float) -> void:
if (Time.get_ticks_msec() / 1000.0) > change_seconds:
velocity = Vector3.ZERO
The drawback of this approach is that... It takes extra effort to support pause (you could listen NOTIFICATION_PAUSED
, and NOTIFICATION_UNPAUSED
, and keep track of accumulated time). It is probably better to change approach if that is important.
delta
Some people prefer a countdown and take advantage of delta
.
var remaining_time:float
func _ready() -> void:
remaining_time = a_few_seconds
func _physics_process(delta:float) -> void:
remaining_time -= delta
if remaining_time < 0.0:
velocity = Vector3.ZERO
This is probably the easier to grasp.
Timer
(from the editor)The above method is also how a regular Timer
works behind the scenes, so that is another option:
Timer
in your scene as a child to your Node
in the editor.wait_time
to the few seconds you want to wait.autostart
property to true
so it starts automatically.timeout
signal to your Node
.Then you will have a method that handles the timeout
signal looking like this:
func _on_timer_timeout() -> void:
velocity = Vector3.ZERO
Timer
(from code)Of course, the above implies that you have a scene where you can do that. If you don't you can still make the timer from code:
var timer:Timer
func _ready() -> void:
timer = Timer.new()
timer.wait_time = a_few_seconds
timer.timeout.connect(_on_timer_timeout)
timer.start()
func _on_timer_timeout() -> void:
velocity = Vector3.ZERO
And, of course, SceneTreeTimer
is a convenient way of doing that. So we have come full circle.
Thread
There is arguebly another way of doing it: start a Thread
and have it sleep with OS.delay_msec
for the desired amount of time, then it can use call_deferred
or set_deferred
to do the change you want.
The only advantage of this approach is that you are not checking every frame in _process
, but of course a Thread
has its own cost, so this might only make sense for the case of a long wait time. It also has the caveat of not supporting pause.
Upvotes: 1