How to make a program for a Torsion Spring

I am trying to make a rotational recoil system but my code currently doesn’t work as it is too fast
how do I make a better torsion recoil

RunService = game:GetService("RunService")
spring = {
	Target = script.Parent.Position,
	OriginalOrientation = script.Parent.Orientation,
	
	Position = script.Parent.Position,
	Orientation = script.Parent.Orientation,
	
	Velocity = Vector3.new(0,0,0),
	AngularVelocity = Vector3.new(0,0,0),
	
	Mass = 10,
	VectorForce = 50,
	AngularForce = 1,
	Damping = 4,
	Speed = 5  	
}
ITERATIONS = 8

function shoveSpring(force,orient)
	spring.Velocity = spring.Velocity + force
	spring.AngularVelocity = spring.AngularVelocity + orient * 10000
end

function updateSpring(dt)
	local scaledDeltaTime = math.min(dt,1) * spring.Speed / ITERATIONS
	for i = 1,ITERATIONS do
		local distance         = spring.Target - spring.Position -- get the inverse distance from orgin
		local acceleration  = (distance * spring.VectorForce) / spring.Mass -- hookes law and F = ma
           
		acceleration        = acceleration - spring.Velocity * spring.Damping --dampening this to prevent oscilation
           
		spring.Velocity   = spring.Velocity + acceleration * scaledDeltaTime -- use acceleration to factor in velocity
		spring.Position   = spring.Position + spring.Velocity * scaledDeltaTime -- use velocity to determine position
		
		local angle = spring.OriginalOrientation - spring.Orientation -- inverse angle from orgin
		local angularForce = (angle * spring.AngularForce) -- hookes law
		
		local angularAcceleration = angularForce / spring.Mass -- spring.AngularVelocity * spring.Damping
		
		spring.AngularVelocity = spring.AngularVelocity + angularAcceleration * scaledDeltaTime
		spring.Orientation = spring.OriginalOrientation + spring.AngularVelocity * scaledDeltaTime
		print(angle,angularAcceleration)
	end
	return (CFrame.new(spring.Position) * CFrame.fromEulerAnglesYXZ(math.rad(spring.Orientation.X),math.rad(spring.Orientation.Y),math.rad(spring.Orientation.Z)))
end


RunService.Heartbeat:Connect(function(dt)
	local coordinateframe = updateSpring(dt)
	script.Parent.CFrame = coordinateframe
end)
wait(2)
shoveSpring(Vector3.new(0,0,0),Vector3.new(3,3,3))

I took the code from blackshibe but this still isn’t working.

1 Like

Actually so I made this like nine months ago bot I got a fix and an improvement to this so I am just going to paste it here.

ITERATIONS = 8

local springModule = {}

springModule.__index = springModule

function springModule.new(mass,position,vectorForce,damping,speed,orientation,angularForce,angularDamping,angularSpeed)
	local spring = {
		Target = position or Vector3.new(),
		OriginalOrientation = orientation or Vector3.new(), -- keep this in radians
		
		Position = position or Vector3.new(),
		Orientation = orientation or Vector3.new(),
		
		Velocity = Vector3.new(0,0,0),
		AngularVelocity = Vector3.new(0,0,0),
		
		Mass = mass or 5,
		VectorForce = vectorForce or 50,
		AngularForce = angularForce or .3,
		
		Damping = damping or 5,
		AngularDamping = angularDamping or .2,
		
		Speed = speed or 4,
		AngularSpeed = angularSpeed or 60
	}
	setmetatable(spring,springModule)
	return spring
end


function springModule:Shove(force,orient)
	self.Velocity = self.Velocity + force
	self.AngularVelocity = self.AngularVelocity + orient
end

function springModule:Update(dt)
	for i = 1,ITERATIONS do
		local scaledDeltaTime = math.min(dt,1) * self.Speed / ITERATIONS
		local distance         = self.Target - self.Position -- get the inverse distance from orgin
		local acceleration  = (distance * self.VectorForce) / self.Mass -- hookes law and F = ma

		acceleration        = acceleration - self.Velocity * self.Damping --dampening this to prevent oscilation

		self.Velocity   = self.Velocity + acceleration * scaledDeltaTime -- use acceleration to factor in velocity
		self.Position   = self.Position + self.Velocity * scaledDeltaTime -- use velocity to determine position


		scaledDeltaTime = math.min(dt,1) * self.AngularSpeed / ITERATIONS
		local angle = self.OriginalOrientation - self.Orientation -- angle from current orientation to the target
		local angularForce = (angle * self.AngularForce) -- hookes law

		local angularAcceleration = (angularForce / self.Mass) - (self.AngularVelocity * self.AngularDamping)

		self.AngularVelocity = self.AngularVelocity + angularAcceleration * scaledDeltaTime
		self.Orientation = self.Orientation + self.AngularVelocity * scaledDeltaTime

	end
	return (CFrame.new(self.Position) * CFrame.fromEulerAnglesYXZ(math.rad(self.Orientation.X),math.rad(self.Orientation.Y),math.rad(self.Orientation.Z)))
end

return springModule

2 Likes