Tweening Locally with welded parts

Hello,

I have followed this tutorial on how to tween locally. I am wanting to make a theme park ride system out of this but need a bit of help. When I try and weld other parts to the TweenPart it does not move or anything. It does not even change position on the server once the local tween has finished. I have tried using ManualWelds and WeldConstaints but nothing is working.

Does anyone know how I can fix this? It works when I tween on the server bit it can cause mass lag.

If anyone can help me that would be great!

Thanks :slight_smile:

12 Likes

I think that one way to do this, although a little awkward, is to tween everything together rather than just one object.

2 Likes

Might be because the welds are made on server.

3 Likes

Ye that is what I heard from other developers.

Is there anyway around it?

2 Likes

I will have quite a few parts but I will probably try and union them all together and tween it as one. Hopefully that may work :crossed_fingers:

2 Likes

You could put the stuff containing the welds in ReplicatedStorage then clone it and parent it to workspace on client.

2 Likes

I will give that a try! Thanks for the help :slight_smile:

1 Like

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