Does Anyone know what is wrong with my code here?

I have been working on some code for a game I’m making which makes a part with minor wind physics and it works ok but keeps getting glitchy.

here is the code

--[[

Explaination on how to create the movement physics for a part by bettercat4

]]

--[[

Reflection formula

r = d - 2(d ⋅ n)n

Where ‘r’ is the resultant reflection normal, ‘d’ is the normal of 
our ray, and ‘n’ is the surface normal that our ray hit 
(n will be the value FindPartOnRay returns).

]]

--[[

to calculate the air resistance we need to direct a force that 
pushes the part in a direction that is perpendicular to the force, 
reflected off of the face.

we need to fire a ray from the negative move direction to the 
part and calculate the reflection of the result and use a vector 
force to move the part in the opposite direction of the reflection.
The force should be equal to about either two times the velocity, 
or equal to the velocity, or half of the velocity.

]]

local part = script.Parent
local pos1 = part.Position
local p1x = tonumber(string.format("%." .. (3 or 0) .. "f", pos1.X))
local p1y = tonumber(string.format("%." .. (3 or 0) .. "f", pos1.Y))
local p1z = tonumber(string.format("%." .. (3 or 0) .. "f", pos1.Z))
local pos2 = part.Position
local p2x = tonumber(string.format("%." .. (3 or 0) .. "f", pos2.X))
local p2y = tonumber(string.format("%." .. (3 or 0) .. "f", pos2.Y))
local p2z = tonumber(string.format("%." .. (3 or 0) .. "f", pos2.Z))
local pos3 = Vector3.new(p1x,p1y,p1z)
local pos4 = Vector3.new(p2x,p2y,p2z)

game:GetService("RunService").Heartbeat:Connect(function()

	local vel = part.Velocity
	local raystartpos = part.Position + (vel.Unit*100)
	local endpoint = part.Position
	local startpoint = raystartpos
	local distance = 200
	local direction = ((endpoint - startpoint).Unit) * distance
	local normal = -(vel.Unit)
	local raycastparams = RaycastParams.new()
	raycastparams.FilterType = Enum.RaycastFilterType.Whitelist
	raycastparams.IgnoreWater = true
	raycastparams.FilterDescendantsInstances = {part}
	local ray = workspace:Raycast(raystartpos,direction,raycastparams)

	--local ray2 = Ray.new(raystartpos,-(vel.Unit) * 500)
	--local hit, position, surfaceNormal = game.Workspace:FindPartOnRay(ray2) -- Cast ray

	if ray then

		local hit = ray.Instance
		local position = ray.Position
		local surfaceNormal = ray.Normal

		-- Get the reflected normal: (this is the formula applied)
		local ReflectedNormal = (direction - (2 * direction:Dot(surfaceNormal) * surfaceNormal))		
		-- Override our current normal with the reflected one:
		-- normal = reflectedNorma

		local resistance = (math.pi*part:GetMass())/2
		local vector = part.VectorForce
		vector.Force = -(ReflectedNormal.Unit * vel.Magnitude*(part:GetMass()+resistance))
	end
	
	if part.AssemblyLinearVelocity.Magnitude > 10000 then
		part.Anchored = true
		part.AssemblyLinearVelocity = Vector3.new(0,0,0)
		part.AssemblyAngularVelocity = Vector3.new(0,0,0)
		part.VectorForce.Force = Vector3.new(0,0,0)
	end
	
	--[[pos1 = part.Position
	p1x = tonumber(string.format("%." .. (3 or 0) .. "f", pos1.X))
	p1y = tonumber(string.format("%." .. (3 or 0) .. "f", pos1.Y))
	p1z = tonumber(string.format("%." .. (3 or 0) .. "f", pos1.Z))
	pos3 = Vector3.new(p1x,p1y,p1z)
	if pos3.Unit ~= pos4.Unit then
		print("move")
		print(pos3)
		print(pos4)
		local direction = pos3 - pos4
		local direction2 = direction.Unit
		local speed = direction.Magnitude
		local Raystartpos = part.Position + direction2
		local part = Instance.new("Part",workspace)
		part.Anchored = true
		part.CanCollide = false
		part.Position = Raystartpos
		wait(.1)
		part:Destroy()
		--local Raycast = workspace:Raycast(Raystartpos,)
		pos2 = part.Position
		p2x = tonumber(string.format("%." .. (3 or 0) .. "f", pos2.X))
		p2y = tonumber(string.format("%." .. (3 or 0) .. "f", pos2.Y))
		p2z = tonumber(string.format("%." .. (3 or 0) .. "f", pos2.Z))
		pos4 = Vector3.new(p2x,p2y,p2z)
	end]]
end)

