Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
1

How do I rotate an object back to its original angle if moved?

Asked by 5 years ago

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?

1 answer

Log in to vote
0
Answered by
aschepler 135
5 years ago

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)
0
I tried this and first, it came up with the error on line 24: expected vector3, got number. So I then changed it to Vector3.new(0), and it was fixed. Second, it came up with the error on line 28:attempt to perform arithmetic on local 'angle2' (a nil value), and thats where I'm at now KingCheese13 21 — 5y
Ad

Answer this question