[Portal] Issues Replicating Character CFrames to Viewports

I am trying to use the portal demo @EgoMoose created to replicate tools in the portal world, as well as trying to fix the bugs with characters not being removed after death in the viewport. To follow along, you can take a copy of the place from the link.

The issues that I am running into:

Images

https://cdn.discordapp.com/attachments/625882244376166410/626206995388563477/unknown.png

https://cdn.discordapp.com/attachments/625882244376166410/626196467262029836/unknown.png

I have tried making a detection function that updates the characters when death occurs or a tool is equipped/unequipped inside CharacterClone:

CheckReplace
-- Replace Function
function CharacterClone:CheckReplace(char)
	for fake, real in next, self.Lookup do
		if (char:FindFirstChild("Humanoid")) and Died == true then
			print("Humanoid")
			Died = false
		end
		char:WaitForChild("Humanoid").Died:connect(function()
			fake:Destroy()
			Died = true
			return true
		end)
		if char:FindFirstChild("ClassicSword") and ToolGate == false then
			fake:Destroy()
			ToolGate = true
			print("Tool!")
			return true
		end
		if not char:FindFirstChild("ClassicSword") and ToolGate == true then
			fake:Destroy()
			ToolGate = false
			print("No tool!")
			return true
		end
		--print("Ran!")
	end
end

As well, inside the GetLookup function I added code to clone tools (this works):

GetLookup
elseif (item:IsA("Tool")) then
	local match = character:FindFirstChild(item.Name).Handle
	item = item.Handle
	item.Anchored = true
	lookup[item] = match
end```

Finally, I added the CheckReplace function into the FixedBlock script in the RenderStepped portion:

RenderStepped
game:GetService("RunService").RenderStepped:Connect(function(dt)
	for i = 1, #clones do
		clones[i]:Update()
		if clones[i]:CheckReplace(script.Parent) then
			onCharacter(script.Parent)
		end
	end
end)

However, my solution fails to work. If you have any ideas on how to fix this, let me know!

The way I dealt with tools was simply using .DecendantAdded and .DecendantRemoving events. Tools get parented between Backpack and Character, so they fire DescendantAdded when you equip and DescendantRemoving when you unequip.

This way, you don’t need to poll every single character every single frame! Just handle them when the events fire. This method is nice cuz it’ll handle other things being added to the character too, such as hats or even custom armor meshes.

For deaths, you can simply reuse the dead body parts for the respawned character. This means you don’t need to recreate it, you just move them from the floor back up into the character.

Edit: Made a functional example

Using my [Open Source] ViewportFrame Handler, I whipped together what you’ve asked for.

local ViewportHandler = require(script.ViewportHandler)

local VF = game.Players.LocalPlayer:WaitForChild("PlayerGui"):WaitForChild("ScreenGui").ViewportFrame
	VF.CurrentCamera = workspace.CurrentCamera

local VF_H = ViewportHandler.new(VF)


local pHs = {} --player handlers

game.Players.PlayerRemoving:Connect(function(plr)
	if pHs[plr] then
		pHs[plr]:Destroy() -- Clear old body
	end
end)

game.Players.PlayerAdded:Connect(function(plr) -- Setup players that join later
	
	--Initial
	local char = plr.Character or plr.CharacterAdded:Wait()
	local hum = char:WaitForChild("Humanoid",3)
	
	if hum then wait() -- wait otherwise we run this before the meshes load properly
		pHs[plr] = VF_H:RenderHumanoid(char)
	end
	
	--Future
	plr.CharacterAdded:Connect(function(char)
		local hum = char:WaitForChild("Humanoid",3)
	
		if hum then wait() -- wait otherwise we run this before the meshes load properly
			if pHs[plr] then
				pHs[plr]:Destroy() -- Clear old body
			end
			pHs[plr] = VF_H:RenderHumanoid(char)
		end
	end)
	
end)

wait(1) -- Let players load in

for i,plr in pairs(game.Players:GetPlayers()) do -- Setup players in game
	spawn(function() -- Run in parallel since each can yield from the :Wait()
		
		
		--Initial
		local char = plr.Character or plr.CharacterAdded:Wait()
		local hum = char:WaitForChild("Humanoid",3)
		
		if hum then wait() -- wait otherwise we run this before the meshes load properly
			pHs[plr] = VF_H:RenderHumanoid(char)
		end
		
		--Future
		plr.CharacterAdded:Connect(function(char)
			local hum = char:WaitForChild("Humanoid",3)
		
			if hum then wait() -- wait otherwise we run this before the meshes load properly
				if pHs[plr] then
					pHs[plr]:Destroy() -- Clear old body
				end
				pHs[plr] = VF_H:RenderHumanoid(char)
			end
		end)
		
	end)
end

Everything is handled inside the module, you just tell it what you want it to do!

3 Likes