Updates to Streaming Enabled

THANKS U, we don’t need to manually fix A-Chassis anymore!!

9 Likes

Here’s my attempt at doing what you said, I tried to copy the errors and behavior the WaitForChild function has:

function WaitForDescendant(parent: Instance, name: string, t: number?): Instance?
	if parent == nil then error("Argument 1 missing or nil") end
	if name == nil then error("Argument 2 missing or nil") end
	if typeof(parent) ~= "Instance" then error("Argument 1 must be an Instance!") end 
	name = tostring(name) 
	local descendant = parent:FindFirstChild(name, true)
	if descendant then return descendant end
	if type(t) ~= "number" then t = 5 end 
	local start = os.clock()
	local result = nil 
	local connection: RBXScriptConnection
	connection = parent.DescendantAdded:Connect(function(descendant: Instance)
		if descendant.Name ~= name then return end 
		connection:Disconnect()
		result = descendant 
	end)
	repeat task.wait() until result or os.clock()-start > t 
	if not result then 
		connection:Disconnect()
		warn("Infinite yield possible on '"..parent.Name..":WaitForDescendant(\""..name.."\")'") 
		task.wait(3.402823328927018e+38)
	end 
	return result 
end
10 Likes

Not sure which one, but one of these is an issue with my game, Bloxy Kart in the Race place. Turning on StreamingEnabled completely breaks the Kart system probably because it uses legacy joints and Body Movers. I unfortunately tried converting them to the new system but it has not worked out well. As soon as these fixes ship, I will enable StreamingEnabled in the beta version of Bloxy Kart!

8 Likes

one liner “WaitForDescendant”

repeat task.wait() until workspace:FindFirstChild("Object",true)

you can also

repeat task.wait() until workspace:FindFirstDescendant("Object")

and its the exact same thing both of those search for the descendant

13 Likes

Uhhhhhh that’s not really good for performance but, ok, it works I guess! :person_shrugging:

8 Likes

The post is a bit old, but the problem has reappeared lately

8 Likes

Thanks for taking the time! I’m aware that there’s a way to create a function that does this. For the record, here’s how I implement it when I need it:

local function WaitForDescendant(Ancestor, Name)
	assert(typeof(Ancestor) == "Instance", "Ancestor is not an Instance")
	assert(type(Name) == "string", "Name is not a string")
	
	local Descendant
	
	repeat
		Descendant = Ancestor:FindFirstChild(Name, true)
			or Ancestor.DescendantAdded:Wait()
	until Descendant and Descendant.Name == Name
	
	return Descendant
end
9 Likes

Thanks for taking the time to reply! First of all it’s worth noting that FindFirstDescendant has never been enabled.

Second of all, these methods require polling, which is inefficient, and they don’t support a timeout. To circumvent that, other similarly inefficient methods must be used. I’m advocating for a better, engine-implemented way.

8 Likes

This especially, is awesome. I’d really want to make this a setting in my game or have it as a script-controlled automatic setting for players with different hardware and network conditions.

By the way wouldn’t it help the server performance more than hurting it? If I have 20 players with 256 min. streaming radius vs 10 with 256 but 10 with 96 for example.

While I’m here I’d like to give some feedback:

  • There’s a bug which results in terrain loading spiked (with deformed triangles) if streaming radius is less than 96. It happens with 96 and 64 and doesn’t happen with 128 min. streaming radius, I think this is a known issue, is a fix for this on the way?

  • I use a system where elevators teleport to upper floor or another terrain piece. Players can use it together so I can’t yield the elevator for player loading, if I don’t though, some players just fall off of the map while loading. I have to use some sort of invisible local part tricks to fix this, maybe the collision data should be provided earlier than terrain textures or I’m sure Roblox has a better solution, just wanted to give feedback on this.

6 Likes

well I guess use the FindFirstChild(“name”,true) method (its alternative of FindFirstDescendant when you pass the second argument as true)

6 Likes

Your code relies on polling and weird magic numbers, here’s a version I’ve used for a long time for my own game:

