Hello, my name is Mark_GoodMan, today i'll show you how to make a REALISTIC MIRROR, thanks to sStillWater for this script, like a VERY BIG THANKS to him lol. Right, now let's get into making the MIRROR!
Before you say anything like i stole sStillWater's script or anything, i made this tutorial because there are many people having trouble with making a mirror, the video sStillWater made was not fully detailed and 70% people saying it doesn't work for them, so before saying this script wasn't made by me and i stole it from him, i made this to help people how to make a mirror, 100% fully detailed and accuracy, the video on youtube is a bit too fast and slow reader may have trouble making the mirror, so i made this to help people learn how to completely make a working mirror, and to make your game success, thank you for reading!
I know this may be easy just by adding parts, but no, you need to change it's details correctly.
Now insert a Model, then rename it to "Mirror model", then insert "Part" in it (as shown in the image)
Now after you add the Part, scale the part to full size of map (as shown in the image)
After it, now select it and go to properties and then change the following appearance (as shown in the images below).
After you change the properties of the part, now go to StarterGui and insert "LocalScript"
After putting LocalScript in StarterGui, rename it to mirrors.
Now click on LocalScript (mirrors) and enter the following script:
-- StarterGUI:
-- LocalScript:
-- Name The LocalScript: mirrors
local player = game:GetService("Players").LocalPlayer
local character; repeat wait() character = player.Character until character
local camera = game:GetService("Workspace").CurrentCamera
local rs = game:GetService("RunService").RenderStepped
local reflections = require(script:WaitForChild("reflections"))
local mirrors = game:GetService("Workspace"):WaitForChild("Mirror model")
rs:connect(function()
reflections:clearCharacters()
local characters = {}
for _, player in pairs(game:GetService("Players"):GetPlayers()) do
table.insert(characters, player.Character)
end
for _, mirror in pairs(mirrors:GetChildren()) do
if mirror:IsA("BasePart") then
reflections:drawWorld(mirror, game:GetService("Workspace"), {mirrors, unpack(characters)})
reflections:drawCharacters(characters, mirror)
end
end
end)
Now after you done putting the script into the LocalScript (mirrors), now right click on LocalScript and insert ModuleScript
After inserting ModuleScript, rename it to reflections.
Now click on ModuleScript (reflections) and enter the following script:
--// Declarations
local class = {}
local camera = game:GetService("Workspace").CurrentCamera
local renderPacket = {}
local reflections = Instance.new("Model", camera)
local users = Instance.new("Model", reflections)
local environment = Instance.new("Model", reflections)
reflections.Name = "reflections"
users.Name = "users"
environment.Name = "environment"
--// Functions
--[[
Collects all items recursively in a certain class range.
@param children: A table full of instances that the function will search
@param class: The type of instance (IsA method used) that is required
@param tab: If adding to another table this parameter may be used.
@return A table containing all the instances that met the requirements.
--]]
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
--[[
Collects all items recursively in a certain class range with a given instance ignore list (including decendants).
@param children: A table full of instances that the function will search
@param class: The type of instance (IsA method used) that is required
@param ignores: Table of instances that can be ignored
@return A table containing all the instances that met the requirements.
--]]
function gather_Ignores(children, class, ignores)
local tab = {}
for _, part in pairs(gather(children, class)) do
local pass = true
for _, thing in pairs(ignores) do
if part == thing or part:IsDescendantOf(thing) then
pass = false
end
end
if pass then
table.insert(tab, part)
end
end
return tab
end
--// Methods
--[[
Reflects item on local x axis.
@param item: The instance (model or basepart) that will be reflected.
@param against: The instance (basepart) that will be used as the reflection origin (mirror).
--]]
function class: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
--[[
Reflects item on local x axis.
@param item: The instance (model or basepart) that will be reflected.
@param against: The instance (basepart) that will be used as the reflection origin (mirror).
--]]
function class:drawWorld(against, parent, ignores)
table.insert(ignores, camera)
local renders = gather_Ignores({parent}, "BasePart", ignores)
renderPacket[against] = renderPacket[against] or {}
for _, part in pairs(renders) do
if (not part.Locked or part.Parent:IsA("Hat")) and part.Transparency < 1 then
if not renderPacket[against][part] or renderPacket[against][part].cf ~= part.CFrame then
if renderPacket[against][part] then
renderPacket[against][part].focus:Destroy()
end
local focus = part:Clone()
local joints = gather(focus:GetChildren(), "JointInstance")
for _, joint in pairs(joints) do joint:Destroy() end
focus.Anchored = true
self:reflect(focus, against)
focus.Parent = environment
renderPacket[against][part] = {
cf = part.CFrame;
origin = part;
focus = focus;
event = part.AncestryChanged:connect(function() focus:Destroy() end);
}
end
end
end
end
function class:drawCharacters(characters, against)
for _, character in pairs(characters) do
character.Archivable = true
local character = character:Clone()
local hum = character:FindFirstChild("Humanoid")
local scripts = gather(character:GetChildren(), "BaseScript")
local parts = gather(character:GetChildren(), "BasePart")
local joints = gather(character:GetChildren(), "JointInstance")
if hum then
hum.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.None
end
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
self:reflect(part, against)
end
character.Parent = users
end
end
function class:clearCharacters()
users:ClearAllChildren()
end
function class:cleanup()
environment:ClearAllChildren()
users:ClearAllChildren()
renderPacket = {}
end
return class
And after you pasted the script in the ModuleScript (reflections), your done, now try to run the game in studio, you should see yourself on the otherside of the mirrors as it follows all of your movements correctly, just like i did see myself, the script is still working btw. It also reflect model and NPC and props, let's just say for short it will definitely reflect everything it sees.
So recently i did some mirror test and they all worked, but the problem here is that they reflects the wrong way (as shown in the image)
The reason for this is because the scale is at the wrong position, if you rotate it's still the same, to fix this we just need to rescale it to the other side of the map (not rotating)
After scaling it to the other side of the map, now it should reflect you normally and fine, that's all for the bugs fixing!
yet this is script made by sStillWater, shoutout to him. Also i'll be checking on this tutorial, so if the script is outdated or not working now, then i'll try to find a way to fix it.
Last time viewed this tutorial was 3/27/2020, thank you for reading :D