Any help instant loading viewportframe character changes?

So I have this viewportframe that shows your character, but it doesn’t load in new assets instantly, for instance shirts and pants, and I haven’t tested faces, any help with that?

--Services
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.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 function RenderHumanoid(Model, Parent, MainModel)
	local ModelParts = Model:GetDescendants()
	for i=1, #ModelParts do
		local Part		= ModelParts[i]
		
		if ValidClasses[Part.ClassName] then
			
			local a			= Part.Archivable
				Part.Archivable	= true
				
			local RenderClone	= Part:Clone()
				Part.Archivable	= a
		
			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.ClassName == "Humanoid" then
				RenderClone:SetStateEnabled(Enum.HumanoidStateType.FallingDown,			false)
				RenderClone:SetStateEnabled(Enum.HumanoidStateType.Running,				false)
				RenderClone:SetStateEnabled(Enum.HumanoidStateType.RunningNoPhysics,	false)
				RenderClone:SetStateEnabled(Enum.HumanoidStateType.Climbing,			false)
				RenderClone:SetStateEnabled(Enum.HumanoidStateType.StrafingNoPhysics,	false)
				RenderClone:SetStateEnabled(Enum.HumanoidStateType.Ragdoll,				false)
				RenderClone:SetStateEnabled(Enum.HumanoidStateType.GettingUp,			false)
				RenderClone:SetStateEnabled(Enum.HumanoidStateType.Jumping,				false)
				RenderClone:SetStateEnabled(Enum.HumanoidStateType.Landed,				false)
				RenderClone:SetStateEnabled(Enum.HumanoidStateType.Flying,				false)
				RenderClone:SetStateEnabled(Enum.HumanoidStateType.Freefall,			false)
				RenderClone:SetStateEnabled(Enum.HumanoidStateType.Seated,				false)
				RenderClone:SetStateEnabled(Enum.HumanoidStateType.PlatformStanding,	false)
				RenderClone:SetStateEnabled(Enum.HumanoidStateType.Dead,				false)
				RenderClone:SetStateEnabled(Enum.HumanoidStateType.Swimming,			false)
				RenderClone:SetStateEnabled(Enum.HumanoidStateType.Physics,				false)
			end
			
			RenderClone.Parent = Parent
		end 
	end
end

wait(1)


local function Render()
	ViewPort:ClearAllChildren()
	--Render the character
	local Char = instance("Model")
		Char.Name = ""
		Char.Parent = ViewPort
	RenderHumanoid(Character,Char)
end

--Handle changes
Character.DescendantAdded:Connect(Render)
Character.DescendantRemoving:Connect(Render)

--Initialize
Render()

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

Any asset that is used for the first time in your game must be downloaded by the client before it shows, which is what’s resulting in assets not being loaded instantly. You can’t achieve this behaviour for any asset as a matter of fact.

The best option you have is to call PreloadAsync on the viewport character before sending it into the ViewportFrame, though even then you won’t get instantaneous results. PreloadAsync is a yielding function and until the assets load, the character won’t be parented.

Nothing you do is ever instantaneous. Near-instantaneous or the illusion that it is? Maybe.

1 Like

They could preload all possible assets, then it will load the next frame.

This is not necessarily correct. Preloading an asset does not immediately make it available the next frame - that depends on how quickly the client is able to download and cache the asset.

I’ve already mentioned it in my post however. The character can be passed through PreloadAsync, which will automatically place all related assets in the queue and download them. This is still not instantaneous loading nor can it be. The function will yield until the assets are off the queue.

You can’t achieve instantaneous loading, you can only get near-instantaneous loading. And you will have the small wait gap that the yield causes.