Closed PudgeKim closed 2 years ago
@PudgeKim Hey, okey, that's great! I saw your posting initally, but didn't have the time to answer before now.
dt
and args.dt
which you referred to in the 3D example are the same because args = UpdateArgs { dt }
, so you can use either.
Also, dt
specifies how much into the future you want your behavior tree to advance for a particular tick. Typically, you will set the dt
time to be the same time as the 1 / rate_of_you_program
e.g 1 / 100Hz = 0.01s
. The different processes/nodes in your behavior tree will consume of the value dt
, so this value should be strictly decreasing as time goes.
e.g when a node returns, it should return whatever status the node resulted in and the input dt
time minus the time it took to process the node (Success, dt-process_time)
(see concecpts page for more info, specifially the Events section). The tree will then have a remaining dt = dt - process_time
to process other nodes for this tick.
If you have any more questions, just let me know :)
Thanks for answering even though I closed the issue. After looking at your answer, I have a question. Here's my simple example code.
#[derive(serde::Deserialize, serde::Serialize, Clone, Debug, PartialEq)]
enum Npc {
Walk,
Run,
}
fn game_tick(dt: f64, bt: &mut BT<Npc, String, serde_json::Value>) {
let e: Event = UpdateArgs { dt }.into();
bt.state.tick(&e, &mut |mut args: bonsai_bt::ActionArgs<Event, Npc>| {
match *args.action {
Npc::Walk => {
println!("walk! dt: {}", args.dt);
(bonsai_bt::Success, args.dt)
},
Npc::Run => {
println!("run! dt: {}", args.dt);
(bonsai_bt::Success, args.dt)
}
}
});
}
fn main() {
let blackboard = HashMap::new();
let walk = Action(Walk);
let run = Action(Run);
let seq = Sequence(vec![walk, run, Wait(200.0)]);
let behavior = While(Box::new(WaitForever), vec![seq]);
let mut bt = BT::new(behavior, blackboard);
loop {
game_tick(70.0, &mut bt);
sleep(Duration::from_secs(1));
println!("1 sec");
}
}
Here's the output of the code.
walk! dt: 70
run! dt: 70
1 sec
1 sec
walk! dt: 10
run! dt: 10
1 sec
1 sec
1 sec
walk! dt: 20
run! dt: 20
1 sec
1 sec
1 sec
walk! dt: 30
run! dt: 30
1 sec
1 sec
1 sec
...
My expectation of args.dt: tick1: Wait 200 - 70 = 130 tick2: Wait 130 - 70 = 60 tick3: Wait 60 - 70 = -10 tick4: now behavior tree is finished so args.dt would be set to 80(remaining dt 10 + UpdateArgs{dt} )
But tick4 sets args.dt to 10. So args.dt is not updated even though behavior tree is finished.
UpdateArgs{dt}.into
works after args.dt is set to 0?
If you BT runs at intervals of 70, and you wait for 200, then you will be overdue of (200 - 210) = -10
as you say. However, I don't portray overdue time as a negative value because that messes with the timing in the following nodes. so it is basically abs(Wait 60 - 70) = Abs (Wait -10 ) = 10
see implementation here: https://github.com/Sollimann/bonsai/blob/42081d26c7344723d6aa0fd4f1e5a8db57bc591d/bonsai/src/state.rs#L144
Here is another question related to time as well, in case that gives you some more clarification: https://github.com/Sollimann/bonsai/issues/10
I resolved issue by myself. sorry.