Unsure where NaN appears from in raycast bullet simulation

I’m trying to create a projectile system that simulates with raycasts, on each RenderStep.

I’ve just implemented air resistance into my system, but for higher velocities and drag coefficients, my projectiles behave strangely, and velocity prints as {nan, nan, nan}

I’m not really sure at all where these values come from, I thought they could only come from divide-by-zero errors, but I don’t divide by anything anywhere in my script.

(This function is a method of a class I’m creating, as far as I can tell this is the only relevant part of the script)

function METATABLE:CastShot(origin, direction, muzzleVelocity, dragCoefficient)--start is a position, goal is a position
	local onlyRaycastParams = RaycastParams.new()
	onlyRaycastParams.FilterType = Enum.RaycastFilterType.Exclude
	for i, v in LocalPlayer.Character:GetDescendants() do
		onlyRaycastParams:AddToFilter(v)
	end
	
	local startTime = tick()
	
	if not dragCoefficient then dragCoefficient = 0.01 end
	local verticalAcceleration = -34.9958
	

	
	local lastRay = nil
	local lastOrigin = nil
	local lastEndpoint = origin
	local endpointVelocity = direction * muzzleVelocity
	local RenderStepped
	RenderStepped = RunService.RenderStepped:Connect(function(dT)
		--[[This loop calculates the bullet's path based on a raycast fired in every renderstep.
		The reason the steps seem weirdly sized is because I wrote them on paper in mental steps,
		not based on how difficult they would be to code.]]
		local timeSinceStart = tick() - startTime
		if timeSinceStart > 15 then
			RenderStepped:Disconnect()
		end
		
		--1. Find origin point (Endpoint of last ray)
		local thisOrigin = lastEndpoint
		
		--2. Find velocity at last endpoint.
		local velocity = endpointVelocity
		
		--3. Solve for acceleration, based on wind resistance and gravity.
		
		local accelerationDueToGravity = Vector3.new(0, verticalAcceleration, 0)
		
		
		local attitude = (velocity.Unit)
		
		local density = 1.3--This is intended to be tweaked to make gameplay more realistic, but should not change during gameplay.
		local drag = (0.5) * density * (velocity.Magnitude^2) * dragCoefficient
		print(drag)
		local airResistance = attitude * -drag
		
		local acceleration = airResistance + accelerationDueToGravity
			
		--4. Modify velocity based off calculated acceleration.
		velocity = velocity + (acceleration * dT)
		
		--5. Solve for displacement (ray direction) based off calculated velocity.
		local displacement = velocity * dT
		
		--6. Cast Ray
		local renderStepRayCast = Raycast2:VisualRay(thisOrigin, displacement, onlyRaycastParams)
		
		--7. Code that executes if the ray has hit something.
		if renderStepRayCast then
			RenderStepped:Disconnect()
		end
		
		--8. Update Relevant Variables
		lastOrigin = lastEndpoint
		if renderStepRayCast then lastEndpoint = renderStepRayCast.Position else
			lastEndpoint = thisOrigin + displacement
		end
		endpointVelocity = velocity
		
	end)
end

If anyone wants to test the full script themselves, here are the necessary modules, to be put into ReplicatedStorage.
GunCast.lua (3.0 KB)
Raycast2.lua (1.5 KB)

The method is called by creating a Guncast.new() object, and then calling :CastShot on it, with origin working like raycast, BUT DIRECTION IS A UNIT VECTOR

If you are unable to replicated my NaN error, I get it when calling
caster:CastShot(Vector3.new(0, 15, 70), Vector3.new(10, 0, 0).Unit, 3000, 0.2)

Having dealt with NaN vectors millions of times myself, my instinctual first guess is that it’s the attitude variable. If you get the .Unit of a 0-vector it will give nan because the unit of a vector is itself divided by its magnitude, which, if 0, will divide by 0 and end up returning nan. since you are using this vector to calculate the acceleration and add it onto the velocity, the velocity will become nan in the end.

one workaround is checking if the magnitude of velocity is equal to 0 when setting attitude, if it’s not 0, you can safely use velocity.Unit, otherwise you should use an alternative vector (for example 0, -1, 0)

I tried this, but it didn’t work. It is something valuable though and is probably the cause of a different bug I had that I couldn’t fix, so thank you.

I did realize however, that the projectile’s velocity goes up for whatever reason, and then throws NaN when it hits inf. That is probably the cause of the NaN, but now I just need to find out why the velocity goes up exponentially.

i just copied the code and verified that it’s the drag does go up until hits infinity.
maybe i should actually looked at your code past the first few lines…

anyway, the ACTUAL culprit is the air density, which is extremely high, in real life the density of air at sea level is 0.002377 slugs/ft^3, if you set the air density to that value it will fix it and this time i have tried it, too.

works too, but i’m uncomfortable with how wacky it is. shouldn’t extremely high density just slow it down really quickly? i don’t like that there’s a bug that makes bullets behave like this that i don’t really understand

edit: zawg what the hell is a slug

if numbers are too high they will screw up things especially when doing physics calculations, 0.0023 vs 1.3 is a MASSIVE difference

a slug/ft^3 is the imperial version of kg/m^3, its a measure of density

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