Alright. I may have just been to picky and probably have pushed it too far. I’ll see if I can just use someone’s solution and move on. Thank you for your help and patience with me, though. I think I honestly pushed the conversation too far, and now you’ve gotten tired of this. I have a headache, so I’ll just end the post.
Here a single use case for EasingStyle.Linear applied to up/down movement, and EasingStyle.Circular applied to rotation.
--=================================================================================
local runService = game:GetService("RunService"); -- the function used to animate the part/model
local runFunction = runService.Heartbeat; -- this is run on the server so we need Heartbeat over RenderStepped
--*** you must rename this to the part/model you want to movel!! ***
local object = workspace.Model_Rotate4; -- this is the path-name of the part/model to tween
local objectOrigin = object:GetPivot().Position; -- the origin position of the above part/model
local moveVector = Vector3.new(0,5,0); -- the number of x,y,z studs to move the part/model (
local rotateAxis = Vector3.yAxis; -- the rotation axis to spin the part/model around, thanks [5uphi](https://devforum.roblox.com/u/5uphi)
local rotateSpeed = math.pi*4; -- must be multiple of pi for complete rotations
local cFrame = CFrame.new(); -- an empty CFrame to apply the changes to
--=================================================================================
-- the range over which to tween the values (a sort of resolution in time steps)
local timeScale = 5;
-- time steps table iterator
local tableIndex = 1;
-- time steps table iterator direction (1= down, -1=up)
local tableDir = 1;
-- start value for time step interpolation
local timeMin = 0;
--end value for time step interpolation
local timeMax = 1;
-- this is our table of time steps going from timeMin->timeMax across timeScale seconds
local timeTable = {}; -- blank table to store our time steps
local timeTable2 = {}; -- blank table to store our time steps
--=================================================================================
-- this function creates a time step table from v1-v2 using Roblox's in-built
-- interpolation functions defined in Enum.EasingStyle and Enum.EasingDirection
--=================================================================================
local function makeTimeTable(v1 : number,v2 : number,t : number,es : number,ed : number)
-- this value is Tweened to create the time step values
local nv = Instance.new("NumberValue");
-- initialise the value from the supplied input or default to 0
nv.Value = v1 or 0;
-- initalise a local blank table to store the time steps, this is returned to our script
-- because originally I wanted to do separate interpolation methods for rotation and movement
-- i.e. Linear for movement and Circular for rotation (probably requires Modulating to achieve this)
local TimeTable={};
TimeTable[#TimeTable+1] = v1;
-- make a connection to changes in the nv value (i.e. the time steps)
nv.Changed:Connect(function(Progress)
-- everytime the Tween changes the nv value it is sent here
-- so we can store it in the time steps table
TimeTable[#TimeTable+1] = Progress;
end)
-- define these if they weren't provided in the function inputs
es = es or Enum.EasingStyle.Linear;
-- "In" means interp in one direction and in the first half of the Tween
ed = ed or Enum.EasingDirection.In;
-- create the TweenInfo, and put a delay in the start because it
-- doesn't initialise the first few values correctly otherwise (why this happens would be nice to know?)
local info = TweenInfo.new(t or 5,es,ed,0,false,3);
local tween = game.TweenService:Create(nv,info,{Value=v2 or 1});
-- play the tween, wait for it to complete, and destroy it...
tween:Play();
tween.Completed:Wait();
tween:Destroy();
-- get rid of this locally allocated NumberValue (nv) instance
-- (always good to do this, regardless of garbage collection methods)
nv:Destroy();
-- we can't destroy TweenInfo so set to nil i.e. deallocate
-- (always good to do this, regardless of garbage collection methods)
info = nil;
-- we now have a time step table interpolated with Roblox's in-built methods
-- infinitely re-usable every time a new method is added, return this to the caller
return TimeTable;
end
-- Call the above function here so we get a one time initialisation of the time step table
timeTable = makeTimeTable(timeMin,timeMax,timeScale,Enum.EasingStyle.Linear);
timeTable2 = makeTimeTable(timeMin,timeMax,timeScale,Enum.EasingStyle.Circular);
local iteratorMax = math.min(#timeTable,#timeTable2);
--=================================================================================
-- connect the script to a frame stepper (Heartbeat can run on the server, RenderStepped is run on the client)
--=================================================================================
runFunction:Connect(function(deltaTime)
-- the moveOffset is the time step * our moveVector defined above
local moveOffset = timeTable[tableIndex]*moveVector;
-- accumulate the cframe changes in a blank cframe otherwise we may drift
cFrame = CFrame.fromAxisAngle(rotateAxis,rotateSpeed*timeTable2[tableIndex]*tableDir);
-- pivot the part/model to place and apply the rotation in one go
object:PivotTo(cFrame + objectOrigin + moveOffset);
-- increase the time step table iterator index
tableIndex += tableDir;
-- check for wrap and change the direction of the time step iterator
if tableIndex == iteratorMax or tableIndex == 1 then
tableDir *= -1;
end
end)
--=================================================================================
-- EOF...
--=================================================================================
Oh… this worked perfectly. I assume I did something wrong before and didn’t understand much about what was going on, but this is actually exactly what I was looking for.
I’m sorry for the misunderstanding along the way, and thank you so much for your help.