StreamingEnabled: Model.PrimaryPart is nil after a model's parts stream out and back in, making it impossible to use without weird workarounds

This is reproducible even in Studio. I’ve been using the iPhone 7 Plus device emulation to test it with the .rbxl provided and it happens every time. Simply run in Play Solo and do the following:

  1. Look at the PrimaryPart field of workspace.TestModel.
  2. If you walk towards it and it streams in, the PrimaryPart should read PrimaryPartTest.
  3. Walk away and it unloads and the PrimaryPart will be nil, as expected.
  4. Walk back to that part and it streams in, but PrimaryPart remains empty.

The expected behavior here is that the PrimaryPart setting is restored to PrimaryPartTest. There are no added scripts in this .rbxl to interfere with this, so it’s definitely the engine doing it. I’ve narrowed this down to being the cause of my game not functioning well on mobile devices with low amounts of memory, so it definitely is happening on the real client as well.

If the PrimaryPart is not set correctly, there is no way to tell when the model has been streamed back in, and you cannot rely on a model having its PrimaryPart set on the client even if you try to guarantee this. This is pretty critical to making a game that uses streaming. I’m still trying to think of a workaround that would bridge this gap for now, but it’s going to be pretty difficult with the way my game is structured.

I’m not sure when this started, but I’m surprised no one else seems to have reported it yet. It may have been within the last few months, but I thought it was due to something I did and wasn’t able to reproduce it until today, because I tried an emulated device with more memory, but not too much. My own phone (Samsung S20) has too much memory to run into this problem.

streamingbug.rbxl (29.2 KB)

Note: the part you’re looking for is laying on its own off to the side. Walk forward from the default spawn orientation to find it; the streaming target radius is set as low as possible to make it easier to see the problem. The giant stack of parts to the left is just for pushing up the memory usage to try to force streaming to happen.

8 Likes

Separate post for visibility: It occurs to me that it might be useful to know that the model’s PrimaryPart IS indeed set correctly the first time a model’s parts stream in to a client. I confirmed this by moving my test model far enough away that it is not initially streamed to the client.

Side note: I also checked if the part can be saved client-side and restored if it appears again, but it doesn’t look like the two instances are considered equivalent. I’m a little concerned that this might mean the part has a new GUID when it’s replicated again, but I don’t know if that’s really the case. Regardless, it seems odd that the part wouldn’t be considered equal to itself after streaming out and back in, but if this is just an implementation detail, I can live with it. It does mean I can’t use that as a workaround, though.

If anyone else is having this problem and looking for a workaround, I’m going to have the client mark models as streamed out if they have a PrimaryPart and then it’s changed to nil, which will prompt the client to request the current PrimaryPart from the server when the client sees DescendantAdded on that model. This will allow the client to resync the PrimaryPart property itself.

Thank you for the report and detailed steps. I will take a look at this.

4 Likes

I can verify that I do see the issue occur as you describe. I will investigate further to determine why this occurs.

7 Likes

Thanks! I hope the repro file makes for an easy unit test addition.

For anyone else having trouble with this, I can now confirm that my workaround described above works. I can imagine it might be a pain for others to implement, but my game’s structure made it fairly easy.

A fix for this issue is in place and will be in an upcoming release. I’ll post on this thread again when it is active on production.

I’d also like to note that the issue you mention in your second post (that the script reference after the part is streamed back in is not equal to the original reference),while not addressed by this particular fix, is currently being examined. I hope to have good news on that in the near future as well.

6 Likes

Excellent, thanks a lot! I’m not too surprised about the reference not being equal given how the Lua bridge works, but I think I assumed that the equality operator would’ve been using the instance GUID.

Can you give an ETA on when this fix will be live?

1 Like

Hello, this is currently an issue with a game I’m helping working on. Is there a workaround?

You can try to implement something similar to what I did, which I detailed above. It’s a little specific to my game but maybe you can adapt it.

1 Like

Hi, almost three months later now, it’d be great if we could have an update on when if ever that fix will go live. Thanks.