Feedback on a new viewmodel idea

This is explaining how I got to my current position, if you just want to see what im doing skip to the next bold text

So im assuming most programmers here already know how most ROBLOX games with first person fire-arms do the viewmodels

We add a gun model (with arms and etc) under the players main camera like so, and then constantly set its CFrame value to be positioned corrected
2022-07-04 16_28_06-Viewport Render Test - Roblox Studio

I was looking at other ways to do this to avoid some issues including:

  • Large optics if they have zoom features taking up a majority or too much of the screen
  • Models clipping into other objects

Now another way of solving the 2nd bullet point would be detecting when the player is close to an object and making an animation that pulls the weapon up and away, not foolproof, but it works well.
And then I decided that I didnt want to do that

Many mainstream games such as Call Of Duty, Rainbow 6 Seige, and etc; use a way of rendering them on a seperate camera plane (terms might not be right but youll under stand in a second)

I started researching ways to do this in ROBLOX and very quickly came up with ViewportFrame’s, these render objects inside of them.

So I added arms and a gun to it, and ran into the first issue: You cannot load animations in viewport frames. A little bit of digging later, add a WorldModel into the viewport frame, add your part inside of that, and it plays!

Next issue: During animations, aiming, and just playing, I couldnt really get the weapon to be positioned correctly to where I wanted it to be. So I messed around with Camera’s and CFrame and added a camera to the WorldModel and made the ViewportFrames CurrentCamera value equal to said camera.

Then I can use CFrame to position the rootpart of the model and there we have, a gun!

Then I went back to one of the first things I wanted to figure out in this project, can I make the optics of weapons not take up a large portion of the screen during zoom aiming, and the answer is yes.
Using a way many other games do, in the sperate world/camera that the gun is being rendered in, I can change the MainCamera’s FieldOfView and it will only effect the viewmodel (and anything else I put inside the ViewportFrame’s WorldModel)

When the player is aiming, lower the characters main FieldOfView (the one normally used in the workspace) then raise the viewmodels worlds FIeldOfView. This works very well. (along with positioning the camera CFrame to look down the iron sights but you get the point).

Next bold text for people that just want to see it

A demonstration of the original issues that I set out to fix can be show in most ROBLOX FPS games, for this example, I will be using Apocalypse Rising 2 by Dualpoint Interactive
Before I show this video please remember, this is not trying to hate on Apoc 2 or the development team, im just using it as an example, I beleive these are great developers, and their game just went free I highly suggest you check it out!

link

My version:
Aiming here does not show the large optic issue, it fixes that however I forgot to readd it to the test before taking the video!
link

Please excuse any grammatical errors!

Quick how-to on this:
2022-07-04 16_45_08-Viewport Render Test - Roblox Studio

Arms has a gun model, which is rigged to a model with arms and a rootpart

This rootpart’s CFrame is the CFrame you edit in the code for positioning and such
IMPORTANT: You have to make a new camera under viewportWorld in the code because upon runtime the studio made camera gets destroyed, and you will have to set viewportFrame’s CurrentCamera to that camera
I just make the studio camera so I can see how everything looks on an easier basis

My arms setup code:

function setupArms()
	
	frame.Visible = true
--[[
makes the weapon visible 
*Assuming you already have the weapon model in the frame, 
which I do in studio but you will have to do through code
if you want weapon selection!
]]
	


	if frameWorld:FindFirstChild("MainCamera") then
		cam = frameWorld:FindFirstChild("MainCamera")
	else --  generates the new camera
		cam = Instance.new("Camera", frameWorld)
		cam.Name = "MainCamera"
		frame.CurrentCamera = cam
	end
	
	task.wait() -- quick wait to make sure everything is good
-- unsure if that wait is actually needed but it makes me feel good :)
	
	local arms = frameWorld:WaitForChild("Arms")
	local hum = arms:WaitForChild("Humanoid")
	
	loaded = true -- I use this in other parts of the code for checking if we can shoot and etc
	
	arms.PrimaryPart.CFrame = cam.CFrame * CFrame.new(-.7, -1.3, .1) -- set it to the base CFrame
-- *You will probably have to make your own CFrame value and not use mine!

	local idle = hum:LoadAnimation(animsFolder:WaitForChild("Idle")) -- load the idle animation and such!
	idle:Play()
end

Please let me know of any errors here, and let me here any ideas for expansion and additions!

Edit 1: accidentaly uploaded 2 of the same video

3 Likes

Okay I feel like everyone has tried this at some point, the main problem is that lighting is needed for a good immersion experience.

1 Like

I have made my own engine to do this exact thing after reading this. One thing I have realised is that everything looks like a still image so that is a downside.

another way to stop collision with walls, which i used in my own system, is to just move the viewmodel back when you get the front of the gun too close to a wall.

EX:
without movement, far from a wall:

close to a wall:

2 Likes