(UNSOLVED) Story Game Viewport Frame Function PAYING 200 Robux for FIX!

hey everyone im currently working on a story game kind of like field trip z but right now im lost. I have a viewport frame but it captures me whenever an npc talks, i just want to get the npc on there as well as the player when they are talking.
this is what i have right now

here is the current local script inside of the MainGui

local StarterGui = game:GetService("StarterGui")
local RunService = game:GetService('RunService')
local createDialogueEvent = game.ReplicatedStorage.Remotes.createDialogueEvent
local hideDialogueEvent = game.ReplicatedStorage.Remotes.hideDialogueEvent
local setDialogueImageEvent = game.ReplicatedStorage.Remotes.setDialogueImageEvent
local richText = require(game.ReplicatedStorage.Modules.RichText)
local player = game.Players.LocalPlayer
local dialogueFrame = player.PlayerGui.MainGui.Frame
local setDialogueImageEventMonster = game.ReplicatedStorage.Remotes.setDialogueImageEventMonster
local setDialogueImageEventGhost = game.ReplicatedStorage.Remotes.setDialogueImageEventGhost
local RunService = game:GetService('RunService')
local UserInputService = game:GetService("UserInputService")

--Localize
local instance, newRay = Instance.new, Ray.new
local v2, v3, cf, udim2 = Vector2.new, Vector3.new, CFrame.new, UDim2.new
local insert, random, abs = table.insert, math.random, math.abs

local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()

--Basic setup
local ViewPort = script.Parent.Frame.ViewportFrame

--Settings
local Offset = cf(0, 1, -6)

--Create the viewport camera
local Camera = instance("Camera")
ViewPort.CurrentCamera = Camera

local ValidClasses = {
	["MeshPart"] = true; ["Part"] = true; ["Accoutrement"] = true;
	["Pants"] = true; ["Shirt"] = true;
	["Humanoid"] = true;
}

local PartUpdater

local function swooshSound()
	local sound = Instance.new("Sound", game.ReplicatedStorage)
	sound.PlaybackSpeed = 1
	sound.Volume = 1
	sound.PlayOnRemove = true
	sound.SoundId = "rbxassetid://4845387138"
	sound:Destroy()
end

hideDialogueEvent.OnClientEvent:Connect(function()
	StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, true)
	swooshSound()
	dialogueFrame:TweenPosition(UDim2.new(0.5, 0, 2, 0), 0.1)
end)

createDialogueEvent.OnClientEvent:Connect(function(english, spanish)
	if dialogueFrame.Position ~= UDim2.new(0.5, 0, 0.85, 0) then
		StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false)
		dialogueFrame:TweenPosition(UDim2.new(0.5, 0, 0.85, 0), 0.1)
	end

	local ln = game:GetService("LocalizationService").RobloxLocaleId
	local content = english
	if ln == "en-us" then
		content = english
	elseif ln == "es-es" then
		if spanish then
			content = spanish
		end
	end

	local textObject = richText:New(dialogueFrame.textFrame, content)
	textObject:Animate(true)
end)

local function cleanVPF()
	if dialogueFrame.ViewportFrame:FindFirstChildOfClass("Model") then
		dialogueFrame.ViewportFrame:FindFirstChildOfClass("Model"):Destroy()
	end

	if dialogueFrame.ViewportFrame:FindFirstChildOfClass("Camera") then
		dialogueFrame.ViewportFrame:FindFirstChildOfClass("Camera"):Destroy()
	end
end

local function renderHumanoid(model, parent)
	local modelParts = model:GetDescendants()
	for i = 1, #modelParts do
		local part = modelParts[i]

		if ValidClasses[part.ClassName] then
			local archivable = part.Archivable
			part.Archivable = true

			local renderClone = part:Clone()
			part.Archivable = archivable

			if part.ClassName == "MeshPart" or part.ClassName == "Part" then
				PartUpdater = RunService.Heartbeat:Connect(function()
					if part then
						renderClone.CFrame = part.CFrame
					else
						renderClone:Destroy()
						PartUpdater:Disconnect()
					end
				end)
			elseif part:IsA("Accoutrement") then
				PartUpdater = RunService.Heartbeat:Connect(function()
					if part then
						if renderClone.Handle then
							renderClone.Handle.CFrame = part.Handle.CFrame
						end
					else
						renderClone:Destroy()
						PartUpdater:Disconnect()
					end
				end)
			elseif part:IsA("Humanoid") then
				local nameTag = Instance.new("BillboardGui")
				nameTag.Name = "NameTag"
				nameTag.Adornee = renderClone
				nameTag.Parent = parent

				local nameLabel = Instance.new("TextLabel")
				nameLabel.Text = model.Name
				nameLabel.TextSize = 14
				nameLabel.TextStrokeTransparency = 0.5
				nameLabel.Parent = nameTag

				nameTag.StudsOffset = Vector3.new(0, 2, 0)
			end

			renderClone.Parent = parent
		end
	end
end