local function WaitForDescendant(Parent: Instance, Child: string, TimeOut: number?)
    local AlreadyFound = Parent:FindFirstChild(Child, true)
    if AlreadyFound then
        return AlreadyFound
    end

    local Connection
    local TimeOutThread

    local Thread = coroutine.running()

    Connection = Parent.DescendantAdded:Connect(function(Descendant)
        if Descendant.Name == Child then
            Connection:Disconnect()
            if TimeOutThread and coroutine.status(TimeOutThread) == "suspended" then
                task.cancel(TimeOutThread)
            end

            task.spawn(Thread, Descendant)
        end
    end)

    if TimeOut then
        TimeOutThread = task.delay(TimeOut, function()
            if Connection.Connected then
                Connection:Disconnect()
                task.spawn(Thread)
            end
        end)
    end

    return coroutine.yield(Thread)
end
8 Likes

I wonder if any of this solves the consistent replication problems I have been having.

I needed to play an animation when a part spawned, what I was doing before was firing a remotevent with the part as the argument, then animating it. With streaming enabled, even with the parts being marked to always be persistent, the parts were “slow” replicating - They were taking the Streaming process despite being persistent, and therefore came after the remote event fired, not before.

I got around that problem by giving them a unique ID tag so that if this happens, I can use the collection service to figure out what the part is still (probably a weird way to do it, but I had no other options)

Unfortunately this lead to a further consistent bug that I can’t even tell if is in my code or roblox’s - Everything fires correctly, but the things never animated. I think at the time of checking, the properties were seemingly changed correctly but were just… wrong. Like because of how I did it, it just wasn’t applying my changes or something very unusual. I’d print, it’d say it’s made the brick do what I want, but then would still just… not have an effect. Literally could not track this one down because it’s embedded into a lot of unusual code, so it’s hard to tell how far the rabbit hole goes here!

why am I so good at finding ridiculous bugs?

4 Likes

So, here is a major streaming issue, and this is the sole reason why I do not use streaming on any of my places.

Let’s say I have a place focused on trains, which happens to be all of mine quite frankly. If I have a train which is, say, 20 cars long, everything is fine. However, if I have a train that is 40-50 cars long, the rear end of the train un-streams because it is farther away and the whole thing freezes and breaks. This is because there is no way to adjust the way object physics streams. The railcars on the train are connected via constraints, usually rods or ropes.

For this reason, my places will never use streaming because trains of that length are commonplace for us. As a replacement, I use a client-sided chunk loader for scenery objects, which isn’t as efficient as streaming would be but using streaming is physically impossible in our places.

9 Likes

I’m not exactly sure what the problem is - Streaming enabled somewhat recently has given the option to make things persistent. You can set the train cars, at least the base/primary parts of them and such, to be permanently streamed in. You can also set the entire train to Atomic, which would mean the train only is either loaded in, or loaded out, with no inbetween.

If the train is being physically controlled by the server, I don’t see how this would cause issue. Can you describe the problem more in-depth, as well as telling me some of the steps you’ve already tried to fix it with? There might be some solutions yet to the issue, rather than it being a problem with streaming enabled.

9 Likes

sorry if this sounds ignorant but how is the train breaking if it’s being physically simulated on the server?

4 Likes

I agree with this. Render performance out of the box should get better.

Right now, achieving a high framerate on these large worlds is 100% possible, but needs (arguably considerable) manual intervention, by running systems such as custom distance culling (that also takes into account the importance of the object - so, stuff like pebbles should only be rendered while close), and LODs. I’d say Roblox’s largest rendering performance draw right now is the fact there is no occlusion culling.

Edit: I mean these systems can and have been made in Luau, which is able to run them with good performance, if optimized well.

9 Likes

While i’d like to give them the benefit of the doubt, I’d reckon they might be giving an individual player network ownership in this situation. That sounds like the quickest way to make a train stop functioning - second the player with physics ownership steps away from part of the train, the entire train stops functioning.

6 Likes

Yup it sounds like the networkownership is on a client for sure.

3 Likes

This however forces Roblox to go through the entire workspace hierarchy (until it finds the desired instance) every heartbeat which is wildly wasteful and inefficient, this may not cause problems in a very small game but in games with a lot of instances it will have to go through this can definitely impact performance.

4 Likes

I’m hopeful for the addition of the streaming exclusion feature. Being able to exclude certain models from being streamed to specific players is the last missing feature for StreamingEnabled in my opinion.

5 Likes