Avatar Editor Camera - How to move camera off to the side?

There’s a topic similar to this but with no solution. Help with the camera

How do roleplay games achieve this type of camera, where the camera shifts to the left (or right), while still allowing the player to rotate around their character?

I’ve tried to simply set the Humanoid.CameraOffset but it results in the camera pivoting around the new camera offset rather than the player, I’m just looking for the shifting of the camera left, while still pivoting around the character

Would be grateful is anyone had any ideas :pray:, is this done by humanoid camera offset, or something with the camera subject or camera state??

2 Likes

try using Humanoid.CameraOffset and Camera.CFrame, so it’d look smth like this:

local cameraOffset = Vector3.new(5, 0, 0)
local cameraPosition = HumanoidRootPart.Position
local newCFrame = CFrame.new(cameraPosition, cameraPosition + character.HumanoidRootPart.CFrame.LookVector)
camera.CFrame = newCFrame:ToWorldSpace(CFrame.new(cameraOffset))
1 Like

All that does it set the position of camera to point at the humanoid root part, then I move it and it goes back to normal

I’ve achieved this with some help from somebody

local screenSpace = require(script.ScreenSpace)
local camDepth = 9
local camRotation = -28
local camX = 0.463
local camY = 0.430

function CameraOnOpen()
	runS:BindToRenderStep('AvatarEditorCam', Enum.RenderPriority.Camera.Value, function()
		local viewSizeX = screenSpace.ViewSizeX()
		local viewSizeY = screenSpace.ViewSizeY()
		
		local offset = screenSpace.ScreenToWorld(camX * viewSizeX, camY * viewSizeY, -camDepth)
		local camCf = hrp.CFrame * offset
		local lookCf = hrp.CFrame * Vector3.new(offset.X, offset.Y, camDepth)
		camera.CFrame = CFrame.new(camCf, lookCf) * CFrame.Angles(0, math.rad(camRotation), 0)
	end)
end

(In this image the UI start on the right border of the image)

However, this is inconsistent on different size screens, and the players camera is still fixed, so I’m looking for a way to make the player able to pivot around their camera such as the video in the original post.

The screen space module is as attached btw
ScreenSpace.lua (6.7 KB)

Currently, this is the best I’ve got. However it’s really buggy, the camera always seems to be colliding with something and this weird black circle appears in the sky when I look up. Anyone know what’s going on here, or how I could achieve this a different way?

Here’s a module I found from here

-- black frames not included

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

local Camera = Workspace.CurrentCamera

local Module = {}

Module.Position = UDim2.new(0, 0, 0, 0)
Module.Size = UDim2.new(1, 0, 1, 0)

local function UDim2Absolute(udim2)
	local viewSize = Camera.ViewportSize

	return Vector2.new(
		(udim2.X.Scale * viewSize.X) + udim2.X.Offset,
		(udim2.Y.Scale * viewSize.Y) + udim2.Y.Offset
	)
end

--- Compute offset

function Module._computePosition()
	local viewSize = Camera.ViewportSize
	local aspectRatio = viewSize.X / viewSize.Y

	local offset = UDim2Absolute(Module.Position)
	local position = offset / viewSize

	-- Taken from ScreenSpace
	local hFactor = math.tan(math.rad(Camera.FieldOfView) / 2)
	local wFactor = hFactor * aspectRatio

	return -position.X * wFactor * 2, position.Y * hFactor * 2
end

function Module._computeSize()
	local size = UDim2Absolute(Module.Size) / Camera.ViewportSize
	return size.X, size.Y
end

function Module._getOffset()
	local x, y = Module._computePosition()
	local w, h = Module._computeSize()

	return CFrame.new(
		0, 0, 0,

		w, 0, 0,
		0, h, 0,
		x, y, 1
	)
end

--- Handler

function Module.Start()
	RunService:BindToRenderStep("ViewportCamera", Enum.RenderPriority.Camera.Value + 1, function()
		Camera.CFrame = Camera.CFrame * Module._getOffset()
	end)
end

function Module.Stop()
	RunService:UnbindFromRenderStep("ViewportCamera")
end

return Module

Managed to solve this thanks to this person:

You need to parent the sun rays to nil while using the camera like this otherwise those black circles appear. A bit of a workaround but I’m fine with it.

Clamping the X value seemed to do most of the trick though! x = math.clamp(x, -0.663, 0.663)

Heres the full modified version of that module
local RunService = game:GetService("RunService")
local Workspace = game:GetService("Workspace")

local Camera = Workspace.CurrentCamera

local Module = {}

Module.Position = UDim2.new(0, 0, 0, 0)
Module.Size = UDim2.new(1, 0, 1, 0)

local function UDim2Absolute(udim2)
	local viewSize = Camera.ViewportSize

	return Vector2.new(
		(udim2.X.Scale * viewSize.X) + udim2.X.Offset,
		(udim2.Y.Scale * viewSize.Y) + udim2.Y.Offset
	)
end

--- Compute offset

function Module._computePosition()
	local viewSize = Camera.ViewportSize
	local aspectRatio = viewSize.X / viewSize.Y

	local offset = UDim2Absolute(Module.Position)
	local position = offset / viewSize

	-- Taken from ScreenSpace
	local hFactor = math.tan(math.rad(Camera.FieldOfView) / 2)
	local wFactor = hFactor * aspectRatio

	return -position.X * wFactor * 2, position.Y * hFactor * 2
end

function Module._computeSize()
	local size = UDim2Absolute(Module.Size) / Camera.ViewportSize
	return size.X, size.Y
end

function Module._getOffset()
	local x, y = Module._computePosition()
	local w, h = Module._computeSize()
	x = math.clamp(x, -0.663, 0.663) -- this line was vital

	return CFrame.new(
		0, 0, 0,

		w, 0, 0,
		0, h, 0,
		x, y, 1
	)
end

--- Handler
local lighting = game:GetService("Lighting")
local sunRay = nil
local beforeFovMode = Camera.FieldOfViewMode -- keep track of whatever our existing fov mode is

function Module.Start()
	Module.Position = UDim2.new(-0.25, 0, 0, 0)
	Module.Size = UDim2.new(1, 0, 1, 0)
	
	local ray= lighting:FindFirstChildWhichIsA("SunRaysEffect")
	if ray then
                sunRay = ray
		ray.Parent = nil
	end

	Camera.FieldOfViewMode = Enum.FieldOfViewMode.MaxAxis
	
	RunService:BindToRenderStep("ViewportCamera", Enum.RenderPriority.Camera.Value + 1, function()
		Camera.CFrame = Camera.CFrame * Module._getOffset()
	end)
end

function Module.Stop()
	RunService:UnbindFromRenderStep("ViewportCamera")
	Camera.FieldOfViewMode = beforeFovMode
	
	if sunRay then
		sunRay .Parent = lighting
	end
end

return Module