Hello! I’m attempting to recreate a mirror in my small puzzle game. The games not going anywhere its just serving as a way to learn.
Whats going on is the players character is copied, and cloned to the opposite side of a part called “Mirror” in the workspace. With some math I wrote at 3am and dont remember how I did I accurately turn the clone to a position that what a real life mirror would resemble.
The issue is the clone is a still character and I have no clue how to copy animations! Any help is appreciated.
Edit: Im having issues with the video so let me know if it doesnt work, however, a streamable link should be HERE
-- Variables
local Players = game:GetService("Players")
local plr = Players.LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
local HRP = char:WaitForChild("HumanoidRootPart")
-- Clone the character
char.Archivable = true
local clone = char:Clone()
char.Archivable = false
-- Make all the parts in the clone not collidable to prevent issues
for i, child in ipairs(clone:GetDescendants()) do
if child:IsA("BasePart") then
child.CanCollide = false
end
end
-- Not really used but set the clone to a default spot and set his parent to the workspace
local C_HRP = clone.HumanoidRootPart
C_HRP.Anchored = true
C_HRP.CFrame = CFrame.new(workspace:WaitForChild("CloneSpawn").Position.X, workspace:WaitForChild("CloneSpawn").Position.Y + 10, workspace:WaitForChild("CloneSpawn").Position.Z)
clone.Name = "CLONE"
clone.Parent = workspace
-- Wait a bit to prevent issues
wait(3)
while char do
task.wait()
-- calculate the distance from the mirror and the player to determine how far the clone should be
local distanceFromMirror = workspace.Mirror.Position.X - HRP.Position.X
-- z is a variable that is the players humanoidRootPart position but edited if its outside of the mirror space if that makes sense.
local z
if HRP.Position.Z > -274.5 then
z = -274.5
elseif HRP.Position.Z < -417.5 then
z = 418
else
z = HRP.Position.Z
end
-- create a Vector3 with the clones information
local mirroredPosition = Vector3.new(
workspace.Mirror.Position.X + distanceFromMirror,
HRP.Position.Y,
z
)
-- stuff i did at 3am dont ask how i did it
-- Calculate mirrored Y-axis rotation
local mirroredRotationY = -HRP.Orientation.Y -- Negate only the Y-axis rotation
-- Set the CFrame of the clone's HumanoidRootPart
C_HRP.CFrame = CFrame.new(mirroredPosition) * CFrame.Angles(0, math.rad(mirroredRotationY), 0)
end
In the player’s character, there’s a local script called animations. Copy that to the cloned character.
EDIT:
Upon further thought, you don’t need this. What you do need however is a server script in the cloned character that copies the positions of all the MotorD6’s in reverse periodically…as well as the CFrame of the character’s root part…
Something like this:
local runService = game:GetService("RunService")
local ccharMotorD6 = {}
local pcharMotorD6 = {}
local cchar = script.Parent
local pchar = script.ObjectValue.Value
-- Creates a MotorD6 reference table for the cloned character.
for _, item in ipairs(cchar:GetDescendants()) do
if item:IsA("MotorD6") then
table.insert(ccharMotorD6, item)
end
end
-- Creates a MotorD6 reference table for the player character.
for _, item in ipairs(pchar:GetDescendants()) do
if item:IsA("MotorD6") then
table.insert(pcharMotorD6, item)
end
end
-- Render stepped event handler. Runs on every frame before
-- the frame is rendered.
local tablelen = #pcharMotorD6
local cframe
runService.RenderStepped:Connect(function(dt)
for i = 1, tablelen, 1 do
cframe = pcharMotorD6[i].C0
ccharMotorD6[i].C0 = cframe
cframe = pcharMotorD6[i].C1
ccharMotorD6[i].C1 = cframe
end
end)
In general, this should copy the player’s animation movements over to the clone, exactly. You may need to modify things to make it a mirror image.
EDIT 2:
The ObjectValue mentioned above is an ObjectValue where the value is the player’s character. That’s needed so the script knows which character to copy. It’s set when the player is cloned. And it should be a server script, not a local script.
Late response, but was this tested? I appreciate the support, but there are a few issues.
I did try this, however the “Animate” script is a local script which doesn’t work on the Clone as it would need to be a Server Script, unfortunitly I was not able to find a way to copy the contents of one script to another (the local script to the server script which I would create for this situation)
Took me a second to realize that MotorD6’s are actually Motor6D’s, but no worries it happens to everyone. But the RunService cannot be used on the server. And it looks like after looking into Motor6D’s a bit more, they are more for welding and less of altering the orientation or positions of parts.
Actually, <CTRL>-A, <CTRL>-C, <CTRL>-V on Windows or it’s equivalent on Macs. There’s a few items in the code that will need to be commented out towards the end, but it’s possible and doable. To use it as a local script, there’s something else that needs to be done and I can’t remember what it was at the moment.
Yeah, it was late at night. Actually, Motor6D’s are used not only for welding, but also altering the orientation and position of parts because when you animate a rig, it’s the Motor6D’s that are manipulated. No, I didn’t test it, just came up with it from the top of my head. And yes, you can use render stepped on the server, I’ve done it.