Hello again, recently figured a way to find a arbitrary point on a Rope Constraint, as of right now I have not seen anyone accomplish this as there’s no native way of doing so, so I felt the need to challenge myself. I’ve provided a game link to demo it if you’re interested, and a video.
If you’re interested in this sort of tech you can check out the followings below.
https://devforum.roblox.com/t/bypassing-particle-lod-rate-throttle/2446042 - Removes the LOD from Particle Rate property
https://devforum.roblox.com/t/tracking-roblox-particles/2425825 - Can track actual particles from Particle Emitters in-engine.
https://devforum.roblox.com/t/bypassing-forced-beam-lod/2426888/1 - Removes the segment LOD for beams
The Code
Scroll down to where you find EvalPointOnRC function to see usage
-- credits to nurokoi
local function IsNan(value)
return type(value) == `number` and value ~= value
end
local function HyperSolver(t, d)
local N = 1e6
local EAppx = (1 + 1/N) ^ N
local PE = EAppx ^ t
local PEIn = 1 / PE
local TCt = PE + PEIn - 2
local TSt = t * (PE - PEIn)
return t * (2 * TCt - TSt) / (TCt - TSt + (t * t) * d)
end
local function UnitizeDist(dist)
local CatA = (dist < 0.1 and ((2.3e-1 * dist + 1.344e-1) * (dist ^ 1.15))
or (dist < 0.9 and ((9.071e-2 + 1.462e-1 * dist - 1.962e-1 * dist * dist) * (dist / (1 - dist)))
or (math.exp(-1.243) * (dist * dist) / math.sqrt(1 - dist * dist))))
local ApproxT, InverseSq = dist / CatA, 1 / (dist * dist)
for _ = 1, 4 do -- 4 guess attempts should be more than enough
ApproxT = HyperSolver(ApproxT, InverseSq)
end
return dist / ApproxT
end
local function EvalCurve(x, l, a)
return a * (math.cosh((x - l) / a) - 1)
end
local function EvalPointOnRC(ropeConstraint : RopeConstraint, alpha : number)
assert(ropeConstraint.Attachment0 and ropeConstraint.Attachment1, `RC Attachments not prepared for {ropeConstraint}`)
local A0 = (ropeConstraint.Attachment0 :: Attachment).WorldCFrame
local A1 = (ropeConstraint.Attachment1 :: Attachment).WorldCFrame
local Length = ropeConstraint.Length
local A0Pos = A0:ToObjectSpace(A0).Position
local A1Pos = A0:ToObjectSpace(A1).Position
local AVec = A1Pos - A0Pos
-- welcome to where i spent a few days working on, enjoy & expect more down the line.
-- would provide the papers i went by and desmos playgrounds to make sense of all this
-- but it's completely idiosyncratic in workflow, evidently...
local D = math.sqrt(AVec.X ^ 2 + AVec.Z ^ 2)
local H = AVec.Y
local S = math.sqrt(Length * Length - H * H)
local CatA = S * UnitizeDist(D / S)
local XL = CatA * math.log(CatA * (math.exp(D / CatA) - 1) / (H + Length))
local ADs = A0Pos.Y - EvalCurve(0, XL, CatA)
local ADe = A1Pos.Y - EvalCurve(D, XL, CatA)
local X = D * alpha
local Y = EvalCurve(X, XL, CatA) + ADs + (ADe - ADs) * alpha
local Trans = A0Pos + X * Vector3.new(AVec.X, 0, AVec.Z).Unit + Y * Vector3.yAxis
Trans = A0:ToWorldSpace(CFrame.new(Trans))
local IsLinear = IsNan(Trans.X) or IsNan(Trans.Y) or IsNan(Trans.Z)
return (IsLinear and A0:Lerp(A1, alpha) or Trans).Position
end
local function CPointSpacing(ropeConstraint : RopeConstraint, numPoints : number)
local Result = {}
local PreP = EvalPointOnRC(ropeConstraint, 0)
local PreH = PreP.Y
for i = 1, numPoints do
local CTrans = EvalPointOnRC(ropeConstraint, i / numPoints)
local CHeight = CTrans.Y
local HDiff = math.abs(CHeight - PreH)
local PDiff = CTrans - PreP
local LA = HDiff ^ 2 + PDiff.Magnitude ^ 2
PreH = CHeight
PreP = CTrans
table.insert(Result, math.sqrt(LA))
end
return Result
end
local function EvalFixedDistPointsOnRC(ropeConstraint : RopeConstraint, intervalDistance : number, resolution : number?)
assert(ropeConstraint.Attachment0 and ropeConstraint.Attachment1, `RC Attachments not prepared for {ropeConstraint}`)
local A0 = (ropeConstraint.Attachment0 :: Attachment).WorldPosition
local A1 = (ropeConstraint.Attachment1 :: Attachment).WorldPosition
local Result = {}
local PointRes = math.max(resolution or 1e3, ropeConstraint.Length / intervalDistance) -- increased for better precision
local Accu = 0
local LastA = 0
for i, distance in ipairs(CPointSpacing(ropeConstraint, PointRes)) do
Accu += distance
if Accu >= intervalDistance then
local Alpha = i / PointRes
local Trans = EvalPointOnRC(ropeConstraint, (Alpha + LastA) / 2)
if (Trans - A0).Magnitude + (Trans - A1).Magnitude <= ropeConstraint.Length then
table.insert(Result, Trans)
end
Accu = 0
LastA = Alpha
end
end
return Result
end
(Multiple attachments sliding up & down)
Game Link : Ropeconstraint Point Finder - Roblox (Uncopylocked)