Cloning to a ViewportFrame doesn't work properly

I want to make a little 3D display of a drink in a bottle that spins around on the Y axis with a 15 degree X axis tilt.

The script currently looks like this:

local RunService = game:GetService("RunService")
local ServerStorage = game:GetService("ServerStorage")
local bottlesFolder = ServerStorage:WaitForChild("BottlesDrinks")

local isPremium = false

local frames = script.Parent:GetChildren()
local viewportData = {}

local function findFirstBasePart(instance)
	for _, child in instance:GetChildren() do
		if child:IsA("BasePart") then
			return child
		else
			local found = findFirstBasePart(child)
			if found then
				return found
			end
		end
	end
	return nil
end

for _, frame in frames do
	if frame:IsA("Frame") then
		local viewport = frame:FindFirstChildOfClass("ViewportFrame")
		if viewport then
			for _, child in viewport:GetChildren() do
				if child:IsA("Model") or child:IsA("BasePart") then
					child:Destroy()
				end
			end

			local tool = bottlesFolder:FindFirstChild(frame.Name)
			if tool and tool:IsA("Tool") then
				local handle = tool:FindFirstChild("Handle")
				if handle and handle:IsA("BasePart") then
					local partPositions = {}
					if isPremium then
						partPositions = {
							Handle = Vector3.new(0, 0, 0),
							Liquid = Vector3.new(0, -0.209, 0),
							Bottle22 = Vector3.new(0, 0.869, 0),
							Bottle24 = Vector3.new(0.22, -0.348, 0),
							Cork = Vector3.new(0, 1.034, 0),
						}
					else
						partPositions = {
							Handle = Vector3.new(0, 0, 0),
							Liquid = Vector3.new(0, -0.384, 0),
							Bottle13 = Vector3.new(0, -0.4, 0),
							Cork = Vector3.new(0, 0.875, 0),
						}
					end

					local newModel = Instance.new("Model")
					newModel.Name = tool.Name
					newModel.Parent = viewport

					for partName, position in pairs(partPositions) do
						local originalPart = nil
						if partName == "Handle" then
							originalPart = handle
						else
							originalPart = handle:FindFirstChild(partName)
							if not originalPart then
								originalPart = tool:FindFirstChild(partName)
							end
						end

						local partToClone = nil
						if originalPart then
							if originalPart:IsA("BasePart") then
								partToClone = originalPart
							elseif originalPart:IsA("Model") or originalPart:IsA("UnionOperation") then
								partToClone = findFirstBasePart(originalPart)
							end
						end

						if partToClone and partToClone:IsA("BasePart") then
							local clone = partToClone:Clone()
							clone.Anchored = true
							clone.CFrame = CFrame.new(position)
							clone.Parent = newModel

							if partName == "Handle" then
								for _, child in clone:GetChildren() do
									child:Destroy()
								end
							end
						end
					end

					local centerCFrame, _ = newModel:GetBoundingBox()
					local rotatingParts = {}

					for _, part in newModel:GetChildren() do
						if part:IsA("BasePart") then
							local relative = centerCFrame:ToObjectSpace(part.CFrame)
							table.insert(rotatingParts, {
								Part = part,
								RelativeCFrame = relative
							})
						end
					end

					viewportData[viewport] = {
						Model = newModel,
						Center = centerCFrame.Position,
						Angle = 0,
						RotatingParts = rotatingParts
					}

				end
			end
		end
	end
end

RunService.Heartbeat:Connect(function(dt)
	for _, data in pairs(viewportData) do
		data.Angle += math.rad(45) * dt

		local tilt = CFrame.Angles(math.rad(15), 0, 0)
		local spin = CFrame.Angles(0, data.Angle, 0)
		local rotation = spin * tilt
		local center = CFrame.new(data.Center)

		for _, entry in data.RotatingParts do
			entry.Part.CFrame = center * rotation * entry.RelativeCFrame
		end
	end
end)

It’s meant to clone the required bottle’s handle from the bottlesFolder that is located inside ServerStorage under the name BottlesDrinks, the bottle itself is a tool, that’s why I’m cloning the handle and all the parts inside the handle.

For some reason if IsPremium boolean is true, the parts Bottle22 and Bottle24 don’t get cloned or just aren’t found by the script.

So it just looks like this inside the viewport frame:

When it’s meant to look like this, but inside the viewport frame:


This is the bottle itself inside the folder:

And this is the ScreenGui with the viewport frame and everything:

I’ve tried asking the Roblox Studio assistant, I’ve read quite a bit of documentations and it just doesn’t seem to work…

Any help is appreciated!

					if isPremium then
						partPositions = {
							Handle = Vector3.new(0, 0, 0),
							Liquid = Vector3.new(0, -0.209, 0),
							Bottle22 = Vector3.new(0, 0.869, 0),
							Bottle24 = Vector3.new(0.22, -0.348, 0),
							Cork = Vector3.new(0, 1.034, 0),
						}
					else
						partPositions = {
							Handle = Vector3.new(0, 0, 0),
							Liquid = Vector3.new(0, -0.384, 0),
							Bottle13 = Vector3.new(0, -0.4, 0),
							Cork = Vector3.new(0, 0.875, 0),
						}
					end

I noticed that when mentioning isPremium (default value false), Bottle22 and Bottle24 positions are set. However, when isPremium is not false then they are not mentioned when setting their positions. Is there a specific reason for this, and if so could you please tell me?

Hello.
So when IsPremium is false, that means it’s a different type of bottle, therefor it has different parts inside the handle. The script works perfectly fine when cloning the non IsPremium bottle or parts.

This is the non-IsPremium bottle by the way:


And as you can see, the script works perfectly fine when cloning the non-IsPremium bottle parts:

					if not isPremium then
						partPositions = {
							Handle = Vector3.new(0, 0, 0),
							Liquid = Vector3.new(0, -0.209, 0),
							Bottle22 = Vector3.new(0, 0.869, 0),
							Bottle24 = Vector3.new(0.22, -0.348, 0),
							Cork = Vector3.new(0, 1.034, 0),
						}
					else
						partPositions = {
							Handle = Vector3.new(0, 0, 0),
							Liquid = Vector3.new(0, -0.384, 0),
							Bottle13 = Vector3.new(0, -0.4, 0),
							Cork = Vector3.new(0, 0.875, 0),
						}
					end

Sorry if I am misunderstanding, but I believe the issue relies in the script logic. Try replacing your current code with this, and tell me if it still is messing up.

Sadly, it didn’t work.
However it did find the correct parts to clone for the IsPremium bottle, but the positions are all messed up. And it didn’t find the Bottle13 part for the non-IsPremium bottle.

Oh my god…
I just found out I literally forgot to change the value of the IsPremium variable…
Why does this keep happening to me, ha ha…

Thank you for your help though, I appreciate it.
Without you mentioning that the isPremium value is always set to false, I wouldn’t have noticed it.
I guess I’m just too sleepy for this type of stuff…

No worries, so the problem was with it being set wrong?

The problem was, I forgot to change it based on the bottle’s actual Premium BoolValue. Therefor isPremium was always false.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.