Addition of delta time destroys drag and thrust equations

Hi guys! (first devforum post btw)

  1. What do you want to achieve? Keep it simple and clear!
    I want to achieve a realistic flight physics system, but more specifically to this point, I wish to make it so that when the throttle is pulled up, the forward velocity moves up to that point. (Eg. engine levels of 20% will only cause a forward velocity of 20 studs/sec, and increasing throttle will cause higher forward velocity).

  2. What is the issue? Include screenshots / videos if possible!
    The addition of delta time into my physics calculations solve a bug that I was having (drag overshooting the required drag force), but by solving this bug this new bug has came up, where the forward velocity runs away and the drag force is unable to compensate. (20% causes that 20 studs/sec forward velocity, and then this forward velocity rapidly increases continually.)

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I have tried as much as I can, but I don’t understand why this would cause any problems. I did look for solutions, found none.

Here is my code:

local function runThrust(dt)
	
	-- rudimentary fcs
	localMovementVector += Vector3.new(0,0,-thrust * dt)
	
end

local function runDrag(dt)
	
	local airDensity = 0.01
	local dragTweak = 6
	
	-- runaway drag from thrust
	local dragX = (PlaneVelocity.X ^ 2) * dragPerFace.x * 0.5 * airDensity * dt * dragTweak
	local dragY = (PlaneVelocity.Y ^ 2) * dragPerFace.y * 0.5 * airDensity * dt * dragTweak
	local dragZ = (PlaneVelocity.Z ^ 2) * dragPerFace.z * 0.5 * airDensity * dt * dragTweak
	
	warn(dragX,dragY,dragZ)
	localMovementVector += Vector3.new(-dragX,-dragY,dragZ)
	
end

CONTEXT: This is run in a looping function called on Heartbeat, where the “localMovementVector” is set to Vector3.zero at the start, updated throughout the different steps, and then finally the vectorforce is set to this movement vector.
Removing the “* dt” everywhere will cause it to return back to expected functionality, with the drag overshooting problem (which is severe).

Loop code:

local function heartbeat(dt)

	prevMovementVector = aircraftMainPart.VectorForce.Force
	localMovementVector = Vector3.zero

	-- Physics Runtime
	mouseControl()
	runControlSurfaces()
	runLift(dt)
	runDrag(dt)
	runThrust(dt)

	aircraftMainPart.VectorForce.Force = localMovementVector

end

This still hasn’t been answered, so I wanted to close it up with this:

I didn’t end up going with this plane kit variation and instead recoded it from scratch with another method. The way I went about it seemingly caused mass overshooting and while I still do not know why (and would love to know, by the way), I would advise anyone pursuing the same path to ditch this method of going about procedural force calculations.

Instead, perhaps predictions and applying delta time to those may prove more beneficial.

The topic will remain open since it would be great to receive an answer to help others doing the same thing, but for now this thread has been abandoned.

Yep, multiplying by delta time is incorrect for force equations. You only multiply if you are going to solve for acceleration and velocity through numerical integration.

    acceleration = force / mass
    change in position = velocity * dt
    change in velocity = acceleration * dt

So this doesn’t make sense to me.

If you want it to be framerate independent (which I’m assuming why you are multiplying by dt) and prevent too much drag at low fps you will need to do some physics substepping or manually calculate the next acceleration and velocity and basically recreate the physics engine manually.

I found out it is alright for linear movement (force) for the angular movement (moment) such as rotation it’s complicated because instead of just 1 mass number you are dealing with inertia tensor in a 3x3 matrix which is more complicated and I haven’t solved it yet.

Example physics substep for my character controller to replicate humanoid hipheight and how they levitate:

        local upwardForce = calculateForces(targetHeight, currentHeight, currentYVelocity, t, mass, hipHeight, dt)

        local function physicsSubstep(substepUpwardForce, step, substepYVelocity, iterateHeight)
            local netForce = substepUpwardForce  - weight

            local predictedVelocity = predictVelocity(netForce, mass, substepYVelocity, step)
            local predictedDisplacement = predictDisplacement(netForce, mass, substepYVelocity, step)

            local newUpwardForce = calculateForces(targetHeight, iterateHeight+predictedDisplacement, predictedVelocity, t, mass, hipHeight, dt)
            local averageVelocity = (substepYVelocity+predictedVelocity) * 0.5
            local averageForce = (newUpwardForce+ substepUpwardForce)*0.5
            local averageHeight = iterateHeight+predictedDisplacement*0.5

            return averageForce, averageVelocity, averageHeight
        end

        --Perform physics substep
        local iterateForce = upwardForce
        local iterateYVelocity = currentYVelocity
        local iterateHeight = currentHeight
        local n = 3
        local step = dt/n
        for _ = 1, n-1 do
            iterateForce, iterateYVelocity, iterateHeight = physicsSubstep(iterateForce, step, iterateYVelocity, iterateHeight)
        end
        upwardForce = iterateForce

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.