diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp
index af261f490b..faa9f88ae9 100644
--- a/interface/src/avatar/MyAvatar.cpp
+++ b/interface/src/avatar/MyAvatar.cpp
@@ -932,7 +932,8 @@ void MyAvatar::simulate(float deltaTime, bool inView) {
         bool isPhysicsEnabled = qApp->isPhysicsEnabled();
         bool zoneAllowsFlying = zoneInteractionProperties.first;
         bool collisionlessAllowed = zoneInteractionProperties.second;
-        _characterController.setFlyingAllowed((zoneAllowsFlying && _enableFlying) || !isPhysicsEnabled);
+        _characterController.setZoneFlyingAllowed(zoneAllowsFlying || !isPhysicsEnabled);
+        _characterController.setComfortFlyingAllowed(_enableFlying);
         _characterController.setCollisionlessAllowed(collisionlessAllowed);
     }
 
diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp
index 66ce5f32bf..a5f1a0598f 100755
--- a/libraries/physics/src/CharacterController.cpp
+++ b/libraries/physics/src/CharacterController.cpp
@@ -781,18 +781,18 @@ void CharacterController::updateState() {
                 const float jumpSpeed = sqrtf(2.0f * -DEFAULT_AVATAR_GRAVITY * jumpHeight);
                 if ((velocity.dot(_currentUp) <= (jumpSpeed / 2.0f)) && ((_floorDistance < FLY_TO_GROUND_THRESHOLD) || _hasSupport)) {
                     SET_STATE(State::Ground, "hit ground");
-                } else if (_flyingAllowed) {
+                } else if (_zoneFlyingAllowed) {
                     btVector3 desiredVelocity = _targetVelocity;
                     if (desiredVelocity.length2() < MIN_TARGET_SPEED_SQUARED) {
                         desiredVelocity = btVector3(0.0f, 0.0f, 0.0f);
                     }
                     bool vertTargetSpeedIsNonZero = desiredVelocity.dot(_currentUp) > MIN_TARGET_SPEED;
-                    if ((jumpButtonHeld || vertTargetSpeedIsNonZero) && (_takeoffJumpButtonID != _jumpButtonDownCount)) {
+                    if (_comfortFlyingAllowed && (jumpButtonHeld || vertTargetSpeedIsNonZero) && (_takeoffJumpButtonID != _jumpButtonDownCount)) {
                         SET_STATE(State::Hover, "double jump button");
-                    } else if ((jumpButtonHeld || vertTargetSpeedIsNonZero) && (now - _jumpButtonDownStartTime) > JUMP_TO_HOVER_PERIOD) {
+                    } else if (_comfortFlyingAllowed && (jumpButtonHeld || vertTargetSpeedIsNonZero) && (now - _jumpButtonDownStartTime) > JUMP_TO_HOVER_PERIOD) {
                         SET_STATE(State::Hover, "jump button held");
-                    } else if (_floorDistance > _scaleFactor * DEFAULT_AVATAR_FALL_HEIGHT) {
-                        // Transition to hover if we are above the fall threshold
+                    } else if ((!rayHasHit && !_hasSupport) || _floorDistance > _scaleFactor * DEFAULT_AVATAR_FALL_HEIGHT) {
+                        // Transition to hover if there's no ground beneath us or we are above the fall threshold, regardless of _comfortFlyingAllowed
                         SET_STATE(State::Hover, "above fall threshold");
                     }
                 }
@@ -801,8 +801,10 @@ void CharacterController::updateState() {
             case State::Hover:
                 btScalar horizontalSpeed = (velocity - velocity.dot(_currentUp) * _currentUp).length();
                 bool flyingFast = horizontalSpeed > (MAX_WALKING_SPEED * 0.75f);
-                if (!_flyingAllowed) {
-                    SET_STATE(State::InAir, "flying not allowed");
+                if (!_zoneFlyingAllowed) {
+                    SET_STATE(State::InAir, "zone flying not allowed");
+                } else if (!_comfortFlyingAllowed && (rayHasHit || _hasSupport || _floorDistance < FLY_TO_GROUND_THRESHOLD)) {
+                    SET_STATE(State::InAir, "comfort flying not allowed");
                 } else if ((_floorDistance < MIN_HOVER_HEIGHT) && !jumpButtonHeld && !flyingFast) {
                     SET_STATE(State::InAir, "near ground");
                 } else if (((_floorDistance < FLY_TO_GROUND_THRESHOLD) || _hasSupport) && !flyingFast) {
@@ -847,12 +849,6 @@ bool CharacterController::getRigidBodyLocation(glm::vec3& avatarRigidBodyPositio
     return true;
 }
 
-void CharacterController::setFlyingAllowed(bool value) {
-    if (value != _flyingAllowed) {
-        _flyingAllowed = value;
-    }
-}
-
 void CharacterController::setCollisionlessAllowed(bool value) {
     if (value != _collisionlessAllowed) {
         _collisionlessAllowed = value;
diff --git a/libraries/physics/src/CharacterController.h b/libraries/physics/src/CharacterController.h
index d59374a94a..c46c9c8361 100755
--- a/libraries/physics/src/CharacterController.h
+++ b/libraries/physics/src/CharacterController.h
@@ -65,10 +65,10 @@ public:
     // overrides from btCharacterControllerInterface
     virtual void setWalkDirection(const btVector3 &walkDirection) override { assert(false); }
     virtual void setVelocityForTimeInterval(const btVector3 &velocity, btScalar timeInterval) override { assert(false); }
-    virtual void reset(btCollisionWorld* collisionWorld) override { }
-    virtual void warp(const btVector3& origin) override { }
-    virtual void debugDraw(btIDebugDraw* debugDrawer) override { }
-    virtual void setUpInterpolate(bool value) override { }
+    virtual void reset(btCollisionWorld* collisionWorld) override {}
+    virtual void warp(const btVector3& origin) override {}
+    virtual void debugDraw(btIDebugDraw* debugDrawer) override {}
+    virtual void setUpInterpolate(bool value) override {}
     virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTime) override;
     virtual void preStep(btCollisionWorld *collisionWorld) override;
     virtual void playerStep(btCollisionWorld *collisionWorld, btScalar dt) override;
@@ -90,7 +90,7 @@ public:
     void preSimulation();
     void postSimulation();
 
-    void setPositionAndOrientation( const glm::vec3& position, const glm::quat& orientation);
+    void setPositionAndOrientation(const glm::vec3& position, const glm::quat& orientation);
     void getPositionAndOrientation(glm::vec3& position, glm::quat& rotation) const;
 
     void setParentVelocity(const glm::vec3& parentVelocity);
@@ -129,7 +129,8 @@ public:
 
     bool getRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation);
 
-    void setFlyingAllowed(bool value);
+    void setZoneFlyingAllowed(bool value) { _zoneFlyingAllowed = value; }
+    void setComfortFlyingAllowed(bool value) { _comfortFlyingAllowed = value; }
     void setCollisionlessAllowed(bool value);
 
     void setPendingFlagsUpdateCollisionMask(){ _pendingFlags |= PENDING_FLAG_UPDATE_COLLISION_MASK; }
@@ -212,7 +213,8 @@ protected:
     uint32_t _pendingFlags { 0 };
     uint32_t _previousFlags { 0 };
 
-    bool _flyingAllowed { true };
+    bool _zoneFlyingAllowed { true };
+    bool _comfortFlyingAllowed { true };
     bool _collisionlessAllowed { true };
     bool _collisionless { false };