(Solved) Probable cause for parts either staying rendered or not rendering at all?

Haven’t actually started scripting the camera yet, I’ll work on getting a basic scriptable camera out and see if that solves the problem.

Ok, so in your case (and I bet Phantom Forces is the same) the problem is relatively straightforward.

Parts are grouped for rendering purposes into clusters, and a cluster has to be invalidated if parts inside it change other than CFrames being updated. I know that Phantom Forces does that all the time for the humanoids by animating the welds (which is bad for performance and I still don’t really understand why it does not use Motor6Ds but that’s a separate conversation); I’m not sure yet why your game has the same behavior - will look into it tomorrow.

Anyway, so what happens is that these clusters are put in a queue whenever they have to be updated, and we only process a few clusters from that queue to try to keep the game realtime. Unfortunately, this queue does not have a well defined ordering so if some clusters are constantly invalidated they can get “in front” of other clusters every time something changes so we end up constantly updating some clusters and never updating other. Which is why you’re seeing what you’re seeing.

It should not be hard to maintain a proper update order. I’ll look into doing this (not sure about next week, probably the week after that).

7 Likes

Sounds great, at least I know what the issue is now! Please do let me know when you look into this so that I know when I can get back to work. In the meantime I’ll work on some other projects. :happy1:

We do use Motor6Ds.

1 Like

Hmm. Right, sorry. I think there’s something else that you guys do that is not ideal for rendering perf… I’ll need to look into this again. I looked very briefly before the winter break but then forgot all the details.

1 Like

So I believe the root cause in your case is - similar to PF - the manual “animation” of Motor6Ds by changing C0/C1.

Motor6D has another CFrame “in between” C0/C1 that’s designed for being free to change (this is what the built-in animation system is driving); changing C0/C1 requires rebuilding some rendering data currently.

I have a tentative fix to make C0/C1 of Motor6D animatable (ideally we’d expose the third cframe in Lua API instead of just one angle but that’s a bigger change and would require changing the scripts). I think I want to make that fix first and not do anything about the queueing mechanism for now - the fix can ship next week (of course it can also break something I’m not thinking of right now…)

P.S. In your case I also sometimes see joints being removed/readded but it could just be people dying/resetting; I hope you aren’t destroying joints every frame on render stepped!

7 Likes

Definitely not re-making joints every frame haha, that’d be insane. It’s likely just players resetting, as all the joints have to be reinitialized on spawn for the new kart.

We are constantly setting the C0s of the Motor6Ds, though, and are not actually using the angle stuff. I don’t know if this is as bad as constantly setting the C0 of Welds. But I mean, how else am I going to do all the foot planting and gun holding and what not?

(Sorry this is late, my Internet connection has been down for hours.)

No no no! I think there was some weird or unwanted behavior happening when we used the joints the player spawned with, or maybe they replicate or something, I don’t remember. But when a new character is loaded, on each client, we remove the joints on the client and replace them with our own joints. Remember on PF, none of your body animations are processed on your own client, Every other client processes your body’s animations.

https://i.gyazo.com/d7dbacf1ead12317ca630bafa0414e70.gif

https://i.gyazo.com/2621a18a5d0081e54209796c91790197.gif

Yeah, Motors are much better than welds. If you change C0/1 on welds we have a reason to regenerate render data. If you change C0/1 on motors we also do that but at least that’s accidental and we can fix that :slight_smile:

You do not have a better way right now. I’m just saying it would be good to have Motor6D fully exposed to Lua - the design intention is that C0/C1 define the points on the respective parts that are joined together, and the other cframe controls the relative position - so ideally you specify C0/C1 once and then animate the cframe. Which is what our animation system is doing, you just can’t do the same thing in Lua right now.

6 Likes

I do the exact same thing in my game, except with boats.

Yes! Please yes! Please expose this API. I’d actually be willing to pay money for this feature. This saves me from:

  1. Replicating default C0/C1 values over to animating clients (an extra network request / handshake)
  2. Having part clusters recalculated (as noted before).

Right now I’m using ManualWelds for my animations.

We had this discussion before, and although I found the issue (JointService wasn’t GCing removed joints, for some reason, leading to errors somehow, resulting in boats going to -inf), I’m still experiencing performance issues with animating welds.

1 Like

Not sure if this has been mentioned before but - I use anchored parts for animation and do the math for C1/C0 in welds with a module. It lets me do some crazy stuff (90 humanoids with one hat and one union weapon) without slowdown.

1 Like

I’ve done this before. In my situation, this doesn’t work because I’m relying on ROBLOX’s physics (remember: boat simulation). The other issue with this is you have to maintain a render-frame update rate, where as I am scaling my updating rate based upon camera distance.

Local rendering lets you do that second part.

Changing CFrame on an anchored part is fine, we don’t really use the Anchored flag for any rendering optimizations.

Just don’t animate C0/C1 on welds.

Welds have rendering optimization but anchored parts don’t? So, from a rendering perspective, a welded brick wall is more efficient than an anchored brick wall?

No, the efficiency of a welded brick wall is the same as anchored brick wall from rendering perspective (physics-wise anchored wall is better but probably not too much).

The issue is really about reconfiguring welds. When two parts are welded together we assume the relative cframe rarely changes. If it changes frequently we execute expensive operations more frequently than we’d like.

1 Like

Basically, for rendering there are two important questions we need answers to for every part:

  • Does this part move?

We used to use Anchored for this but this can result in a lot of parts classified as moving when they don’t (e.g. a lot of debris that settled) and a lot of moving parts get classified as non-moving (turns out a lot of devs cframe anchored parts continuously!). Now we don’t, and instead use a sleeping system where a part is classified as non-moving if it does not move for a while.

  • Does this part move the same way as some other part?

We use weld relationships for this. The intent is to make rendering a bunch of parts welded together fast, even if the entire clump of parts is moving (e.g. physically simulated). This is why changing rigid joints is more expensive than changing non-rigid joints.

2 Likes

We shipped an update last night that fixes this issue. You can still see updates queueing in contrived cases, but motor updates now do not cause invalidations which as far as I can tell solves the issue in your game, solves the Phantom Forces issues and also reduces rendering workload by a few ms/frame on PF.

If you ever have this issue again, there’s now a stat on the Rendering stat panel (Ctrl+Shift+F2) - in the Geometry Gen line at the bottom, “queue” specifies the amount of clusters (groups of parts) that are in the update queue. Normally you’d expect this to be 0 or close to 0; in PF before the fix this number would go up to 30 easily and stay there.

5 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.