So, basically, I wrote some code that allows for a UI to replicate the player’s character model. Here’s the code in question:
rs = game:GetService("RunService")
viewport = script.Parent.Viewport
world = viewport.WorldModel
rs.RenderStepped:Connect(function()
if world:FindFirstChild("Model") then
world.Model:Destroy()
end
local char = Instance.new("Model")
char.Parent = world
for i, child in ipairs(game.Players.LocalPlayer.Character:GetChildren()) do
child:Clone().Parent = char
end
char.PrimaryPart = char.HumanoidRootPart
for i, child in ipairs(char:GetChildren()) do
if child ~= char.PrimaryPart and child:IsA("BasePart") then
local weld = Instance.new("WeldConstraint")
weld.Parent = char.PrimaryPart
weld.Part0 = char.PrimaryPart
weld.Part1 = child
elseif child:IsA("Tool") or child:IsA("Accessory") then
local weld = Instance.new("WeldConstraint")
weld.Parent = char.PrimaryPart
weld.Part0 = char.PrimaryPart
weld.Part1 = child.Handle
end
end
char.PrimaryPart.CFrame = CFrame.new(char.PrimaryPart.CFrame.Position) * CFrame.Angles(0,math.rad(-80),0)
local cam = Instance.new("Camera")
cam.Parent = world
cam.FieldOfView = 30
viewport.CurrentCamera = cam
cam.CFrame = CFrame.new(char.PrimaryPart.Position + Vector3.new(9,2,0), char.PrimaryPart.Position)
cam.CFrame *= CFrame.Angles(0,0,math.rad(-45))
end)
Here’s the hierarchy of the UI (the only important parts are all the stuff that’s in “PlayerDisplay”):
This code works almost perfectly. It clones the character and puts it in a UI, just like how I want it! The only catch is that-
it runs like bricks.
Any help improving this is appreciated!
Cloning the character every frame is less than ideal, you could very easily detect things like if the character is walking or jumping via the UI code and then play the animation on a single clone of the character.
for walking:
if humanoid.MoveDirection.Magnitude > 0 then
and for jumping, I think this will work (although I have never really done this before):
This is great for a game with the simplest controls, but my game is gonna have a lot more than the built in animations, so I’m gonna go with @SirHoog 's idea of updating the animation every time the one’s that playing changes.
rs = game:GetService("RunService")
print("creating model")
charmodel = Instance.new("Model")
charmodel.Parent = script.Parent.Viewport.WorldModel
charmodel.Name = "Character"
function getchildren()
task.wait()
local success, em = pcall(function()
for i, child in ipairs(game.Players.LocalPlayer.Character:GetChildren()) do
local newpart = child:Clone()
newpart.Parent = charmodel
end
end)
if not success then
wait(em)
charmodel:ClearAllChildren()
getchildren()
end
charmodel.PrimaryPart = charmodel.HumanoidRootPart
charmodel.PrimaryPart.CFrame = CFrame.new(0,0,0)
end
getchildren()
cam = Instance.new("Camera")
cam.Parent = script.Parent.Viewport.WorldModel
cam.CFrame = CFrame.new(Vector3.new(9,2,0), charmodel.PrimaryPart.Position)
cam.FieldOfView = 70
cam.CameraSubject = charmodel
script.Parent.Viewport.CurrentCamera = cam
oldtracks = nil
rs.RenderStepped:Connect(function()
cam.CFrame = CFrame.new(game.Players.LocalPlayer.Character.PrimaryPart.Position + Vector3.new(9,2,0), charmodel.PrimaryPart.Position)
if oldtracks ~= game.Players.LocalPlayer.Character.Humanoid.Animator:GetPlayingAnimationTracks() then
for i, track in ipairs(charmodel.Humanoid.Animator:GetPlayingAnimationTracks()) do
track:Stop()
end
charmodel.Humanoid.Animator:LoadAnimation(game.Players.LocalPlayer.Character.Humanoid.Animator:GetPlayingAnimationTracks()[1].Animation):Play()
end
oldtracks = game.Players.LocalPlayer.Character.Humanoid.Animator:GetPlayingAnimationTracks()
end)
Don’t worry about that script. I started over and rewrote the script, and I’ve fixed two of the three issues.
task.wait()
rs = game:GetService("RunService")
charmodel = script.Parent.Viewport.WorldModel.Character
cam = Instance.new("Camera")
cam.Parent = charmodel.Parent
charmodel.Parent.Parent.CurrentCamera = cam
cam.FieldOfView = 30
oldtracks = nil
rs.RenderStepped:Connect(function()
print(oldtracks)
cam.CFrame = CFrame.new(-1,0,-10) * CFrame.Angles(math.rad(-180),math.rad(-5),math.rad(135))
if oldtracks ~= game.Players.LocalPlayer.Character.Humanoid.Animator:GetPlayingAnimationTracks() then
for i, track in ipairs(charmodel.Humanoid.Animator:GetPlayingAnimationTracks()) do
track:Stop()
end
charmodel.Humanoid.Animator:LoadAnimation(game.Players.LocalPlayer.Character.Humanoid.Animator:GetPlayingAnimationTracks()[1].Animation):Play()
end
oldtracks = game.Players.LocalPlayer.Character.Humanoid.Animator:GetPlayingAnimationTracks()
end)
When an animation starts playing, after a bit of time it’ll just… stop. Like it’ll stop playing until a new animation starts playing, and it’ll do the same thing. It’s strange.
I’m checking to see if the animations being played are the same because when you constantly send AnimationPlay requests it screws things up and is not great for performance, therefore putting me back at where I was at at the beginning.
I’m gonna hit the sack, but I’ll post the finalized script tomorrow in case anybody needs it. You never know when someone’ll stumble upon this post 3 years later.
I’m almost finished, but there’s one thing still bugging me.
I tried to implement a system where the tool’s in the player’s character would clone over to the preview of the character in the box, and while the tool does go in the preview, it’s heavily offset, and its tool grips are being ignored by the player.
Any help with this?
task.wait()
rs = game:GetService("RunService")
charmodel = script.Parent.Viewport.WorldModel.Character
cam = Instance.new("Camera")
cam.Parent = charmodel.Parent
charmodel.Parent.Parent.CurrentCamera = cam
cam.FieldOfView = 30
oldtracks = nil
rs.RenderStepped:Connect(function()
cam.CFrame = CFrame.new(-1,0,-10) * CFrame.Angles(math.rad(-180),math.rad(-5),math.rad(135))
oldtracks = game.Players.LocalPlayer.Character.Humanoid.Animator:GetPlayingAnimationTracks()
if charmodel:FindFirstChildWhichIsA("Tool") ~= nil then -- clone tools
if game.Players.LocalPlayer.Character:FindFirstChildWhichIsA("Tool") ~= nil then
if charmodel:FindFirstChildWhichIsA("Tool").Name ~= game.Players.LocalPlayer.Character:FindFirstChildWhichIsA("Tool").Name then
charmodel:FindFirstChildWhichIsA("Tool"):Destroy()
game.Players.LocalPlayer.Character:FindFirstChildWhichIsA("Tool"):Clone().Parent = charmodel
end
else
charmodel:FindFirstChildWhichIsA("Tool"):Destroy()
end
elseif game.Players.LocalPlayer.Character:FindFirstChildWhichIsA("Tool") ~= nil then
game.Players.LocalPlayer.Character:FindFirstChildWhichIsA("Tool"):Clone().Parent = charmodel
end
if oldtracks ~= game.Players.LocalPlayer.Character.Humanoid.Animator:GetPlayingAnimationTracks() then
for i, track in ipairs(charmodel.Humanoid.Animator:GetPlayingAnimationTracks()) do
local found = false
for i, subtrack in ipairs(oldtracks) do
if subtrack.Animation.AnimationId == track.Animation.AnimationId then
found = true
end
end
if found == false then
track:Stop()
end
end
for i, track in ipairs(game.Players.LocalPlayer.Character.Humanoid.Animator:GetPlayingAnimationTracks()) do
local playingtracks = charmodel.Humanoid.Animator:GetPlayingAnimationTracks()
local found = false
for a, subtrack in ipairs(playingtracks) do
if subtrack.Animation.AnimationId == track.Animation.AnimationId then
found = true
end
end
if not found then
charmodel.Humanoid.Animator:LoadAnimation(game.Players.LocalPlayer.Character.Humanoid.Animator:GetPlayingAnimationTracks()[i].Animation):Play()
end
end
local playingtracks = {}
for i, track in ipairs(charmodel.Humanoid.Animator:GetPlayingAnimationTracks()) do -- removes excess tracks playing
if table.find(playingtracks, track.Animation.AnimationId) then
track:Stop()
else
table.insert(playingtracks, track.Animation.AnimationId)
end
end
end
end)
Not sure why it isn’t covering as much but there you go.
The code I used:
char = game.Players.LocalPlayer.Character
cam = Instance.new("Camera",script.Parent)
game:GetService("RunService").RenderStepped:Connect(function()
for i,v in pairs(script.Parent.ViewportFrame.Character1:GetDescendants()) do
v:Destroy()
end
for i,v in pairs(char:GetChildren()) do
local v2 = v:Clone()
if v2:IsA("Script") or v2:IsA("LocalScript") or v2:IsA("ModuleScript") then
v2:Destroy()
else
v2.Parent = script.Parent.ViewportFrame.Character1
if v2:IsA("Humanoid") then
v2.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.None
end
end
end
script.Parent.ViewportFrame.CurrentCamera = cam
cam.CFrame = game.Players.LocalPlayer.Character.HumanoidRootPart.CFrame * CFrame.new(-2,2,-5) * CFrame.Angles(math.rad(5),math.rad(200),math.rad(20))
end)
(I think it’s a terrible free model I got a year ago actually…)