Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

CFrame-Intergrated Revolving-axis(es) - How?

My current game in development requires the use of 'laser distributors' and 'laser receptacles', additionally paired with several more custom-made items.
My current focus is on the distributor, which requires for the 'nozzle' or 'cannon' (/'launcher') brick to revolve in an orbit around the distributor's turret brick, always sticking inside-of the hull of the the brick in question.

The nozzle/cannon brick is required to make 90-degree rotations, always having one end of the brick (which is a cylinder) inside the hull; that doesn't mean that it can't move, just that it needs to appear-to-be in the hull at all times.

My current script, which has served me very well in the making of sliding-doors and hidden-panels, derived from the Roblox Wiki Article concerning Part Sliding is seen as below:

local Part = cannon -- this is the Part we will move
local newPos = Part.Position + Vector3.new(-2,0,2) -- the position the Part will go to
local Time = 5 -- the time that the script will take to move the part
local Increment = 0.05 -- the Part will move 0.05 studs each time it moves: smooth movements!
local Debounce = false
local Diff = newPos - Part.Position -- the difference between the two positions
local Mag = Diff.magnitude -- the distance between the two parts
local Direction = CFrame.new(Part.Position, newPos).lookVector
function MovePart() -- function to move the Part
	if Debounce then return end -- end the function if debounce is true
	Debounce = true -- make Debounce true so the function can't run
	for n = 0, Mag, Increment do
		Part.CFrame = Part.CFrame + (Direction * Increment)
		wait( (Time/Mag) * Increment )
	end
	Debounce = false
end
script.Parent.ClickDetector.MouseClick:connect(MovePart)

I have tried to modify it to suit my need of an additional 'rotationAxis' argument, but that has met a brick-wall. Figuratively, of course...

local Part = cannon -- this is the Part we will move
local newPos = Part.Position + Vector3.new(-2,0,2) -- the position the Part will go to
local Time = 5 -- the time that the script will take to move the part
local Increment = 0.05 -- the Part will move 0.05 studs each time it moves: smooth movements!
local Debounce = false
local Diff = newPos - Part.Position -- the difference between the two positions
local Mag = Diff.magnitude -- the distance between the two parts
local Direction = CFrame.new(Part.Position, newPos).lookVector

local RotationAngle = Part.CFrame * CFrame.Angles(-45, 0, 45)
local RotationAxis = RotationAngle * Direction 

function MovePart() -- function to move the Part
	if Debounce then return end -- end the function if debounce is true
	Debounce = true -- make Debounce true so the function can't run
	for n = 0, Mag, Increment do
		Part.CFrame = Part.CFrame + ( (Direction * Increment) * RotationAxis * Mag)
		wait( (Time/Mag) * Increment )
	end
	Debounce = false
end
script.Parent.ClickDetector.MouseClick:connect(MovePart)

And bearing in mind that the Roblox Wiki's document on this is really really hard to understand, I can't fit my needs properly - hence why I came here.

To recap, the subject of assistance: Rotation Axis and Orbits: How do I create such thing?
If you have a viable solution, that is appreciated. Smiley face.

After-Note: It seems like I have solved the problem Myself. Albeit a bit 'laggy' and 'un-optimised', it serves well. You'll see my answer to the post.

2 answers

✓ Accepted answer

Some tips for potentially smoother animation:

  • Use lerp to interpolate between two different CFrames. If you can get the starting and goal CFrames, perform newCFrame = startCFrame:lerp(goalCFrame, timePassed/animationTime) every frame/update.
  • Ideally you should use Heartbeat ) if you want very smooth animation. This will be faster than using wait() (which waits for about 0.03 seconds, which is about what you're waiting for at the moment).
  • math.rad(0) == 0 (so you could simplify line 7 if you wanted)

3 comments

0

Great answer! Sorry I couldn't get to you - a lot of stuff happening and me forgetting that this site exists... Anyway, I have a few questions: How would I integrate the Heartbeat Service into the lerp'ing? I already have a basic idea, " Part.CFrame = this.CFrame:lerp( (this.CFrame * fromEulerAngles(0, 90, 0) ), timePassed / animationTime)

0

game:GetService("RunService").Heartbeat:connect(function(waiting) return end) --Instantly ends to take up one frame... "

0

Looks like you've got the right idea. In the Heartbeat:connect line, instead of "return" you should have your code from your first comment. You'll need to increase 'timePassed' by 'waiting'.

Yay, solving my own conundrum!
Instead of using the Wiki's script as a base line, I just used a 'while' loop.

From there... it built this.

function performRotation()
	local n = 30
	local movementTime = 3	
	local movementIncrement = 0.1
	external = true
	while n == n do
		Part.CFrame = Part.CFrame * CFrame.Angles(math.rad(0), math.rad(3), math.rad(0))
		wait((movementIncrement / movementTime))
		n = n - 1
		if n == 0 then return end
	end
end
parent.clickDetector.MouseClick:connect(performRotation)

I siphoned the Increment and Time variables, did a bit of searching and threw in a few mathematical operators. And by golly it worked. If you guys want to take this, feel free.

This discussion is preserved as it was. New answers, comments, and votes are closed.