I'm trying to smoothly rotate an object back to its original Y angle if it goes over a certain amount of degrees (15) away from the start angle. I tried to do this, but I am not very good at all when is comes to positions or orientations of an object.
local StartAngle = script.Parent.Orientation.Y while true do local Angle = script.Parent.Orientation.Y if Angle >= StartAngle +15 then Angle = Angle-4 elseif Angle <= StartAngle-15 then Angle = Angle +4 end end
This probably isn't even close to what I'm trying to accomplish, but what am I doing wrong?
Your Angle
is just a local variable, so changing it won't have any effect on the actual parent Part
. You could use your Angle
to modify script.Parent.CFrame
directly as a function of time, but this doesn't really account for continuing interactions with other parts, and can even result in overlapping parts. To do this in a more physics-like way, the two options are BodyAngularVelocity
, which will have the object attempt to move at a certain rate of angle per time, or BodyGyro
, which will apply a given torque to the object to attempt to move it toward a certain orientation.
So here's one possible try, using a BodyAngularVelocity
. It assumes you've put a BodyAngularVelocity
as a child of the Part using Roblox Studio, leaving the default Name to match the ClassName. Not tested!
local part = Script.Parent local StartAngle = part.Orientation.Y local triggerAngle = math.rad(15) local angVelocity = part:WaitForChild("BodyAngularVelocity") -- 10 degrees per second; play with this local angSpeed = math.rad(10) -- maxTorque influences how strongly the part can push against other -- parts in its way to achieve the rotation. At lower values, you -- might see a smoother start of motion even if nothing is still -- pushing the part due to just the part's own inertia. -- You can try maxTorque = math.huge to have it not slow down for -- anything, but if multiple "absolute" settings like this conflict, -- it can lock up the physics system. local maxTorque = 100 -- Sign of the angle difference that caused rotation to start, -- or zero when not active. local angSign = 0 -- Initially, no angular velocity enforced: angVelocity.AngularVelocity = Vector3.new() angVelocity.MaxTorque = 0 -- Difference between two angles, in the range -pi to pi. local function AngleDiff(angle1, angle2) local diff = math.modf(angle1 - angle2, 2*math.pi) if diff <= math.pi then diff = diff + 2*math.pi elseif diff > math.pi then diff = diff - 2*math.pi end end local function update() local diff = AngleDiff(part.Orientation.Y - StartAngle) if angSign == 0 then if math.abs(diff) >= triggerAngle then angSign = math.sign(diff) angVelocity.AngularVelocity = -angSign * angSpeed * Vector3.FromAxis(Enum.Axis.Y) angVelocity.MaxTorque = maxTorque end -- The part won't necessarily reach EXACTLY StartAngle, -- so check if it has reached OR overshot. elseif math.sign(diff) ~= angSign -- End the effects. angVelocity.AngularVelocity = Vector3.new() angVelocity.MaxTorque = 0 angSign = 0 end end -- Set the update function to run once per physics engine update: local RunService = game:GetService("RunService") RunService.Heartbeat:Connect(update)