After careful consideration I figured this should be in #help-and-feedback:cool-creations and not #resources:community-resources as it’s not really a substantial resource, but rather one used for learning. Unfortunately, that means less people will probably see this, so if you see anyone asking about a static camera feed system on a surface gui don’t hesitate to point them here even though it’s not in #resources:community-resources.
This is a very simple live camera feed system, it’s more for teaching users how to make their own camera systems, but functions all the same. It doesn’t have a lot of configurability. My hope is that this shows one of the many ways to do this to developers so they can make their own systems (swipe/click to get a new camera feed anyone? This doesn’t support that, but it would be easy to make after analyzing this code). Every now and then I try to come on the devforum and help people. Recently, someone was asking about security cameras and live camera feeds. They said that there weren’t any just configure and go type of resources for a live feed camera that is on a screen. I decided, since I’ve done this before, that I can go ahead and tackle this.
I made this because some people may not understand how to use the ViewportFrame Handler module for this use case, so I wanted to make something simple. But I want to ensure you know, ViewportFrame Handler is made by boatbomber and sufficient credit for this should go to them for their amazing module.
Method
This is a very simple system. It uses the amazing module ViewportFrame Handler (ViewportFrame Handler). However, this version was modified to fix a memory leak regarding event connections (this means don't download your own version of ViewportFrame handler and expect it to work). I notified the developer of this and gave them my modified code, so in future versions, this may be not necessary.Using the module, it’s easy make a viewport update parts and humanoids. For optimization purposes, it only renders what it can actually see, using config values for fov and camera range. However, it does render parts that are behind walls (raycasting every update to see if it can really see the part is worse for performance than just letting it sit there).
Resources
I've provided a editable place with 3 examples you can access it here. It has examples for a camera feed on a screen, a tablet tool, and a screen gui.I’ve also provided the scripts in a model which you can get here.
Unless you’re making your own system, the only thing you should really edit is the config module script. The hierarchy looks like this:
It’s really important that any camera feed you make with this resource has this hierarchy. You should have the LocalScript in a SurfaceGui that has a ViewportFrame in it.
Config
A basic config looks like this:local Players = game:GetService("Players")
local Player = Players.LocalPlayer
-- The above is for example for tools, it is not required.
local config = {
CameraEye = workspace.Camera1.Eye, -- The part the camera looks through, looks in the front face of the part
FOV = 70, -- How wide the field of vision should be
CameraRange = 100, -- The max distance to render parts
FPS = 60, -- How many updates objects being rendered should undergo per second
UpdateFrequency = 20, -- How many times to update rendered objects per second (removing/adding objects to the ViewportFrame)
RenderCameraModel = false, -- Whether or not the model containing CameraEye should be rendered
PlayerVisionRange = 100, -- How far away the player can see the screen (outside of this range, everything unrenders)
AdornOnEnable=false, -- Whether or not to adorn the surfacegui on enable (useful for tools)
Adornee=nil, -- The adornee if AdornOnEnable is true
AttachToFace=Enum.NormalId.Top -- Which face to attach to
}
return config
There’s not a lot to it. If you want to attach it to a tool, I suggest you open up the example place and go into the config in the tool SurfaceGui. Essentially, you’re just adding a specific part and face to adorn to. Because tools are typically cloned into the player, it’s important to access it from their backpack and not just set the adornee in the surfacegui.
You can have a part not update if you want. This is done using attributes. The attribute we use is called CameraNoUpdate
:
This will not update or refresh on parts already in the frame, so if you want a part to not update that you’re creating from a script, make sure to add the attributes before parenting it to the workspace.
Caveats
- This will not render camera screens inside of camera screens. This is why the tablet is blank in the camera feed.
- This is not meant to be complicated. It's not supposed to have many options. Though it will work just fine if you just want a static screen.
- This will not work well on very large games with many parts. The more parts, the more lag. This script recurses every model in the workspace to see if it needs to render. I'm trying to figure out a way to do this without iterating every part, but I haven't come up with a way yet.
- Performance will dramatically increase if you use the CameraNoUpdate attribute on anchored parts that will never move. We still update regular anchored parts because it's possible they could be projectiles. Weapon scripts actively use anchored parts for their bullets, so not updating them could cause conflicts and odd behavior, so instead we opted for the attribute.
- This is not fully optimized. I didn't go over a ton of things. I did a few optimizations, but not many.
GIFs
On a screen:
On a tool/tablet:
These gifs are lower resolution and lower fps than it actually is in game, make sure to check out the actual place for a good demonstration.
Remarks
As I said earlier this is more a resource for learning, while it does function on its own, I made this for people to reverse engineer. That's why I made a place for people to edit. If you want extra features like clicking an arrow to switch feeds, this is something you'll have to implement on your own using knowledge you already knew or gained by looking at how the scripts work. This script in particular is not modular. It could be modular to allow switching camera feeds and would ultimately work better if made into a class based system, but I can't stress this enough: this is a basic resource you can build off of/extract methods from and make your own system. There's not a lot of complicated logic, but not everyone is experienced with it, or maybe they didn't even know the ViewportFrame Handler existed which streamlines the entire process.If it has enough interest, I may make a modular system for this (something you could just require
in a localscript and create new handlers or specific surface guis), so let me know if that’s something you’d be interested in, but it would take longer because I’m doing a lot of stuff right now.