[Solved] How to make camera position and orientation fixed

I’ve decided to make a game (after months of deleting projects that I couldn’t complete) with a camera system similar to the game Hades

The position and orientation are fixed and have a slight camera latency while following the player.

how would I make a camera that has the same or similar position where it moves with the player but Keeps orientation?

I read @Mad_Scientist99’s post How to make Camera position move with character, but has a fixed orientation but that isn’t what I’m looking for.

For comparison this is what I’m looking for:

And this is what i got:

For the latency/smoothness, I’m using AGF Smooth Module but if there is anything else I can use please let me know thanks in advance.

6 Likes

You’ll probably want to program your own camera controller. To do this, you can set the camera’s type to scriptable, then update the camera every RunService.RenderStepped. Example:

local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local Workspace = game:GetService("Workspace")

local player = Players.LocalPlayer
local camera = Workspace.CurrentCamera

camera.CameraType = Enum.CameraType.Scriptable

RunService.RenderStepped:Connect(function()
    if player.Character and player.Character:FindFirstChild("HumanoidRootPart") then
        -- Update the camera's CFrame here.
    end
end)

To make the camera slide to the position you’d like, you can create a target CFrame or position, then have the camera move towards the target CFrame (or position) over time, and update the target CFrame (or position) based on the character’s position. Here is a super simple way of doing this:

local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local Workspace = game:GetService("Workspace")

local player = Players.LocalPlayer
local camera = Workspace.CurrentCamera

camera.CameraType = Enum.CameraType.Scriptable
camera:GetPropertyChangedSignal("CameraType"):Connect(function()
	camera.CameraType = Enum.CameraType.Scriptable
end)

local offset = Vector3.new(10, 10, 10)
local rate = 0.05

RunService.RenderStepped:Connect(function()
	local character = player.Character
	if not character then
		return
	end
	local humanoidRootPart = player.Character:FindFirstChild("HumanoidRootPart")
	if not humanoidRootPart then
		return
	end


	local targetPosition = humanoidRootPart.Position + offset
	local currentPosition = camera.CFrame.Position

	local nextPosition = currentPosition:Lerp(targetPosition, rate)

	camera.CFrame = CFrame.lookAt(nextPosition, nextPosition - offset)
end)
2 Likes

I’d just use tweening instead of lerping.

3 Likes

Lerping is actually better here because hes already moving the camera every frame with the “RenderStepped”

1 Like

What I mean is that you don’t need RenderStepped. Tweening can be smoother and more adjustable.

2 Likes

Oh I see, but I dont think tweens update the goal position so it should be better to just update it every frame.

It does update the goal position.

1 Like

So which one do I choose lerping or tweening?

Id try both and see what works best for you.

1 Like

I would personally use tweening. Just get the CFrame of the HumanoidRootPart, adjust the orientation (using CFrame of course), and then offset the CFrame by however far away you want the camera to be. Then use tweening to update that position in a loop. You can adjust the speed of the tween and whatever else you want.

1 Like

I forgot to mention it earlier but how would I add “layered” health bar for example when the npc’s health reaches 53 it changes from gold to red?

Well theres a couple things you could do.

If you just want 53 to instantly turn red then ( on update ) change the color of the frame or image-color

Id probably do a percent calculator and do:

Color3.new( " YELLOW " ):Lerp(Color3.new( " RED " ),Percent)
-- Red I would use:
Color3.new(1, 0.19, 0.2)
-- Yellow I would use:
Color3.new(1, 0.86, 0.18)
1 Like

Tweening is either as smooth or less smooth. It doesn’t get smoother than updating every frame. While tweening is easier to adjust, it’s less adjustable than just writing in the math.

To use tweening for this, a new tween would need to be created extremely often (since the goal of a tween can’t be changed) to avoid sudden changes direction of the camera movement. This removes a lot of the advantages of tweens and makes them fairly inefficient.

You should use lerping. A tween uses lerping too, but the goal can’t be changed without creating a new tween, so just programming something that functions similarly to a tween is a good idea.

1 Like

Creating tweens often isn’t going to be an issue. Also this does not remove advantages if you adjust accordingly. You can do a lot more with a lot less math. It’s also probably more efficient being built-in. I personally use tweening for any sort of transitional operation, but as long as it does what you want it to do without causing issues, it’s up to the individual.

It might be more efficient in cases where you only need a single tween, but when you need to create a new tween 30-60 times a second, it’s very certainly less efficient (tweens are instances, creating a new instance alone is probably makes it less efficient).

The thing with tweens though is that because the goal is updated so often things like easing style and easing direction are basically ignored since only the first ~17-33 milliseconds of the tween are played.

I guess so. If efficiency isn’t a huge deal (and it usually isn’t) it doesn’t really matter. @OP if you want to use tweens, use the same code as above but instead of using the lerp function:

  • If there is a tween stored destroy it*
  • Create a new tween
  • Store the new tween*
  • Play the new tween

* Automatically garbage collected, as MightyDantheman pointed out.

I’m a bit confused with this part as it’s not actually an Instance. A tween is just a class object, which only references. It works in the same way a variable would and is automatically garbage collected the same way. You don’t need to ‘destroy’ or ‘store’ a tween. You can simply create and play it immediately without any extra steps.

This is partly true, but it still plays a noticeable role. It depends on how often you update the tween and how quickly you have the tweet set to reach a given goal. You can tweak those variables until you reach the desired outcome.

The goal changes every frame though. If you don’t have the target change approximately every frame the camera will suddenly change the direction it’s traveling.

Tweens are an instance. You are correct though, they don’t need to be destroyed since instances without a parent are garbage collected once they don’t have a reference. I’ll fix that.

(Source)

1 Like

Again, with the right tweaking, you can make it do what you want (from experience). I suppose lerping does get straight to the point if all you want is perfectly linear transitions. I still prefer to use tweening due to the simplicity.

I stand corrected then. I was thrown off by “Instance.new cannot be used for this particular object.” Did some testing and it was quite strange being able to parent a tween object with no icon. The more you know.

1 Like

Here’s my version as an example:

local speed = .1

local T = game:GetService('TweenService')
function tween(o,t,l,s,d)
	s = s or Enum.EasingStyle.Linear
	d = d or Enum.EasingDirection.InOut
	local i = TweenInfo.new(l,s,d)
	return T:Create(o,i,t)
end

local players = game:GetService('Players')
local player = players.LocalPlayer
player.CharacterAdded:Connect(function(character)
	local root = character:WaitForChild('HumanoidRootPart')
	local dead
	local died
	died = character:WaitForChild('Humanoid').Died:Connect(function()
		died:Disconnect()
		dead = true
	end)
	local camera = workspace.CurrentCamera
	camera.CameraType = Enum.CameraType.Scriptable
	repeat
		task.wait()
		local cf = CFrame.new(root.Position) * CFrame.Angles(math.rad(-45),math.rad(22.5),math.rad(22.5)) * CFrame.new(0,0,20)
		tween(camera,{CFrame=cf},speed):Play()
	until dead
end)

You can adjust the speed at the top or add your own easing styles with the tween function.
Both the speed and easing style will modify how the tween works.

Although in the case of Hades, it seems to be a bit more than just following the player? I’m having a hard time pin-pointing how.

5 Likes