local function CaptureImage(model, camera)
	local player = game.Players.LocalPlayer

	local viewportFrame = Instance.new("ViewportFrame")
	viewportFrame.Size = UDim2.new(1, 0, 1, 0)
	viewportFrame.CurrentCamera = camera
	viewportFrame.BackgroundTransparency = 1

	for _, part in pairs(model:GetDescendants()) do
		if part:IsA("BasePart") then
			part.LocalTransparencyModifier = 0  -- Make sure the part is not transparent
		end
	end

	model.Parent = viewportFrame
	local imageLabel = Instance.new("ImageLabel")
	imageLabel.Size = UDim2.new(1, 0, 1, 0)
	imageLabel.BackgroundTransparency = 1
	imageLabel.Parent = player.PlayerGui

	wait(2)  -- Adjust this wait time as needed

	-- Cleanup
	viewportFrame:Destroy()
	model.Parent = game.Workspace
	for _, part in pairs(model:GetDescendants()) do
		if part:IsA("BasePart") then
			part.LocalTransparencyModifier = 1  -- Restore original transparency
		end
	end
end


setDialogueImageEventMonster.OnClientEvent:Connect(function(model, color)
	dialogueFrame.PlayerName.TextColor3 = Color3.new(0, 0, 0)
	dialogueFrame.PlayerName.TextStrokeColor3 = Color3.new(0.82089, 0, 0)
	dialogueFrame.PlayerName.TextStrokeTransparency = 0
	dialogueFrame.Message.TextColor3 = Color3.new(0, 0, 0)
	dialogueFrame.Message.TextStrokeTransparency = 0
	dialogueFrame.Message.TextStrokeColor3 = Color3.new(0.82089, 0, 0)
	dialogueFrame.PlayerName.Text = model.name

	local image = CaptureImage(model, Camera)
	renderHumanoid(model, dialogueFrame.ViewportFrame)
end)

setDialogueImageEventGhost.OnClientEvent:Connect(function(model, color)
	dialogueFrame.PlayerName.TextColor3 = Color3.new(1, 1, 1)
	dialogueFrame.PlayerName.TextStrokeColor3 = Color3.new(0.197635, 0.66746, 1)
	dialogueFrame.PlayerName.TextStrokeTransparency = 0
	dialogueFrame.Message.TextColor3 = Color3.new(1, 1, 1)
	dialogueFrame.Message.TextStrokeTransparency = 0
	dialogueFrame.Message.TextStrokeColor3 = Color3.new(0.197635, 0.66746, 1)
	dialogueFrame.PlayerName.Text = model.name

	local image = CaptureImage(model, Camera)
	renderHumanoid(model, dialogueFrame.ViewportFrame)
end)

setDialogueImageEvent.OnClientEvent:Connect(function(model, color)
	dialogueFrame.PlayerName.TextStrokeTransparency = 1
	dialogueFrame.PlayerName.TextColor3 = Color3.new(255, 255, 255)
	dialogueFrame.Message.TextColor3 = Color3.new(255, 255, 255)
	dialogueFrame.Message.TextStrokeTransparency = 1
	dialogueFrame.PlayerName.Text = model.name

	local image = CaptureImage(model, Camera)
	renderHumanoid(model, dialogueFrame.ViewportFrame)
end)

local function Render()
	ViewPort:ClearAllChildren()

	local localPlayerChar = instance("Model")
	localPlayerChar.Name = ""
	localPlayerChar.Parent = ViewPort
	renderHumanoid(Character, localPlayerChar)

	for _, player in ipairs(game.Players:GetPlayers()) do
		if player ~= Player and player.Character then
			local otherPlayerChar = instance("Model")
			otherPlayerChar.Name = ""
			otherPlayerChar.Parent = ViewPort
			renderHumanoid(player.Character, otherPlayerChar)
		end
	end
end

Character.DescendantAdded:Connect(Render)
Character.DescendantRemoving:Connect(Render)

Render()

local CameraUpdater = RunService.Heartbeat:Connect(function()
	if Character.HumanoidRootPart then
		Camera.CFrame = cf(Character.HumanoidRootPart.CFrame:toWorldSpace(Offset).p, Character.HumanoidRootPart.CFrame.p)
	end
end)

Screenshot 2023-11-27 at 12.41.34 AM

1 Like

thanks for the help in advance!

1 Like

I am not sure if this would help you but here you go : https://devforum.roblox.com/t/make-two-or-multiple-objects-stick-together-in-a-viewport-frame/1852993?u=milkyfiend

Soooo, what are you having problems with? Can’t you just re-use your Render function, but on the NPC model instead of the player model? You should include this information in your post.

You can just use:

for _, part in model:GetDescendants() do

Why? Especially since you are asking random people for help, this can just make your code more difficult to understand for those who are unfamiliar with it. Also, the fact that the comment says “Localize” almost makes me think you’re trying to use an outdated optimization where you store every single member function of a library in a variable, which is completely useless nowadays.

2 Likes

i have fixed the capture image but it still only seems to put my image on the viewport not the others.

