Train Node System - Figuring out getting the orientations and slightly adjust

I’ve managed to figure out how to get a block to follow the nodes, but I’m more concerned on how it is going to follow the next node’s orientation given ONLY the CFrame position.

I would want the orientation to change smoothly along the position movement. This is what I’ve been experiencing for better clarity. I’m using RunService for this method, it does not use TweenService, instead it places the block into a new CFrame value. As of right now, it only changes the position, but I need help on trying to get the orientation set.

The video lags, not the movement. I’d like to also keep in mind that speed can change constantly to the point where it can stop anywhere on the nodes if set to 0.

1 Like

I’m assuming you’re setting the .Position of the part - could you do .CFrame instead, as it holds the position of the node and the orientation?

If you are using CFrame, you can do this:

Block_CFrame = CFrame.new(x,y,z) * CFrame.Angles(x,y,z)

Did you try to do

Train.CFrame = CFrame.lookAt(CurrentNode.Position, NextNode.Position)

That seems to snap, where I want the orientation essentially ‘tween’ on the same speed as the position movement. But this is going in the right direction!

That solution will not work because the method to place the block goes into small increments based on subtracting two Vector3 values, which is the train and the node it’s heading towards.

I personally feel like if you are using the solution that @det3rr proposed, there’s no simpler way than tweening the CFrame.LookAt, I suspect Basepart/Model:PivotTo() would also snap if that’s the case with CFrame.LookAt snapping.

Since you are working with subtracting two Vector3 values, have you tried Cframe:VectorToObjectSpace?

I’m subtracting position Vector3 values, sorry. What I replicated was basically ‘lerping’ the positions at a consistent speed using position subtraction.

workspace.Part.CFrame = CFrame.new(workspace.Part.CFrame.p + (workspace.Nodes[CurrentNode].CFrame.p - workspace.Part.CFrame.p).Unit * (speed))

Sorry for the messy code, but this is the idea of making my system able to function.
This is how I achieved what was shown in the video.

The easiest solution, I think, would be thinking more into the future, when the train car has an actual length

You could get the exact position of the back of the car and the front of the car and orient it between those two points, this would fix the snapping position (but would leave a snapping velocity but it shouldnt look noticeable)

Part of the main issue is to get the timing in par with the positioning. Basically make it act like it was TweenService all over again.

To fix the snapping orientation its an easy fix just use linear interpolation! Assumming you’re already moving the train and have the node and next node as variables. This will lerp it to the next node’s look vector depending on how far along it is on the current node. Node or track node just makes more sense to me for some reason.

local function GetDirectionalCFrame(Train, Node, NextNode):CFrame
	local Start = (Node.CFrame * CFrame.new(0, 0, -Node.Size.Z/2)).Position;
	local End = (Node.CFrame * CFrame.new(0, 0, Node.Size.Z/2)).Position;
	local Alpha = (Train.Position - End).Magnitude/(Start-End).Magnitude;
	local DirectionalCFrame = CFrame.fromMatrix(Train.Position, Node.CFrame.LookVector:Lerp(NextNode.CFrame.LookVector, Alpha), Vector3.new(0, 1, 0));
	
	return DirectionalCFrame;
end
2 Likes