--[[while wait() do
	
	local vel = part.Velocity
	local raystartpos = part.Position + (vel.Unit*100)
	local endpoint = part.Position
	local startpoint = raystartpos
	local distance = 200
	local direction = ((endpoint - startpoint).Unit) * distance
	local normal = -(vel.Unit)
	local raycastparams = RaycastParams.new()
	raycastparams.FilterType = Enum.RaycastFilterType.Whitelist
	raycastparams.IgnoreWater = true
	raycastparams.FilterDescendantsInstances = {part}
	local ray = workspace:Raycast(raystartpos,direction,raycastparams)
	
	--local ray2 = Ray.new(raystartpos,-(vel.Unit) * 500)
	--local hit, position, surfaceNormal = game.Workspace:FindPartOnRay(ray2) -- Cast ray

	if ray then
		
		local hit = ray.Instance
		local position = ray.Position
		local surfaceNormal = ray.Normal
		
		-- Get the reflected normal: (this is the formula applied)
		local ReflectedNormal = (direction - (2 * direction:Dot(surfaceNormal) * surfaceNormal))		
		-- Override our current normal with the reflected one:
		-- normal = reflectedNorma
		
		local resistance = 50
		local vector = part.VectorForce
		vector.Force = -(ReflectedNormal.Unit * vel.Magnitude*(part:GetMass()+(game.Workspace.Gravity/2)))
	end

	--[[pos1 = part.Position
	p1x = tonumber(string.format("%." .. (3 or 0) .. "f", pos1.X))
	p1y = tonumber(string.format("%." .. (3 or 0) .. "f", pos1.Y))
	p1z = tonumber(string.format("%." .. (3 or 0) .. "f", pos1.Z))
	pos3 = Vector3.new(p1x,p1y,p1z)
	if pos3.Unit ~= pos4.Unit then
		print("move")
		print(pos3)
		print(pos4)
		local direction = pos3 - pos4
		local direction2 = direction.Unit
		local speed = direction.Magnitude
		local Raystartpos = part.Position + direction2
		local part = Instance.new("Part",workspace)
		part.Anchored = true
		part.CanCollide = false
		part.Position = Raystartpos
		wait(.1)
		part:Destroy()
		--local Raycast = workspace:Raycast(Raystartpos,)
		pos2 = part.Position
		p2x = tonumber(string.format("%." .. (3 or 0) .. "f", pos2.X))
		p2y = tonumber(string.format("%." .. (3 or 0) .. "f", pos2.Y))
		p2z = tonumber(string.format("%." .. (3 or 0) .. "f", pos2.Z))
		pos4 = Vector3.new(p2x,p2y,p2z)
	end]]
--end

how it works is it is supposed to fire a raycast from the negative velocity direction and use a vectorforce to move it in the negative direction of the mirror of that raycast. I used a bullet reflection formula for making the mirror raycast and it seems to work ok at first but sometimes it seems to gather too much velocity eventually and then it goes crazy and starts to fly around everywhere.

also dont mind the part clipping through the ground and the other two parts i clicked on were examples of other failed versions. (2 of about 26 failed versions) I have tried using multiple other modules made by people with no avail and idk what to do now.

also the code is located inside of a part in the workspace with a vectorforce and attachment in it.

here is the link to the youtube version of this recording.

also the bit of code that says the following is to stop it if it hits a certain speed when it glitches.

	if part.AssemblyLinearVelocity.Magnitude > 10000 then
		part.Anchored = true
		part.AssemblyLinearVelocity = Vector3.new(0,0,0)
		part.AssemblyAngularVelocity = Vector3.new(0,0,0)
		part.VectorForce.Force = Vector3.new(0,0,0)
	end

Not sure what’s causing the issue, but why are you using such a high number (10000) for your magnitude check? 10000 studs/sec is pretty dang fast.

1 Like

it usually doesn’t get that fast while moving normally but it gets to very high speeds while it glitches and that is to stop it. and 10000 because I didn’t know what to put so I put something random. It would probably also work with 1000 as well. it actually activated while I was recording I think it anchored and stopped the part twice while going crazy.

edit: I think the speed check activated at about 1:30 and 2:20 in the video maybe.

You might be able to use math.clamp to help you keep it to a minimum in your calculations.

add it where? If you mean the speed check, that is not what my problem is. I implemented the speed check so there is a chance I can save the part if it goes crazy in dev mode. The speed check would not be in the final product because it would possibly hinder in the creation of builds within my game. I’m not quite sure where the problem is, I was hoping someone could help me figure it out. There is also a chance it comes down to an issue with the Roblox Raycasting but If not then I think the reason it goes crazy might be that it is occasionally returning the wrong results with the raycast since sometimes raycasts have trouble with moving parts.

But the math.clamp would limit it to a velocity that could be handled and not hinder anything that I can see.

Is the issue that the raycast is pointing upwards and isn’t hitting any object, causing your equation to apply too much force?

the raycast is blacklisted so that it only ever hits the part and it is constantly hitting the part in a loop but there is a chance that the movement of the part is causing the raycast to be inaccurate and hit the wrong spot on the part. if it misses the part that likely has no effect because it sends no data if it misses. if it hits the wrong spot on the part that is another story though because it would then calculate the mirror angle differently and angle the vector in the wrong direction. the speed should not be affected be a raycast error because when i set the speed it is unrelated to the raycast. the speed uses the velocity speed to be calculated. Im gonna try to see if I can use the formala directly with the velocity and no raycast but im not sure how to. if anyone can figure it out feel free to let me know.

just thought of a possible solution. I was originally gonna fire a raycast from 100 blocks away to allow for the raycast to hit the part while moving but i am going to try to fire from half the part size distance away instead to allow for a more accurate hit possibly. I will instead compensate for the raycast missing by re-firing the ray if it returns nill.

update: it still goes crazy and the ray isn’t missing the part. it may still be hitting the wrong location though.

update 2: I created a part that looks towards where the force is being applied and it is looking all over. based on these results I may have to give up on this strategy and try something new.