local function CaptureImage(model, camera)
	local player = game.Players.LocalPlayer

	local viewportFrame = Instance.new("ViewportFrame")
	viewportFrame.Size = UDim2.new(1, 0, 1, 0)
	viewportFrame.CurrentCamera = camera
	viewportFrame.BackgroundTransparency = 1

	for _, part in model:GetDescendants() do
		if part:IsA("BasePart") then
			part.LocalTransparencyModifier = 0  -- Make sure the part is not transparent
		end
	end

	model.Parent = viewportFrame
	local imageLabel = Instance.new("ImageLabel")
	imageLabel.Size = UDim2.new(1, 0, 1, 0)
	imageLabel.BackgroundTransparency = 1
	imageLabel.Parent = player.PlayerGui

	wait(2)

	-- Cleanup
	viewportFrame:Destroy()
	model.Parent = game.Workspace
	for _, part in model:GetDescendants() do
		if part:IsA("BasePart") then
			part.LocalTransparencyModifier = 1  -- Restore original transparency
		end
	end
end

i cant find out the reason why its only showing players.

Are you sure you are getting other player models and registering to the viewportFrame?

That’s what I’m trying to do I don’t know if I got it right tho.

1 Like

okay so ive been working on the local script and this is where im at,

local StarterGui = game:GetService("StarterGui")

local createDialogueEvent = game.ReplicatedStorage.Remotes.createDialogueEvent
local hideDialogueEvent = game.ReplicatedStorage.Remotes.hideDialogueEvent
local setDialogueImageEvent = game.ReplicatedStorage.Remotes.setDialogueImageEvent

local richText = require(game.ReplicatedStorage.Modules.RichText)

local player = game.Players.LocalPlayer
local dialogueFrame = player.PlayerGui.MainGui.Frame
local setDialogueImageEventMonster = game.ReplicatedStorage.Remotes.setDialogueImageEventMonster
local setDialogueImageEventGhost = game.ReplicatedStorage.Remotes.setDialogueImageEventGhost

local clonedChar
local cam = Instance.new("Camera")
cam.Parent = dialogueFrame.ViewportFrame

local function swooshSound()
	local sound = Instance.new("Sound", game.ReplicatedStorage)
	sound.PlaybackSpeed = 1
	sound.Volume = 1
	sound.PlayOnRemove = true
	sound.SoundId = "rbxassetid://4845387138"
	sound:Destroy()
end

hideDialogueEvent.OnClientEvent:Connect(function()
	StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, true)
	swooshSound()
	dialogueFrame:TweenPosition(UDim2.new(0.5, 0, 2, 0), 0.1)
end)

createDialogueEvent.OnClientEvent:Connect(function(english, spanish)
	if dialogueFrame.Position ~= UDim2.new(0.5, 0, 0.85, 0) then
		StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false)
		dialogueFrame:TweenPosition(UDim2.new(0.5, 0, 0.85, 0), 0.1)
	end

	local ln = game:GetService("LocalizationService").RobloxLocaleId
	local content = english
	if ln == "en-us" then
		content = english
	elseif ln == "es-es" then
		if spanish then
			content = spanish
		end
	end

	local textObject = richText:New(dialogueFrame.textFrame, content)
	textObject:Animate(true)
end)

-- Viewport Script Starts Here

local function cleanVPF()
	local viewportFrame = dialogueFrame.ViewportFrame

	for _, obj in pairs(viewportFrame:GetChildren()) do
		if obj:IsA("Model") or obj:IsA("Camera") then
			obj:Destroy()
		end
	end
end

-- Function to set up the camera for a character
local function setupCamera(vpCharacter)
	if clonedChar then
		clonedChar:Destroy()
	end

	clonedChar = vpCharacter:Clone()
	local hrp = clonedChar:WaitForChild("HumanoidRootPart")
	cam.CFrame = CFrame.new(hrp.Position + (hrp.CFrame.LookVector * 5), hrp.Position)
	dialogueFrame.ViewportFrame.CurrentCamera = cam

	clonedChar.Parent = dialogueFrame.ViewportFrame
end

-- Connect to hideDialogueEvent to remove the cloned character when conversation is complete
hideDialogueEvent.OnClientEvent:Connect(function()
	if clonedChar then
		clonedChar:Destroy()
	end
end)

setDialogueImageEvent.OnClientEvent:Connect(function(model, color)
	dialogueFrame.PlayerName.TextStrokeTransparency = 1
	dialogueFrame.PlayerName.TextColor3 = Color3.new(255, 255, 255)
	dialogueFrame.Message.TextColor3 = Color3.new(255, 255, 255)
	dialogueFrame.Message.TextStrokeTransparency = 1
	dialogueFrame.PlayerName.Text = model.name

	local vpCharacter = model
	if vpCharacter then
		cleanVPF()
		setupCamera(vpCharacter)  -- Initial camera setup
		game:GetService("RunService").RenderStepped:Connect(function()
			setupCamera(vpCharacter)
		end)
	else
		warn(model.Name .. " is not in ReplicatedStorage")
	end
end)

it just stays on my character


1 Like

ill pay someone who can help me solve this, maybe 200 robux.

the problem is, it just stays on my picture for the viewport and it doesnt move on. and also the name and text update to the correct thing.

alr send me $2, just use a worldmodel and remove the old character from the viewport at each time u need!

thanks that didnt help me understand what i need to do to solve the issues im having.