Why is this rigidbody jumping all the time?

Im trying to adapt @John’s first-person player-control system, the one from the built-in examples.

In the original code, you can move the player figure around and it will do an automatic jump whenever it hits a Craft block, but I must’ve gone wrong somewhere in my adaptation, because it seems to jump sometimes just from simple contact with the ground.

I’ve isolated the relevant code into the attached project, and it’s also available for cut-and-paste right here:

viewer.mode = FULLSCREEN

function setup()  
    assert(blocks, "Project requires Block"..
        " Library as a dependency")

function makeScene()
    craft.scene.main = craft.scene() 
    craft.scene.main.physics.gravity = 
        vec3(0,-14.8, 0)
    viewer = craft.scene.main.camera:add(
    craft.scene.main.camera.position =
        vec3(29.5, 14, 54)
    viewer.rx = 10

function makeGround()
    -- Setup voxel terrain.
    -- Because of the way Block Library works,
    -- making blocks requires a "scene" global
    scene = craft.scene.main
    _ = blocks()    
    local voxels = craft.scene.main.voxels
    voxels.coordinates = vec3(0,0,0)    
    -- Create ground out of grass
    --something to bump into, for testing jumps
    voxels:fill("Red Brick")
    voxels:box(20,11,30, 50,11,60)
    voxels:box(21,11,31, 49,11,59)

function makeOrc()
    --create orc
    orc = craft.scene.main:entity()
    orc.model = craft.model(asset.builtin.
    orc.position = vec3(29.5, 20, 66.5)
    orc.scale = vec3(0.12485, 0.12485, 0.12485)
    --add rigidbody the same size as the orc
    rb = orc:add(craft.rigidbody, DYNAMIC, 1)
    local size = orc.model.bounds.size
    size.x = size.x * orc.scale.x
    size.y = size.y * orc.scale.y
    size.y = size.z * orc.scale.z
    orc:add(craft.shape.capsule, size.x, 
    --set default rigidbody attributes
    rb.angularFactor = vec3(0,0,0)
    rb.sleepingAllowed = false
    rb.friction = 0.5
    rb.group = 1<<11
    rb.linearDamping = 0.97

--utility class for making touch handlers
TouchReceiver = class()
function TouchReceiver:init()
    touches.addHandler(self, -1, true)

--make "shouldApplyForce" true during touches
function makeTouchesTriggerForce()
    --make a touch receiver
    local touchToMove = TouchReceiver()
    --override its touched function
    function touchToMove:touched(touch)
        if touch.state ~= CANCELLED and 
        touch.state ~= ENDED then
            force = 10
            if touch.x > WIDTH / 2 then
                force = -10
            shouldApplyForce = true
            shouldApplyForce = false

function draw()
    --onscreen instructions
    text("Let orc come to a full stop, then",
        WIDTH / 2, HEIGHT - 65)
    text("tap to apply force left or right.",
        WIDTH / 2, HEIGHT - 90)
    text("Why is jump triggered so much?",
        WIDTH / 2, HEIGHT - 115)
    --apply force if shouldApplyForce
    if shouldApplyForce then
        if rb.linearVelocity.x < 5 and
        rb.linearVelocity.x > -5 then
            rb:applyForce(vec3(force, 0, 0)) 

    --make orc jump if it hits something
    if orcHitSomething() then

--use sphereCast to detect orc collisions
function orcHitSomething()
    local hitCheck = craft.scene.main.
            orc.position, vec3(0,-1,0), 0.5, 
            0.52, ~0, ~rb.group)
    local didHit = hitCheck and 
        hitCheck.normal.y < 0.5
    return didHit

--apply momentary boost of vertical force
function jump()
    local v = rb.linearVelocity
    v.y = 3.5
    rb.linearVelocity = v

Can anyone help me stop the figure from jumping all the dang time, so it works like it does in the built in example?

This doesn’t work on my iPad. When I run it, I’m way below the ground looking up at it.


Huh—this is how it looks for me.


By the looks of it you may have an issue with how the spherecast in orcHitSomething() works.

scene.physics:spherecast(origin, direction, distance, radius, group, mask)

Direction should point in the direction the orc is moving, radius could be slightly too big and catching the ground unintentionally. Distance shouldn’t be too big or it will jump prematurely. So you could try moving the origin, reducing the distance or radius and see if that helps

@John what’s the difference between distance and radius?

Think of a spherecast as a sphere of size radius starting at origin that travels in direction for the set distance (this forms a capsule) and stops at the first thing it hits. A smaller radius results in a thinner capsule, shorter distance = shorter capsule. Think of it as a kind of thick raycast

@John ok so in this case the origin is like the center of the orc model, and the sphere travels down to the bottom of its feet to basically sense if anything connects with its lower half.

@John ok I’m trying to calculate the right radius and distance and this seems to at least be stopping all the bouncing:

--use sphereCast to detect orc collisions
function orcHitTest()
    --make the sphere the model width
    local radius = orc.model.bounds.size.x * 
        orc.scale.x / 2
    --move the sphere for half the body height
    --MINUS the radius of the sphere so that
    --it doesn't go beneath his feet
    local distance = (orc.model.bounds.size.y *
        orc.scale.y / 2) - radius
    --check for contact with those settings
    local hitCheck = craft.scene.main.
            orc.position, vec3(0,-1,0), radius, 
            distance, ~0, ~rb.group)
    return hitcheck

Only problem is that now it’s not detecting the orc coming in contact with the wall! So before it jumped too much and now it doesn’t jump at all.

Attached is a modified project where you can move the orc in four directions and make it hit the wall.