ViewportFrame Handler - Custom updating objects & humanoids in VPFs

Made a cool flashbang effect using this.

Does the whole “burns the image to your eyes” thing.

Creates all the object handlers with an FPS of 0, and then calls the ViewportHandler:Refresh() when it wants to burn the image.

44 Likes

Update!

Added the Object APIs into the Handler APIs, allowing you to handle all objects at once without having to store all your Obj_Handlers and loop through each one to call their function.

Could you possibly open-source this? :o

1 Like

Using this module for it is overkill and actually wastes CPU.

I’ll make a Screenshot module or something that’s specifically designed for this, and open source that.
I’ll fix this module to work better in these cases.

1 Like

Made a pretty awesome change to the module.

Although still perhaps overkill, it no longer wastes CPU.


The issue:

The reason it was wasting CPU was very simple.

Every frame we iterate over every part and check if it needs to be updated. There are no parts that were active (aka everything was 0 FPS and being refreshed manually when burning the image), so we always iterated through them all and did nothing but update some numbers in them.


This was my initial change in an attempt to solve the issue. I've removed this, for reasons discussed in the end of this dropdown.

I made a simple(ish) change.

function ViewportHandler:_ValidateRefresher()

Anytime you make a change to the handler or an object within the handler, this gets called.

This function goes through all the objects. If there’s an active object, we make sure we have our binding to renderstep. If there are no active objects (such as our flashbang case), we remove that binding.

This way, when no objects are active, there’s no iteration happening.


Why I removed this:

There’s still a downside: if you have even one object active, it iterates through all the inactive ones too.
My final solution fixed this, and also reduces the cost of the module since it doesn’t need to call :_ValidateRefresher() all the time.

The solution:

Instead of iterating over every part, we only iterate over the active ones!

We now have 2 dictionaries: AllObjects and ObjectsRenderQueue.
When an object is inactive, it’s removed from the render queue, and added back in when made active again.

Our render logic only iterates through the render queue, which is empty in the flashbang case.

This also makes our render logic faster in it of itself, since it no longer has to check if the object is active. If it’s in that queue, we know it is!


This is a huge performance gain.

The previous version would be impacted by static objects. In our flashbang example, everything was static. But it matters in other uses too! If you have a large static map, you’d have rendered them at 0 FPS too! Now that won’t crush your performance!

2 Likes

Small change.

No longer uses BindToRenderStep. Connects to .Heartbeat instead.

Doesn’t affect much, but it allows it to run in parallel to the frame drawing so it shouldn’t drastically affect your game’s FPS.

2 Likes

Is that cheaper to run on the server?

ViewportFrames and frame rendering are client processes.

4 Likes

Is there a way you could provide a coding example of how the flashbang or “burn” effect was made? I tried doing it myself, but I can’t seem to wrap my head around it :^(

1 Like

So from this brief explanation, I’m copying the entire world? Ok

You should only really copy what you need to. You can see the Security Camera example, or open a linked topic if you require more help.

1 Like

What if I would make live interactive concerts with those cameras :thinking::thinking::thinking::thinking:

2 Likes

Sorry to bother you kind sir but I have a couple questions:

  1. Heartbeat vs Stepped or .Changed
  2. if RunService then would it be best to have 1 Heartbeat or Stepped connection managing all the new viewports or 1 per viewport

You’re making history my guy, keep up the great effort! I wouldn’t look for guidance for Viewport Frame’s from anyone else other than you.

3 Likes

Hey boatbomber, I was wondering why my humanoid animations (AnimationTrack) wouldn’t play in ViewportFrames. Does this module allow me to animate Humanoid objects with them? I’m curious to see what the Humanoid handlers do.

If it does, then I’d be really glad, since I’m still looking for solutions to this (very) annoying problem. All of your open-source projects are awesome and I’m looking forward to an answer.

1 Like

ViewportFrames don’t natively support animations or physics.

This module does work with animations, just not in the way you might think.

When you tell the module to render a humanoid, it’ll make sure the VPF’s humanoid matches the pose of the workspace humanoid. If you animate the workspace humanoid, it’ll show up properly in the VPF as the handler will manually set the CFrames.

2 Likes

So trying to utilize ViewportFrames + the module for an FPS viewmodel doesn’t work? I’ve tried using object handlers but I don’t really think I’m doing it correctly.

I’ll try locally storing a copy of the viewmodel in Workspace at 0, 0, 0, then render the object to the viewport. Hopefully it works.

Edit 2: It works! It works! Thanks for clarifying @boatbomber, your modules are absolutely helpful!

4 Likes

Shouldn’t this be something that reflection property should do?

Shouldn’t this be something that reflection property should do?

The Reflectance property just defines how much a part reflects the skybox cubemap. Even if it had raytraced reflections, that’s still not what the module does.

This module has nothing to do with reflections. This is a module to help you handle your VPFs. Although you could try to use it for makeshift reflections, that is not what this is. You can see various uses throughout the thread, and not a single one is a reflection. It can be used for cameras, fps viewmodels, shop items, flashbangs, scopes, and more.

What part of this thread made you think it was a reflection module? Let me know so I can rephrase and clear it up for future readers.

1 Like