First post here, so apologies if anything’s a little rusty!
So I’ve been trying to create a unique afterimage-like effect for a moving, unanchored part. The effect I intended on creating was a group of multiple carbon copy clones of said part that copied every movement and rotation the part made with about a second of delay, in smaller increments for each clone.
I’ve tried using AlignPosition, which did not give the intended effect I was looking for, as it had a lot of drag in its alignment to the main part.
CFrame seems to be what I’m after but I still couldn’t get it to work how I envisioned. The code below almost works for me, but the first clone always renders in front of the the main part for some reason, predicting the movements of the main part in a way.
I’m also not entirely sure how to add delays between the parts properly.
local part = script.Parent
script.Disabled = true
local follower = part:Clone()
follower.Parent = part
follower.Position = part.Position
follower.CanCollide = false
follower.Anchored = true
local follower2 = follower:Clone()
follower2.Parent = part
follower2.Position = part.Position
follower2.CanCollide = false
follower2.Anchored = true
while true do
follower.CFrame = part.CFrame:ToWorldSpace()
task.wait(.01)
follower2.CFrame = follower.CFrame:ToWorldSpace()
end
Any help is super appreciated I’m still learning a lot so there’s something super silly I probably missed haha.
I’m not entirely sure I’m doing this correctly but I tried adding your code samples into mine but I got an error at follower.CFrame = history[#history - 4]
I’m also a little new on some terminology, Is the Index the 4? I know the basics of heartbeat too but I am still a little lost.
i was not at my computer to check. but i’m trying to record the cframes in array
history = { cframe1, cframe2, cframe3, cframe4, cframe5 } -- for example, after 5 records
print(#history) -- it should print 5
print(#history - 4) -- it should print 1
-- history[#history - 4] = history[1] = 4 cframes before the current time, so
follower.CFrame = history[#history - 4] -- set follower to be the cframe of part in the past
local part = script.Parent
local followers = {}
local followerAmount = 2 -- how much followers you want, recommended max 4-5
local smoothness = 0.8 -- 0.00-1.00, lower = smoother
function createFollower(base) -- creates a follower based on the base part
local fwr = base:Clone()
fwr.Anchored = true
fwr.CanCollide = false
fwr.Parent = base
return fwr
end
for i = 1, followerAmount do -- creates the followers and puts them on table
followers[i] = createFollower((i==1 and part) or followers[i-1])
end
game["Run Service"].Heartbeat:Connect(function(delta)) -- main func
for index, follower in followers do
if not (follower:IsA("BasePart") and follower.Parent and follower.Parent:IsA("BasePart")) then -- check if the follower is valid
followers[index] = nil
continue
end
follower.CFrame = follower.CFrame:Lerp(follower.Parent.CFrame, smoothness) -- smooth effect
end
end
i recommend running this on a local script
you can also just set an script’s RunContext to client and put it under the part you want
Even with this understanding im still experiencing the error, does it have something to do with the fact the history table is called before any cframes are listed?
01:19:31.996 Unable to assign property CFrame. CoordinateFrame expected, got nil - Server - CFrame:24```
What you see here is what I call a “one-line conditioner”
I’ll explain; (i==1 and part): this is checking if i is equal to 1, and if yes, it will return part, so the function would be createFollower(part)
But if i is not 1, then it will use followers[i-1], which is just i-1 (a past part that is registered already in the table, i.e. if i is 3 then it will look for followers[2]), which is expressed by the or statement, so the function would be createFollower(followers[i-1])
This is just to compress the code, but something equal to this would be
if i == 1 then
createFollower(part)
else
createFollower(i-1)
end
Yeah! I just found out why, it was because when the part was being cloned, the script would be cloned and it would repeat the entire process, duplicating and well, crashing
Here’s the fixed version
local part = script.Parent
local followers = {}
local followerAmount = 2 -- how much followers you want, recommended max 4-5
local smoothness = 0.6 -- 0.00-1.00, lower = smoother
local cloneTransparency = 0.65 -- more transparency would make it look better
function createFollower(base) -- creates a follower based on the base part
local fwr = base:Clone()
fwr:ClearAllChildren()
fwr.Anchored = true
fwr.CanCollide = false
fwr.Transparency = cloneTransparency
fwr.Parent = base
return fwr
end
for i = 1, followerAmount do -- creates the followers and puts them on table
followers[i] = createFollower((i==1 and part) or followers[i-1])
end
game["Run Service"].Heartbeat:Connect(function(delta) -- main func
for index, follower in followers do
if not (follower:IsA("BasePart") and follower.Parent and follower.Parent:IsA("BasePart")) then -- check if the follower is valid
followers[index] = nil
continue
end
follower.CFrame = follower.CFrame:Lerp(follower.Parent.CFrame, smoothness) -- smooth effect
end
end)
OH, now that you mention it, my original script did crash for a similar reason before added the script.Disabled = true
I’m testing it now and the parts are still kinda rendering infront of the original part, I havent moved to a local script, is that why?
I’m going to mark your second script as the solution as you’ve helped me more than I deserve, thank you so so so much for your time.
Before I finish for the night would there be any way to add some delay between the copies?
by lowering the smoothness it will simulate more delay.
about this; its not really why but i really really recommend using a local script instead, its as easy as setting a server script’s RunContext to Client. To solve that, just add this line on the createFollower() function;
Sorry for the Delayed response but I went to bed, I’ve tried using a local script instead, and added that fwr.Size *= 0.99 to the create function but nothing shows up?
I’m also noticing the clones sometimes take shortcuts when trying to copy the movements of the origin part, as in they dont take the direct path it took. I’ve seen something like this in a game before but i;m not sure if its super complicated.
If i’m understanding correctly, theoretically I wanna set the smoothness to 0 so each clone copies the movement of the part exactly, but then I’d have the parts have a delay between when they actually register the now, previous position of the part, but they keep a consistent time delayed between the movement.