"Dual Render" Scope System

This is really good work but one small system using ~5.7% is not the best, have you tried using renderstepped or stepped, I find that heartbeat isnt always the best.
anyway looks amazing so far though good luck.

1 Like

Thanks.
Like I said, this isn’t something that can really be implemented into a game. It’s a cool tech demo, but doesn’t scale well.

1 Like

This looks amazing! Nice job!

2 Likes

This is amazing! Hopefully there’ll be a more reliable and smoother system for actual games at some point though. Good job on it anyways!

2 Likes

I was going to implement this idea but then realized ViewportFrames do not support smooth terrain :c

1 Like

I finally got around to making it scale on all devices. It now fills the scope properly, regardless of screen resolution.

Also tossed in a showcase section, because ViewportFrames are live now!

1 Like

I’m disappointed in myself. There were a lot of oversights in this.
Luckily, I fixed them!

Issue A: Scaling
My scaling assumed that the part wasn’t rotated, so it broke and distorted when tipped. I’ve redone it using proper A = bh by getting 3 corners and getting the magnitude without depth.

Function:

local function GetObjectScreenSize(Object)
	local cframe,size = Object.CFrame,Object.Size
	
	--Area is base times height
	local tR = WorldToScreenPoint(PlrCamera, cframe * v3(-size.x/2,  size.y/2, -size.z/2))
	local bR = WorldToScreenPoint(PlrCamera, cframe * v3(-size.x/2, -size.y/2, -size.z/2))
	local tL = WorldToScreenPoint(PlrCamera, cframe * v3( size.x/2,  size.y/2, -size.z/2))
	
	local base	= (v3(tR.X,tR.Y,0)-v3(tL.X,tL.Y,0)).magnitude
	local height	= (v3(tR.X,tR.Y,0)-v3(bR.X,bR.Y,0)).magnitude
	
	return UDim2.new(
		0,
		base,
		0,
		height
	)
end

Issue B: Rotation
When the ScreenPart tips, the GUI wouldn’t. This is also fixed in the patch step-by-step link.

Issue C: Mapping
Another mistake is that the GUI mapped to the center of the ScreenPart, rather than to the face. This has been solved and is updated in the patch step-by-step.

1 Like

I don’t know if you knew about this but: https://gyazo.com/6d7dba8fef864b245493f147779c72d5

1 Like

Thanks!

The issue there is that it renders from the tip of the scope, so if you clip through things, it renders past them. Obviously this would be an issue in a real game, but for this demo it’s not very important.

However, for sake of discussion, what possible solutions could we do?

The first one I think of is making the gun CanCollide, but that can cause issues with others things.
Another is that we could “holster/at ease” the gun when we get too close to an object.

What do you guys think?

Maybe you can ray cast from the scope to the player and if the scope isn’t on screen make it invisible? (I don’t really have much experience with ViewportFrames.

1 Like

That’s an interesting idea!

To clarify, you’d cast from the camera to the scope render point to make sure it isn’t clipping anything, and if it is, make the scope go black.

I just realized I mispoke… If the ray doesn’t hit the player than you can count the scope as invisible. There are obviously some flaws in this however.

Using this method of checking for clipping via raycasts, this issue is mostly avoided!

Whenever the tip of the Scope gets clipped, it goes dark!

DevForum kept erroring when I tried uploading in 1080p60 so enjoy this gross built in recorder version

--Altered code for this change

--Only update camera CFrame when scope CameraPart moves
GetPropertyChangedSignal(CameraPart, "CFrame"):Connect(function()
	Camera.CFrame			= CameraPart.CFrame 
	local vector = WorldToScreenPoint(PlrCamera, ScreenPart.CFrame*v3(0,0,-ScreenPart.Size.Z/2))
	if vector.X ~= RenderFrame.Position.X.Offset then
		RenderFrame.Position	= udim2(0,vector.X,0,vector.Y)
		RenderFrame.Size		= GetObjectScreenSize(ScreenPart)
		RenderFrame.Rotation	= ScreenPart.Orientation.Z
	end
	--Check for clipping
	local ray = Ray.new(
		PlrCamera.CFrame.Position,
		((CameraPart.CFrame.Position+(CameraPart.CFrame.LookVector*5)) - PlrCamera.CFrame.Position).unit * (PlrCamera.CFrame.Position - CameraPart.Position).magnitude
	)
	local hit = workspace:FindPartOnRayWithIgnoreList(ray, {Character,GunModel.Parent.Parent})
	if hit then
		ViewPort.Visible = false
	else
		ViewPort.Visible = true
	end
end)
2 Likes

Great fix! This actually wasn’t what I was pointing out. I was showing that even though the scope isn’t visible when you clip the gun through walls the ViewportFrame is.

Ohhh

Well, we can apply this same method the the ScreenPart instead of the CameraPart!

If the ScreenPart isn’t visible, then make the entire scope GUI not visible!

Ahhhh, never make the gun CanCollide. You will fling 99.999999% of the time.

Yup! That’s why I didn’t go with that!

Decided to update my example place with some nicer touches.

  • Scope fades out when unaimed (also made it only update when not faded, so it doesn’t eat CPU when unaimed)
  • Blur effect fades rather than appears
  • Added dirty glass texture over the scope
  • Added lighting effects for fun
External Media
3 Likes

Would you have a download for those updated touches?

Some are specific to my FPS system, so no.

To do the performance saving when unaimed, it’s a simple if statement.

PartUpdater = Heartbeat:Connect(function()
	if ViewPort.Visible and ViewPort.ImageTransparency~=1 then