Mirror is almost done[HELP]

Hi. I am making a mirror, and it’s most likely done. Just a bit of help, the problem is with when a player is facing straight, the clone is also facing straight instead of looking at the character and it’s unanimated, too. Here’s how:


Here’s my code:

local Mirror = game.Workspace:WaitForChild("Mirror")

local RunService = game:GetService("RunService");

local Mirror = game.Workspace:WaitForChild("Mirror")

local RunService = game:GetService("RunService");

local function reflect()

    for i, v in next, game.Players:GetPlayers() do

        if (v) ~= nil then

            if (v.Character) ~= nil then

                for a, b in next, v.Character:GetDescendants() do
                    if (b) ~= nil then
                        if b:IsA("BasePart") or b:IsA("UnionOperation") or b:IsA("MeshPart") then

                            local objectSpace = Mirror.CFrame:Inverse() * (v.Character:GetPrimaryPartCFrame());
                            
                          
                            
                            local worldSpace = Mirror.CFrame:ToWorldSpace(CFrame.new(objectSpace.X, objectSpace.Y, -objectSpace.Z) * CFrame.Angles(objectSpace:ToEulerAnglesXYZ()));
                            v.Character.Archivable = true;

                            local newCharacter;

                            if not workspace:FindFirstChild("Dummy") then

                                newCharacter = v.Character:Clone()

                                newCharacter.Name = "Dummy"

                                newCharacter.Parent = workspace;

                            end

                            local new = workspace:FindFirstChild("Dummy")

                            if new then

                                new:SetPrimaryPartCFrame(worldSpace) 
                            end
                        end
                    end
                end
            end
        end;
    end;
end;


RunService.RenderStepped:Connect(reflect);

Help is really appreciated: :slight_smile:

3 Likes

You need to multiply the final CFrame by

CFrame.Angles(0, math.pi, 0)

1 Like

Hi, this topic may be useful: ViewportFrame Camera System

But I don’t want to make a mirror by using Viewports.

1 Like

I got it working. Now the only problem is the animation.

The animation script in characters which aren’t players must be a normal script and not LocalScript.

The reason it isn’t animated is because you’re only setting the CFrame of the dummy and not each of its individual parts. I see you’re looping through each part inside of the character, but you’re setting only the character’s CFrame each time, which is redundant. Try doing the same math but on the individual parts instead. You also have several unnecessary if checks. You don’t need to check if (b) is not nil, because the GetDescendants function by definition will not return a table with nil values.

They’re not using an animator. They’re making a mirror, and that’s still not true. It can be a LocalScript as well.

Oh, yes. I completely forget about that. Thanks, I will do that right now.

Oh right, I completely forgot about that.

1 Like

Well then it will be pretty tricky. You would have to replicate all the animations on your character to the dummy somehow (in real-time!).

Not if they just copy the CFrames of each body part individually. No animation copying will be needed.

Lol.:joy:
I basically did what you told me to, and it is still not animated, instead it’s giving me some weird CFrame changes when jumping, or walking. Here’s the new code:

local Mirror = game.Workspace:WaitForChild("Mirror")

local RunService = game:GetService("RunService");

local function reflect()

    for i, v in next, game.Players:GetPlayers() do

        if (v) ~= nil then

            if (v.Character) ~= nil then

                v.Character.Archivable = true

                if not game.Workspace:FindFirstChild("Dummy") then

                    local character = v.Character:Clone()

                    character.Name = "Dummy"

                    character.Parent = game.Workspace


                end

                if workspace:FindFirstChild("Dummy") then

                    for index, val in pairs(workspace.Dummy:GetDescendants()) do
                        if val:IsA("BasePart") or val:IsA("UnionOperation") or val:IsA("MeshPart") then
                            local plrchar = v.Character:FindFirstChild(val.Name, true)
                            
                            local objectedSpace = Mirror.CFrame:Inverse() * plrchar.CFrame

                            local yaw, pitch, roll = objectedSpace:ToEulerAnglesXYZ()

                            local worldSpace = Mirror.CFrame:ToWorldSpace(CFrame.new(objectedSpace.X,objectedSpace.Y, -objectedSpace.Z)) * CFrame.Angles(yaw, -pitch, roll);

                            val.CFrame = worldSpace * CFrame.Angles(0, -math.pi+math.pi, 0)
                        end
                    end
                end


            end
        end
    end;
end;


RunService.RenderStepped:Connect(reflect);

Help pls.

anyone? help Please, I need a solution for this

1 Like

Check the math, possibly redo calculations.

1 Like

I did the way @gooey333 suggested, and it is still not working. Can you help? It’s kinda weird when the player jumps and walks.

local Mirror = game.Workspace:WaitForChild("Mirror")

local RunService = game:GetService("RunService");

local Mirror = game.Workspace:WaitForChild("Mirror")

local RunService = game:GetService("RunService");

