I was thinking “It can’t be that much of a difference can it?”
Oh my. Time to go change some things.
I was thinking “It can’t be that much of a difference can it?”
Oh my. Time to go change some things.
Good to know! By a stroke of luck, I frequently use my own implementation of util.Create, but it already does parent assignment last so properties are what they should be when ChildAdded/etc fire.
Oh.
Oh no.
EDIT: Never mind, as far as I can tell I had been taking this into account the whole time. whew
I’ve always done this. Now I’m justified!
Time to start CTRL+F-ing
Oh dear, I was under the assumption that none of this would happen until the next frame. Better get round to some optimization.
Not to sound grumpy, but there’s a reason not to look into how ROBLOX gears works.
From a selected few gears, not only is there this sort of code, but also issues with people getting stuck with it, it’s not cross-platform compatible, and even invites to collision-related exploits for people to teleport outside of game barriers. Bites lip in disgust - that is, recode it all
A lot of CoreGui uses this, should probably look into cleaning those up.
You just gave me flashbacks on all the times I used the second/third method
Rip me, I used this at every chance I could. Guess now would be a good time to stop
I almost feel like I need to find something worse just to upset zeuxcg further.
Perhaps
Instance.new("Object")
.Transparency(0)
.Size(Vector3.new(2, 2, 2))
.Anchored(true)
.CFrame(CFrame.new(5, 5, 5))
.BrickColor(BrickColor.new("Bright red"))
.Parent(workspace)
Through the use of a metatable.
Enjoy suffering some more @zeuxcg
do
local create = Instance.new
local object, parentFunction, setFunction, tab
tab = setmetatable({}, {
__index = function (_, index)
if index == "Parent" then
return parentFunction
else
return function (value)
return setFunction(index, value)
end
end
end
})
parentFunction, setFunction = function (parent)
object.Parent = parent
return object
end, function (index, value)
object[index] = value
return tab
end
Instance = {
new = function (class)
object = create(class)
return tab
end
}
end
NEVER NEVER NEVER read ROBLOX gear code.
Please.
Oh my
Time to go change all my instancing I guess
Tbh, if your game needs this kind of optimization…
@zeuxcg wouldn’t it be possible for the engine to only start doing the queueing for new objects when the thread yields?
E.g.
local obj = Instance.new("Part",workspace) -- state: instantiation
-- set properties
-- state: still instantiation
coroutine.yield() -- or wait()
-- thread yielded, obj's state becomes "initial setup" or "doing the queueing"
Oh my. I had observed this but I hadn’t connected it to setting properties after setting Parent. Good to know.
I’ve added a warning to the wiki documentation for Instance.new.
Reading ROBLOX Gear code is how I got started with Lua in the first place.
Keep in mind in his example the first 100 parts have already been created when the second for loop runs, it would be better to test fresh both times.
I just tried it (restarting each time) and got 0.0027530193328857 and 0.10685229301453 (40x difference) over 100 iterations, which is still a lot.
For those of you wondering how to find all cases of where you may have done this, search your game with this:
Instance.new\([\s\S]*,
Make sure you check “Regular expression”
This used to be necessary to avoid having WaitForChild hang itself when parenting AND THEN renaming (now fixed I believed)
There are many issues with parenting early which are not simply performance benchmarks. A while ago I ran into an issue where I had parented a part to workspace with the surface type defaulted to studs, upon parenting the engine had automatically created snap joints with the baseplate. Immediately after I set the Parent I would also set the surface types to smooth but since the snaps were already made and they stuck around. Ultimately, my projectiles ended up a little more stationary than intended…
This anecdote may have changed in our iterations of the physics solver, but I think it still serves as a good lesson!