AstraTween - Beginner-Friendly Client & Model Tweening Module

IMPORTANT NOTE:

AstraTween Version 2 is current under development. AT V1 is VERY prone to breaking, so do not use it for production titles yet! This post will be updated once V2 comes out.

AstraTween

An 100% free, open source, easy to install, and easy to use client and model tweening module to help your game’s visual smoothness.

AstraTween is a pretty simple TweenService wrapper and model tweener that allows you to move tweens from the server to the client for visual clarity and performance reasons. It is not a full rewrite of TweenService nor does it use anything such as boatbomber’s BoatTween. I’d still heavily suggest looking into learning and using those options, but this is meant as a beginner-friendly option that doesn’t involve too much learning. If you know how to use TweenService, you can use AstraTween!


🤔 About AstraTween

What is AstraTween?

AstraTween is a client tweening module that allows you to improve your game’s tweening quality by shifting the processing cost of tweens from the client to the server.


What is Client Tweening? Why should I use it?

TweenService runs on whatever context it is called on. For some applications such as tweening Value objects that are server-only, this is OK. But for moving parts in Workspace, this can create jittery animations that can break immersion and not look very cool. Client Tweening fixes this jitter by making YOUR client do all the work instead of having to rely on Roblox’s servers!


What is model tweening?

Model Tweening is the act of using the Model class’s PivotTo method to smoothly tween entire models without having to spam WeldConstraints or use other methods which are pretty difficult to set up. AstraTween comes built in with TweenModel, which allows for smooth tweening of any fully-anchored model with a PrimaryPart set.


Where should I use AstraTween?

AstraTween is intended to be used on any existing server-sided tween that is visible on the client. Note that this does not include UI, as UI should be tweened client-side in most cases. For the cases where you do tween UI on the server for some reason, then AstraTween would be applicable.

📁 Setup & Usage

Setup Instructions


Method 1 - Model

Install the model here and place it into ReplicatedStorage. Press Control+U to ungroup the scripts, and then place AstraTweenLocal into StarterPlayerScripts. If you parent AstraTween to anywhere else than just game.ReplicatedStorage, make sure to update the parent on line 1 of the LocalScript.


Method 2 - GitHub

First, go to the GitHub repository here and locate the /src folder.

Copy and paste /src/ServerModule.lua's source code into a new ModuleScript parented anywhere inside of ReplicatedStorage. Name this ModuleScript AstraTween or something else you can remember.

Copy and paste /src/ClientScript.lua's source code into a new LocalScript parented anywhere inside of StarterPlayerScripts. Name this AstraTweenLocal.

Lastly, go into the LocalScript and change the rootPath variable on line 1 to wherever the server module is parented to. Do not set this to the module itself, but to its parent.


Using AstraTween

You can use AstraTween from any script that runs server-side. Require it with local AstraTween = require(game.ReplicatedStorage.AstraTween) (or whatever path you parented it to) and call any of the methods in :books: Documentation on it. You cannot use AstraTween on the client.


📚 Documentation

AstraTween:TweenModel(model, time, style, direction, goalPosition)

model : Model - The model you are tweening. The model tweens from its PrimaryPart, so make sure that’s set!

time : number - How long the tween takes to finish in seconds.

style : Enum.EasingStyle - The style of the animation. See this page for more info.

direction : Enum.EasingDirection - The direction of easing. See this page for more info.

goalPosition : CFrame or Vector3 or Part/MeshPart/Union - The end CFrame of the model’s PrimaryPart. You can pass in a Vector3 to maintain orientation or pass in a BasePart, Union, or MeshPart to use it’s CFrame as the argument.


AstraTween:TweenInstance(target, time, style, direction, goalTable)

target : Instance - The target of the tween.

time : number - How long the tween takes to finish in seconds.

style : Enum.EasingStyle - The style of the animation. See this page for more info.

direction : Enum.EasingDirection - The direction of easing. See this page for more info.

goalTable : {Prop = endValue, Prop2 = endValue2, ...} - A table describing the end values of the tween. Identical to the one used in TweenService:Create().


AstraTween:TweenInstanceFull(target, time, style, direction, repeatCount, reverses, delayTime, goalTable)

target : Instance - The target of the tween.

time : number - How long the tween takes to finish in seconds.

style : Enum.EasingStyle - The style of the animation. See this page for more info.

direction : Enum.EasingDirection - The direction of easing. See this page for more info.

repeatCount : number - How many times the tween repeats. Set to -1 to repeat infinitely.

reverses : boolean - Does the tween reverse back to the start after finishing?

delayTime : number - If repeatCount isn’t 0, how long should the delay be between repeats?

goalTable : {Prop = endValue, Prop2 = endValue2, ...} - A table describing the end values of the tween. Identical to the one used in TweenService:Create().



Feedback & Limitations

Got feedback? Does my code suck? Let me know in the replies and I’ll try to address any issues that may arise! (There are bound to be bugs since this is my first FOSS creation I’ve posted here.)

AstraTween does have some limitations. You can’t make Tween “objects” like you can with TweenService, which removes the functionality to Stop, Pause, or otherwise manipulate Tweens once they are created.

6 Likes

Seems promising but aren’t you supposed to record a showcase of how it works?

Ah right, I’ll record a few videos and put them onto the post later tonight

must have forgotten at the time :sweat_smile:

You still have the videos? I do want to see it in action.

3 Likes

Keeping it real - I completely forgot about this! Apparently there’s a pretty major bug that completely breaks the client-tweening so I’m looking into that before I update this post. I’ll mention you here when it’s ready!

IMPORTANT NOTES

AstraTween Version 2 is currently under development. This version will help simplify AstraTween’s use, remove bloat code, and fix some pretty major issues with the code. It will also help improve the in-forum documentation with visuals!

I don’t have an expected release date, but please stay tuned. You can use AstraTween V1 as it stands, but be aware that it is prone to breaking in its current state.

Thank you all for your patience!

1 Like

Ah, thank you! That was probably the cause of the client tween part breaking!

It seems like the model tweening only works properly with non oriented parts, any solution to this?

I solved my own problem here.
For anyone running into the same issue, I’ve worked out a way to preserve model pivot and orientation.

Replace the executeTweenModel function on the client with my modified one:

local function executeTweenModel(model, time, style, dir, EndV3)
	local tempV3V = Instance.new("Vector3Value")
	tempV3V.Value = model.PrimaryPart.Position
	
	local ti = TweenInfo.new(time, style, dir)
	
	local connection = tempV3V.Changed:Connect(function(NewV3)
		model:PivotTo(CFrame.new(NewV3) * model:GetPivot().Rotation)
	end)
	
	local tween = ts:Create(tempV3V, ti, {Value = EndV3})
	tween:Play()
	tween.Completed:Connect(function()
		connection:Disconnect()
		tempV3V:Destroy()
	end)
end

And replace the AstraTween:TweeenModel in the module with this:

function AstraTween:TweenModel(model:Model, time:number, style:Enum.EasingStyle, direction:Enum.EasingDirection, goalPosition)
	local model = AstraTween:checkModel(model)
	local style = AstraTween:checkStyle(style)
	local dir = AstraTween:checkDir(direction)

	if model.PrimaryPart then
		AstraTween:getRemote("FireClientTweenModel"):FireAllClients(model, time, style, dir, goalPosition)
		task.delay(time, function()
			model:PivotTo(CFrame.new(goalPosition) * model:GetPivot().Rotation)
		end)
	else
		warn("Model does not have a PrimaryPart!")
		return
	end
end
2 Likes