Should physics.wakeup() work on my kinematic collision object in 3d?

Every 3 seconds my kinematic character controller falls asleep and calling physics.wakeup() doesn’t help. It wakes up only by meaningful movement with a speed more than 0.3 units per second.

In this video you can see the problem. Every 3 seconds the physics skips calculation of the one frame and doesn’t send any contact_point_response messages. So the player moves inside the walls, thinking that there are no obstacles. Then again for 3 seconds everything works correctly and again - one frame is skipped, etc.

#6576

<Spoiler> Periodically pushing the kinematic body just for awakening works fine, but unfortunately it works only because of my character reaction movement...

1 Like

I found a tricky workaround. If there are contact points from contact_point_response messages and and last movement was enough to fall asleep I start the timer to pass attempt to move every second.

By this way, the bullet physics timer is reset because the reverse movement from last desired position and to the last original position is sufficient for this. In fact, as we are already barely moving due to the obstacle, this is not noticeable to the player.

Of course, it would be better to fix it, but so far it works like this.

function update(dt)
  ...
  -- Workaround to avoid falling asleep (https://github.com/defold/defold/issues/6576)
  local last_movement = self.position - self.last_position
  local can_fall_asleep = vmath.length(last_movement) / dt < 0.5 and #self.contact_points > 0

  if can_fall_asleep then
    self.wakeup_timer = self.wakeup_timer + dt
    if self.wakeup_timer > 1 then
      self.wakeup_timer = 0
      return -- Pass one frame by standing on the original position to wake up physics.
    end
  elseif self.wakeup_timer then
    self.wakeup_timer = 0
  end

  -- Calculate the position
  local direction = calculate_direction(self)
  self.movement = direction * speed * dt

  -- Update the position
  if self.movement ~= vectors.zero then
    self.position = self.position + self.movement
    go.set_position(self.position)
  end
  ...
end