Help with Camera Manipulation

I get somewhat how to achieve this idea but I want to make it efficient and based on player range.

The design is pretty simple, whenever the player is in “range”, it will change the camera to a certain part, say A, B, C, or whatever. I know how to achieve this but not when the player is in range. I would use a part touch but that is inefficient and buggy.

Also, the camera would in ways follow the player’s position on a straight axis.

so say Z axis, the camera would be confined to the “A” part’s Z axis, then when in range of say “B” part it will change to that part’s axis.

I’ve seen the design of this and I have experimented with other codes but they don’t work in the way I want them to or I just don’t understand them, therefore, it makes it harder for me to implement and change it when I need to.

I have an image of what I want to achieve somewhat (Not my image credit to Nullxiety)
image
this kind of but only 1 limit and when in range it will change to another part.

2 Likes

Look into using Region3 for this. A page on it can be found here.

2 Likes

I was trying some of the sample code/functions in the article though I don’t really understand how to use it.

local partA = workspace:WaitForChild("A")
local partB = workspace:WaitForChild("B")
local min = partA.Position - (0.5 * partA.Size)
local max = partA.Position + (0.5 * partA.Size)
local min1 = partB.Position - (0.5 * partB.Size)
local max1 = partB.Position + (0.5 * partB.Size)
local region = Region3.new(min, max)
local region1 = Region3.new(min1, max1)
local isPartEmpty = workspace:IsRegion3Empty(region, partA) --  ignore part
local isPartEmpty1 = workspace:IsRegion3Empty(region1, partB) --  ignore part

local player = game.Players.LocalPlayer
local Character = player.Character or player.CharacterAdded:Wait ()
local Camera = workspace.CurrentCamera
if isPartEmpty == true then
	print("in rangeA")
	repeat wait ()
		Camera.CameraType = Enum.CameraType.Scriptable
	until Camera.CameraType == Enum.CameraType.Scriptable
	Camera.CameraSubject = partA
	Camera.CFrame = partA.CFrame
end

if isPartEmpty1 == true then
	print("in rangeB")
	repeat wait ()
		Camera.CameraType = Enum.CameraType.Scriptable
	until Camera.CameraType == Enum.CameraType.Scriptable
	Camera.CameraSubject = partB
	Camera.CFrame = partB.CFrame
end

I am only getting rangeA and I still haven’t added the camera axis movement.

1 Like

Hmmm, you could try using :GetPartsBoundInBox every time the player’s HRP CFrame changes to see if they are in the region, instead of this method.

2 Likes

Whats that? I have no idea how to it.

1 Like

A page on :GetPartBoundsInBox can be found here.

2 Likes

Also any idea how I can make the camera move in relation to the players head movement. (i showed a sample image in the post)
i have some samples to work with but it only works on a A-B instead of being able to do
A-B, B-A, B-C, C-B, etc.

1 Like

Here’s the problem illustrated in 2D:

image

You want to find the point C (“camera”) which is the point along the line segment AB that is closest to H (“head”).

C is “somewhere along AB”, which means C can be expressed as C = A + vAB * t where vAB is the vector from A to B, i.e. vAB = B - A.

The only thing that’s left is to compute t, which is a number indicating how far along AB the point C is, where 0 means it’s at A, 1 means it’s at B, and somewhere between means “that far between” (e.g. 0.5 is halfway).

There’s a thing in vector maths called “vector projection” which you can google if you’re interested. In this case it’s relevant because C is exactly the projection of vAH onto vAB. I’ll use some knowledge of that to figure out t: t = vAH.Unit:Dot(vAB.Unit).

Here’s what a function for doing this looks like:

function projectPointOntoLine(point: Vector3, linePointA: Vector3, linePointB: Vector3)
    local vAP = point - linePointA
    local vAB = linePointB - linePointA
    local t = vAB.Unit:Dot(vAP.Unit)
    return linePointA + vAB * t 
end

This works, but doesn’t constrain C to be between A and B:

image

Since t is between 0 and 1 when C is between A and B, we can create another function that does the same except clamping t to the valid range:

function projectPointOntoSegment(point: Vector3, segmentPointA: Vector3, segmentPointB: Vector3)
    local vAP = point - segmentPointA
    local vAB = segmentPointB - segmentPointA
    local t = math.clamp(vAB.Unit:Dot(vAP.Unit), 0, 1)
    return segmentPointA + vAB * t 
end

This should work but I can’t test it right now, let me know if it’s weird because I might have made a mistake :sweat_smile:

2 Likes