Why doesn't this mirror script work?

I’ve recently had a want to turn my current mirror script to be server-sided, so that my game can be more secure from place-copying and such.

A couple of days ago, I successfully turned my old local mirror script (it’s a common script) to a server script by changing a few things, but I noticed some cons to this because it would become “jittery” and have very poor performance for players who have lower processing power. This is because the old script made a new clone of the player every RenderStepped and would destroy the old clone and immediately replace it with the new one.

Then I had an idea of cloning the player’s character once and only update the clone’s parts every RenderStepped so that it would fix this problem.

While working on this though, I got as for as cloning the player and tweaking some properties of the clone, because when it runs the reflect() command (taken from the old script), it does nothing and does not produce any errors.

I couldn’t find anything wrong with it so I’ve taken it here. Am I doing something wrong, or is it just not compatible with being on the server-side?

local players = game:GetService("Players")
local workSpace = game:GetService("Workspace")
local heartBeat = game:GetService("RunService").Heartbeat

local reflection
local mirror = workSpace["Mirror model"].Part

local function reflect(item, against)
	local cf = item:IsA("BasePart") and item.CFrame or item.PrimaryPart.CFrame
	local x, y, z, r00, r01, r02, r10, r11, r12, r20, r21,r22 = against.CFrame:toObjectSpace(cf):components()
	local newCf = against.CFrame:toWorldSpace(CFrame.new(-x ,y ,z , r00, -r01, -r02, -r10, r11, r12, -r20, r21, r22))
	if item:IsA("BasePart") then
		item.CFrame = newCf
		if item:IsA("CornerWedgePart") then
			item.Size = Vector3.new(item.Size.z, item.Size.y, item.Size.x)
			item.CFrame = item.CFrame * CFrame.Angles(0,math.rad(90),0)
		end
	elseif item:IsA("Model") then
		item:SetPrimaryPartCFrame(newCf)
	end
end

local function gather(children, class, tab)
	local tab = tab and tab or {}
	for _, child in pairs(children) do
		if child:IsA(class) then
			table.insert(tab, child)
		end
		tab = gather(type(child) == "table" and child or child:GetChildren(), class, tab)
	end
	return tab
end

local function createReflection(character)
	character.Archivable = true
	reflection = character:Clone()
	reflection.Name = character.Name.."\'s_reflection"
	reflection.Humanoid.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.None
	
	local scripts = gather(reflection:GetChildren(), "BaseScript")
	local parts = gather(reflection:GetChildren(), "BasePart")
	local joints = gather(reflection:GetChildren(), "JointInstance")
	
	for _, src in pairs(scripts) do src:Destroy() end
	for _, joint in pairs(joints) do joint:Destroy() end
	
	for _, part in pairs(parts) do
		part.Anchored = true
		part.CanCollide = false
	end
	
	reflection.Parent = workSpace --<< Reflection Ready
end

local function mimicPlayer(character)
	if reflection and character then
		heartBeat:Connect(function()
			local parts = gather(reflection:GetChildren(), "BasePart")
			for i,v in pairs (parts) do
				reflect(v, mirror)
			end
		end)
	end
end

local function playerAdded(player)
	player.CharacterAppearanceLoaded:Connect(function(character)
		createReflection(character)
		mimicPlayer(character)
	end)
end

players.PlayerAdded:Connect(playerAdded)

Again, any help at all would help me a bunch!

In terms of performance, having it on the server will be a lot worse.
Also, you can’t use RenderStepped on the server, so you might wanna use Stepped instead.

From quickly checking the script, it seems that reflection is parented to nil as you mistyped workspace.

reflection.Parent = workSpace --<< Reflection Ready

No, the workspace is spelled right, I just named it that after I set that variable to game:GetService(“Workspace”). And I’ll try changing the renderStepped to .Stepped.

Thanks for the feedback!

Hey there, rexhawk!

I’ve got a model I’ve created recently that could help you with this.
I encourage you to check it out: Mirror Local Player

This model is all on the client, however, but it can be modified to do other players.
The model will reflect animations specified by you on humanoid events.

It’s possible to get the Reflection to turn in the same direction of the humanoid as well (but I got lazy). So I’ll let you have a try at that! :slight_smile:

EDIT: The reason why this is all on the client is to make it less laggy, if you do this on the server you’ll have massive amounts of lag on the server, as well as a delay in the reaction of the reflection and we all know mirror reflections are instant!
Roblox should definitely make this a built in feature, but for now, this is what we can do!