Skip to content

Commit

Permalink
Add NaN protections for springs
Browse files Browse the repository at this point in the history
  • Loading branch information
dphfox committed Apr 15, 2024
1 parent b444e92 commit c37eb70
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 1 deletion.
44 changes: 44 additions & 0 deletions docs/api-reference/general/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,50 @@ object should be destroyed.

<div class="fusiondoc-error-api-section" markdown>

## springNanGoal

```
A spring was given a NaN goal, so some simulation has been skipped. Ensure no
springs have NaN goals.
```

**Thrown by:**
[`Spring`](../../animation/members/spring)

The goal parameter given to the spring during construction contained one or more
NaN values.

This typically occurs when zero is accidentally divided by zero, or some other
invalid mathematical operation has occurred. Check that your code is free of
maths errors, and handles all edge cases.
</div>

-----

<div class="fusiondoc-error-api-section" markdown>

## springNanMotion

```
A spring encountered NaN during motion, so has snapped to the goal position.
Ensure no springs have NaN positions or velocities.
```

**Thrown by:**
[`Spring`](../../animation/members/spring)

While calculating updated position and velocity, one or both of those values
ended up as NaN.

This typically occurs when zero is accidentally divided by zero, or some other
invalid mathematical operation has occurred. Check that your code is free of
maths errors, and handles all edge cases.
</div>

-----

<div class="fusiondoc-error-api-section" markdown>

## springTypeMismatch

```
Expand Down
12 changes: 12 additions & 0 deletions src/Animation/SpringScheduler.luau
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ local External = require(Package.External)
local packType = require(Package.Animation.packType)
local springCoefficients = require(Package.Animation.springCoefficients)
local updateAll = require(Package.State.updateAll)
local logWarn = require(Package.Logging.logWarn)

type Set<T> = {[T]: unknown}

Expand Down Expand Up @@ -65,11 +66,22 @@ local function updateAllSprings(
local isMoving = false

for index, goal in ipairs(spring._springGoals) do
if goal ~= goal then
logWarn("springNanGoal")
continue
end

local oldDisplacement = startDisplacements[index]
local oldVelocity = startVelocities[index]
local newDisplacement = oldDisplacement * posPos + oldVelocity * posVel
local newVelocity = oldDisplacement * velPos + oldVelocity * velVel

if newDisplacement ~= newDisplacement or newVelocity ~= newVelocity then
logWarn("springNanMotion")
newDisplacement = 0
newVelocity = 0
end

if math.abs(newDisplacement) > EPSILON or math.abs(newVelocity) > EPSILON then
isMoving = true
end
Expand Down
4 changes: 3 additions & 1 deletion src/Logging/messages.luau
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@ return {
possiblyOutlives = "%s could be destroyed before %s; review the order they're created in, and what scopes they belong to. See discussion #292 on GitHub for advice.",
propertySetError = "Error setting property: ERROR_MESSAGE",
scopeMissing = "To create %s, provide a scope. (e.g. `%s`). See discussion #292 on GitHub for advice.",
springNanGoal = "A spring was given a NaN goal, so some simulation has been skipped. Ensure no springs have NaN goals.",
springNanMotion = "A spring encountered NaN during motion, so has snapped to the goal position. Ensure no springs have NaN positions or velocities.",
springTypeMismatch = "The type '%s' doesn't match the spring's type '%s'.",
stateGetWasRemoved = "`StateObject:get()` has been replaced by `use()` and `peek()` - see discussion #217 on GitHub.",
unknownMessage = "Unknown error: ERROR_MESSAGE",
unrecognisedChildType = "'%s' type children aren't accepted by `[Children]`.",
unrecognisedPropertyKey = "'%s' keys aren't accepted in property tables.",
unrecognisedPropertyStage = "'%s' isn't a valid stage for a special key to be applied at.",
useAfterDestroy = "%s is no longer valid - it was destroyed before %s. See discussion #292 on GitHub for advice.",
useAfterDestroy = "%s is no longer valid - it was destroyed before %s. See discussion #292 on GitHub for advice."
}

0 comments on commit c37eb70

Please sign in to comment.