Tweening Locally with welded parts

You can do the following:

  • group the parts you want to weld into a model
  • set the primary part of the model to one of the parts
  • create a cframe value and tween its value to the target cframe
  • :SetPivot() of the model everytime the cframe value changes using the Changed event
2 Likes

This also sounds like a good idea. Will it be the way I locally tween it now?

As long as you set the primarypart to the part you are already tweening.

You have variety of ways to tween a whole model. One of which would be

  • Group all parts that you want to move into a model and make the model have a primary part
  • Weld all the parts of the model to its primary part
  • Unanchor all the parts except the primary part
  • Tween the primary part of the model using the part CFrame

Other way would be to use some sort of a module that moves Models

That is the way I am doing it now. Welded parts does not move with the primary part when I am tweening locally.

I am unsure how to make welded parts move with the primary part when tweeing locally.

I’ve whipped up a quick module which allows you to tween models with just a single function and some content data.

The module scripts consists of:

-- services
local tweenService: TweenService = game:GetService("TweenService") :: TweenService

-- variables
local defaultTweenInfo: any = {
	Time = 1,
	EasingStyle = "Sine",
	EasingDirection = "Out",
	RepeatCount = 0,
	Reverses = false,
	DelayTime = 0,
}

-- functions
return function(model: Model, content: any)
	local cframeValue: CFrameValue = Instance.new("CFrameValue") :: CFrameValue
	cframeValue.Value = model:GetPivot()

	local cframeChangedConection: RBXScriptConnection = cframeValue:GetPropertyChangedSignal("Value"):Connect(function()
		model:PivotTo(cframeValue.Value)
	end) :: RBXScriptConnection
	
	local cframeChangeTween: Tween = tweenService:Create(
		cframeValue,
		TweenInfo.new(
			content.TweenInfo.Length :: number,
			Enum.EasingStyle[content.TweenInfo.Style] :: Enum.EasingStyle,
			Enum.EasingDirection[content.TweenInfo.Direction] :: Enum.EasingDirection,
			content.TweenInfo.Repeats :: number,
			content.TweenInfo.Reverse :: boolean,
			content.TweenInfo.Delay :: number
		),
		content.Properties
	)

	cframeChangeTween:Play()
	cframeChangeTween.Completed:Wait()

	cframeChangedConection:Disconnect()
	cframeValue:Destroy()
end

The module simply creates a new CFrameValue and then tweens the Value property of it. Then a signal detects when a change is made to the CFrameValue and then uses the :PivotTo method to move the actual model ( As others have mentioned above I believe )

This module is great because it means you don’t have to go out of your way to weld anything. The module also accommodates for float point problems. This means you won’t have tiny gaps beween the parts in the model over extensively using the function; Perfect for a train system:

image

The video is an example of a train which just moves on a straight line. Of course this train could be anything, a car, boat, roller coaster or even a penguin! And it can certainly move in more ways than just a straight line!

Now, the LocalScript consists of a very simple call of the function:

-- services
local replicatedStorage: ReplicatedStorage = game:GetService("ReplicatedStorage")

-- modules
local tweenModel: any = require(replicatedStorage:WaitForChild("Tween Model", 100) :: ModuleScript) :: any

-- functions
tweenModel(workspace.Train, {
	TweenInfo = {
		Length = 5,
		Style = "Sine",
		Direction = "Out",
		Repeats = 0,
		Reverse = false,
		Delay = 6,
	},
	Properties = {
		Value = CFrame.new(46, 6.75, 1.5),
	},
})

The second argument you see in the tweenModel function is the content data I mentioned earlier. It consists of two other tables within it. Which of being TweenInfo and Properties. The TweenInfo table controls how the model will actually move.

Tweeninfo table

  • The Length is how long the tween takes.
  • The Style is how it moves from point a to point b ( here is a link to view the different styles )
  • The Direction is how the style is converge from point a to point b ( here is a link to view the different directions )
  • The Repeats is how many times the tween will repeat.
  • The Reverse is if the tween is supposed to reverse after it has been completed.
  • The Delay is how much time passes before playing the tween.

Properties table.

The properties table only contains one value ( which is to be fed in ) This value is called, well… Value. This is the value that the CFrameValue will use to tween using the TweenInfo data.

I hope this helped even a little in your endeavour of creating your roller coaster project.

3 Likes

Wow…

Thank you for doing this all for me! Will this tween locally or on the server? If not how can I make it tween locally so I can make it the smoothest for the players.

I will give this module a try now and let you know how I got on. :smile:

1 Like

It works both on the server and on the client. I mentioned in my reply that I used a LocalScript to run the function. If you want to know how to transmit data from the server to the client, I would personally use RemoteEvents to do that.

If you need anything else, let me know! :+1:

Ah sorry I didn’t quite understand.

At the moment I am using RemoteEvents as I followed this tutorial. This of course makes it so on the server the part is just moving to the location at the end of the tween but on the client it is tweening and moving smoothly.

How would I make it do that with your module? If it does not already do that. Sorry if it does I am just about to try it out :slight_smile:

Thanks.

1 Like

Well my module is well… a Module class as seen here:
image

After using the require function as such local tweenModel: any = require(PATH_WAY_HERE) the variable tweenModel will be a function which you can use. As shown in this demonstration:

tweenModel(workspace.Train, {
	TweenInfo = {
		Length = 5,
		Style = "Sine",
		Direction = "Out",
		Repeats = 0,
		Reverse = false,
		Delay = 6,
	},
	Properties = {
		Value = CFrame.new(46, 6.75, 1.5),
	},
})

I see the video you linked. There seems to be a LocalScript named “LocalTween” within ReplicatedFirst. The function takes in the arguments; instance, tweeninfo and properties. You can replace all the code within that function with something like this:

tweenModel(instance, {
	TweenInfo = {
		Length = tweenInfo.Time,
		Style = tweenInfo.EasingStyle,
		Direction = tweenInfo.EasingDirection,
		Repeats = tweenInfo.RepeatCount,
		Reverse = tweenInfo.Reverses,
		Delay = tweenInfo.DelayTime,
	},
	Properties = {
		Value = properties.CFrame,
	},
})

So if you fire the RemoteEvent ( From the server of course ), it should look a little something like this:

localTweenEvent:FireAllClients(COASTER_MODEL, {
    { Time = 1, Style = "Sine", Direction = "Out", Repeats = 0, Reverse = false, Delay = 0, }, -- change the tween info based on the settings you already set
    { CFrame = ... } -- change the value to where you want to tween the coaster.
})

I obviously don’t know how your code is written so it’s hard to guess how I can help. But I hope this pushes you in the right direction. If you need anything else, let me know :+1:

I am pretty lost.

I am going to first start with just seeing if I can use your module to just get the model moving forward (Like in your demonstration)

So first I setup your module by making a Model in the Workspace and calling it Train. Inside the Model I have 4 parts. One of them being called Main then the others called Tail (Like yours)

  • All of the parts inside the model are Anchored.

image

Also in the Workspace I have a LocalScript called LocalScript with this code inside:

-- services
local replicatedStorage: ReplicatedStorage = game:GetService("ReplicatedStorage")

-- modules
local tweenModel: any = require(replicatedStorage:WaitForChild("Tween Model", 100) :: ModuleScript) :: any

-- functions
tweenModel(workspace.Train, {
	TweenInfo = {
		Length = 5,
		Style = "Sine",
		Direction = "Out",
		Repeats = 0,
		Reverse = false,
		Delay = 6,
	},
	Properties = {
		Value = CFrame.new(46, 6.75, 1.5),
	},
})

Then in ReplicatedStorage I have a ModuleScript called Tween Model. Inside this script is this code:

-- services
local tweenService: TweenService = game:GetService("TweenService") :: TweenService

-- variables
local defaultTweenInfo: any = {
	Time = 1,
	EasingStyle = "Sine",
	EasingDirection = "Out",
	RepeatCount = 0,
	Reverses = false,
	DelayTime = 0,
}

-- functions
return function(model: Model, content: any)
	local cframeValue: CFrameValue = Instance.new("CFrameValue") :: CFrameValue
	cframeValue.Value = model:GetPivot()

	local cframeChangedConection: RBXScriptConnection = cframeValue:GetPropertyChangedSignal("Value"):Connect(function()
		model:PivotTo(cframeValue.Value)
	end) :: RBXScriptConnection

	local cframeChangeTween: Tween = tweenService:Create(
		cframeValue,
		TweenInfo.new(
			content.TweenInfo.Length :: number,
			Enum.EasingStyle[content.TweenInfo.Style] :: Enum.EasingStyle,
			Enum.EasingDirection[content.TweenInfo.Direction] :: Enum.EasingDirection,
			content.TweenInfo.Repeats :: number,
			content.TweenInfo.Reverse :: boolean,
			content.TweenInfo.Delay :: number
		),
		content.Properties
	)

	cframeChangeTween:Play()
	cframeChangeTween.Completed:Wait()

	cframeChangedConection:Disconnect()
	cframeValue:Destroy()
end

When I am in game I no errors in the output at all but also no movement from the model in game. (On the server or the client). I am guessing this is because I must of set it up wrong. Can you spot what I have done wrong? If so could you help me? That would be amazing.

Thanks for this :slight_smile:

1 Like

You can’t run a LocalScript with the workspace. If you wish to create a local environment, first create a regular script within the workspace and set the RunContext property to Client and put the code within. This should fix the problem you are having.

Ah yes sorry about that I had it inside a folder then moved it all into a workspace for the explanation. But yes I completely forgot that.

When I put it in StarterPlayerScripts it works fine. I have not yet tried it with the LocalTween Module I made by following the tutorial but I will try that now! Thank you so much for the help it really has helped me a lot. I will try it with my module now and see what I can do.

I will get back to you with the results shortly. Hopefully it goes well :crossed_fingers:

1 Like

Just seen that I will not need to try it with my module as it already tween on the client!

I cannot thank you enough! It will work really well for what I want it for. I will mark your module as the Solution.

Have a great rest of you day/night! Thanks again :slight_smile:

1 Like

Hey sorry @Inpultion I have ran into a problem. When I use the module it is quite jolty. Is there anyway we can fix that? (I have attached a video so you can see)

If I try and make the module work with my local tween module do you think it will fix this issue?

1 Like

Mind if you display your script? It shouldn’t lag like that. My first guess was something to do with network ownership but it seems unlikely.

I have tried it out in the actual game instead of studio test and it is MUCH better. Still is a little jolty but for now I can deal with it as it will be in a really dark space so you wont really see the other seats jolt.

May it be that I am controlling the tweens from a module script? For example when I click the green button it runs a function in a module script that then runs the fake tween module you made.

1 Like

Well when you run a session within studio, the server and the client runs off your own computer. Which makes some sense to why it would lag. It’s the same reason that you’re able to maintain a lot more physic objects within the actual roblox player.

There shouldn’t be any jittery effects at all. Are you running my module from a local environment? In other words, not from the server.

Edit: To not bump this thread, I suggest messaging me directly on the devforum, or through discord ( Inpultion )

It would be easier for me to message you through discord. My username is danboi_ (Please if you message me / send me friend request tell me your name as I have many friend requests on there).

Thanks

2 Likes

I’ve send you a request. My username is Inpultion.

1 Like