local function getElements()
    local elements = {};
    
    for i, v in next, game.Players:GetPlayers() do

        if (v) ~= nil then

            if (v.Character) ~= nil then

                for a, b in next, v.Character:GetDescendants() do
                    if (b) ~= nil then
                        if b:IsA("BasePart") or b:IsA("UnionOperation") or b:IsA("MeshPart") then
                            table.insert(elements, b.Name)
                        end
                    end
                end
            end
        end;
    end;
    
    return elements
    
end

local function getObjectedSpace(cf1, cf2)
    return cf1:ToObjectSpace(cf2)
end

local function getWorldedSpace(cf1, cf2)
    return cf1:ToWorldSpace(cf2)
end



local function reflect()
    local elements = getElements()
    
    game.Players.LocalPlayer.Character.Archivable = true    
    
    local Playercharacter = game.Players.LocalPlayer.Character
    local clonedCharacter = Playercharacter:Clone()
    clonedCharacter.Parent = game.Workspace
    
    RunService.RenderStepped:Connect(function()
        
        for index, element in pairs(elements) do
            
            
            local elementInOriginal, elementInFake = Playercharacter:FindFirstChild(element, true), clonedCharacter:FindFirstChild(element, true)
            
            local objectedSpace = getObjectedSpace(Mirror.CFrame, elementInOriginal.CFrame)
            
            local yaw, pitch, roll = objectedSpace:ToEulerAnglesXYZ()
            
            local worldSpace = getWorldedSpace(Mirror.CFrame, CFrame.new(objectedSpace.X, objectedSpace.Y, -objectedSpace.Z)*CFrame.Angles(yaw, -pitch, roll))
            
            local new = worldSpace * CFrame.Angles(0, -math.pi, 0)
            
            elementInFake.CFrame = new
            
        end      
    end)
end;

wait(1)

reflect()

Well your math is wrong. It would be pretty complicated. One thing you could try is cloning the character and reverting to what you had previously, but instead of copying part positions, copy Motor6d properties for all the limbs. This may replicate animations better than CFrames.

1 Like

Maybe this will help with your mirror.

1 Like

After setting copying the CurrentAngle property, I feel like I am almost there. Idle animation works, but others don’t work as intended. Here’s a video:
robloxapp-20201209-0904353.wmv (4.4 MB)
and here’s the code:

local Mirror = game.Workspace:WaitForChild("Mirror")

local RunService = game:GetService("RunService");

local Mirror = game.Workspace:WaitForChild("Mirror")

local RunService = game:GetService("RunService");

local function reflect()

    for i, v in next, game.Players:GetPlayers() do

        if (v) ~= nil then

            if (v.Character) ~= nil then

                for a, b in next, v.Character:GetDescendants() do
                    if (b) ~= nil then
                        if b:IsA("BasePart") or b:IsA("UnionOperation") or b:IsA("MeshPart") or b:IsA("Motor6D") then

                            if not b:IsA("Motor6D") then
                                local objectSpace = Mirror.CFrame:Inverse() * (v.Character:GetPrimaryPartCFrame());


                                local yaw, pitch, roll = objectSpace:ToEulerAnglesXYZ()

                                local worldSpace = Mirror.CFrame:ToWorldSpace(CFrame.new(objectSpace.X, objectSpace.Y, -objectSpace.Z) * CFrame.Angles(yaw, -pitch, roll));
                                v.Character.Archivable = true;

                                local newCharacter;

                                if not workspace:FindFirstChild("Dummy") then

                                    newCharacter = v.Character:Clone()

                                    newCharacter.Name = "Dummy"

                                    newCharacter.Parent = workspace;

                                end

                                local new = workspace:FindFirstChild("Dummy")

                                if new then

                                    local set = worldSpace * CFrame.Angles(0, -math.pi, 0)

                                    new:SetPrimaryPartCFrame(set)
                                end
                            else
                                local new = workspace:FindFirstChild("Dummy")
                                if new then
                                    local motor = new:FindFirstChild(b.Name, true)
                                    if motor and motor.Name == b.Name then
                                        motor.Part0 = new:FindFirstChild(b.Part0.Name)
                                        motor.Part1 = new:FindFirstChild(b.Part1.Name)
                                        motor.CurrentAngle = b.CurrentAngle
                                    end
                                end

                            end
                        end
                    end
                end
            end
        end;
    end;
end;


RunService.RenderStepped:Connect(reflect);

Thanks for your help this far. :slight_smile:

1 Like
motor.Name == b.Name

this is not needed ^

You shouldn’t have to set Part0 and Part1 every frame, but I don’t think that is messing you up. Instead of copying motor.CurrentAngle, try copying motor.Transform instead.

motor.Transform = b.Transform

Also you should create the dummy outside of the render stepped function and reference it. Make sure you are not redundantly setting the CFrame of the dummy for every part within the dummy. You only need to do that once per frame.

1 Like