Target of camera when CameraSubject is set to humanoid

Hi!

I want to know where to aim my Workspace.CurrentCamera so that it doesn’t slightly jump when I set it back to custom.

The reason it jumps, is because it aims at the CameraSubject, which is by default the character’s humanoid. It looks nice, I tried setting another CameraSubject but it doesn’t look good.

Before this, I shortly set the camera to Scriptable, and then I try to put it in the position that it will stay in after setting it back to custom. But, what is the position of the humanoid? It doesn’t seem to be any of the body parts… If I would know that position, I could come up with a valid CFrame for the camera so that it would not jump to a new orientation when I set it back to custom mode.

I may be missing something obvious here, does anyone have any idea on how to solve this? Thanks!

1 Like

Ok I figured out the answer, so I’ll answer my own question.

After you press play, you can find under PlayerScripts/PlayerModule/CameraModule/BaseCamera the following piece of code:

if cameraSubject:IsA("Humanoid") then
		local humanoid = cameraSubject
		local humanoidIsDead = humanoid:GetState() == Enum.HumanoidStateType.Dead

		if VRService.VREnabled and humanoidIsDead and humanoid == self.lastSubject then
			result = self.lastSubjectCFrame
		else
			local bodyPartToFollow = humanoid.RootPart

			-- If the humanoid is dead, prefer their head part as a follow target, if it exists
			if humanoidIsDead then
				if humanoid.Parent and humanoid.Parent:IsA("Model") then
					bodyPartToFollow = humanoid.Parent:FindFirstChild("Head") or bodyPartToFollow
				end
			end

			if bodyPartToFollow and bodyPartToFollow:IsA("BasePart") then
				local heightOffset
				if humanoid.RigType == Enum.HumanoidRigType.R15 then
					if humanoid.AutomaticScalingEnabled then
						heightOffset = R15_HEAD_OFFSET

						local rootPart = humanoid.RootPart
						if bodyPartToFollow == rootPart then
							local rootPartSizeOffset = (rootPart.Size.Y - HUMANOID_ROOT_PART_SIZE.Y)/2
							heightOffset = heightOffset + Vector3.new(0, rootPartSizeOffset, 0)
						end
					else
						heightOffset = R15_HEAD_OFFSET_NO_SCALING
					end
				else
					heightOffset = HEAD_OFFSET
				end

				if humanoidIsDead then
					heightOffset = ZERO_VECTOR3
				end

				result = bodyPartToFollow.CFrame*CFrame.new(heightOffset + humanoid.CameraOffset)
			end
		end

The relevant bit comes down to:

heightOffset = R15_HEAD_OFFSET
local rootPart = humanoid.RootPart
if bodyPartToFollow == rootPart then
	local rootPartSizeOffset = (rootPart.Size.Y - HUMANOID_ROOT_PART_SIZE.Y)/2
	heightOffset = heightOffset + Vector3.new(0, rootPartSizeOffset, 0)
end

The part to follow (when the CameraSubject is humanoid) is the rootpart, but then an offset is applied. In my case, with R15 characters and automatic scaling and such, the above calculation gives the heightOffset. The final CFrame is then made of the rootpart’s CFrame + heightOffset (plus humanoid.CameraOffset, but it’s default 0.0.0).

These constants are hardcoded at the start of the script:
local R15_HEAD_OFFSET = Vector3.new(0, 1.5, 0)
local HUMANOID_ROOT_PART_SIZE = Vector3.new(2, 2, 1)

So in the end, I got:
local heightOffset = Vector3.new(0, rootPart.Size.Y/2 +.5, 0)
local targetPos = rootPart.CFrame.p + heightOffset

And it seems to work fine, at least for my character! See it in action here:
https://www.roblox.com/games/6691045926/

Please let me know of anything that might go wrong, or if anything didn’t work!

10 Likes