Moving part relative to the camera's direction

So I’m making a custom camera setup where it admits a part as the center point, moving and rotating accordingly with that part. The rotation works ok, but because of it, since I’m moving the part based on world position, its movement is out of step with the camera’s direction. I tried to use the camera’s lookvector but using its X and Z components didn’t do much. Does anyone have an idea of what I can do? Thanks in advance.

Example:
asda

2 Likes

Hmm, did you multiple 360 on the lookvector?
local directionAngle = game.Workspace.Camera.CFrame.LookVector*360

1 Like

I managed to use LookVector partially. The Forward and Backwards motion are okay, but the side movements are really weird depending on the direction the camera is looking, sometimes moving very fast, sometimes moving very slowly.

In the video, when I press A or D + W or S, it goes very fast:

Here’s the relevant parts of the script:

function inputBegan(input, gameProcessed)
	if not gameProcessed then
		local direction = -Camera.CFrame.LookVector
		local x, z = clamp(direction.X, -1, 1), clamp(direction.Z, -1, 1)
		if input.KeyCode == Enum.KeyCode.A then
			while UserInputService:IsKeyDown(Enum.KeyCode.A) do
				cameraPart.CFrame = cameraPart.CFrame:Lerp(cameraPart.CFrame + Vector3.new(-x, 0, z), .75)
				task.wait()
			end
		elseif input.KeyCode == Enum.KeyCode.D then
			while UserInputService:IsKeyDown(Enum.KeyCode.D) do
				cameraPart.CFrame = cameraPart.CFrame:Lerp(cameraPart.CFrame + Vector3.new(x, 0, -z) , .75)
				task.wait()
			end
		elseif input.KeyCode == Enum.KeyCode.W then
			while UserInputService:IsKeyDown(Enum.KeyCode.W) do
				cameraPart.CFrame = cameraPart.CFrame:Lerp(cameraPart.CFrame + Vector3.new(-x, 0, -z), .75)
				task.wait()
			end
		elseif input.KeyCode == Enum.KeyCode.S then
			while UserInputService:IsKeyDown(Enum.KeyCode.S) do
				cameraPart.CFrame = cameraPart.CFrame:Lerp(cameraPart.CFrame + Vector3.new(x, 0, z), .75)
				task.wait()
			end
		end
	end
end

function onRenderStepped(dt)
	local partPos = cameraPart.Position
	local offset = CFrame.new(OFFSET, OFFSET, OFFSET)
	local cf = cameraPart.CFrame * CFrame.Angles(0, math.rad(rotation), 0) * offset
	Camera.CFrame = CFrame.new(cf.p, partPos)
end

Hmm this might and might not be the solution to the issue, but I think what might be happening is that if you hold d, w at the same times you go 2x faster. What I would maybe do is instead of lerping the camera in the Inputbegan, I would have inputbegan and inputended and have variables that keep track if D,W,A,S is down. And in the renderstepped
I would calculate the direction so if D is down then add .7 to the directionvector
This code is prob not functional but I hope this give an idea of what you could do, you basically don’t lerp the camera right when the input is began, but lets say A is pressed, you change the variable isAdown = true, and then have inputended and if its A then isAdown = false. Then you put the code onRenderStepped so it updates the camera there, this way you don’t need to do
UserInputService:IsKeyDown(Enum.KeyCode.S) to check if the button is down. Did it make sense?

local A, W, S, D = false,false,false,false
local function Toggle(bool, input, gameProcessed)
	if not gameProcessed then
		if input.KeyCode == Enum.KeyCode.A then
			A = bool
		elseif input.KeyCode == Enum.KeyCode.D then
			D = bool
		elseif input.KeyCode == Enum.KeyCode.W then
			W = bool
		elseif input.KeyCode == Enum.KeyCode.S then
			S = bool
		end
	end
end
function inputBegan(input, gameProcessed)
	Toggle(true, input, gameProcessed)
end
function inputEnded(input, gameProcessed)
	Toggle(false, input, gameProcessed)
end

function onRenderStepped(dt)
  local speedVector = vector3.new(0,0,0)
  if D then
    speedVector += vector3.new(0,0,.75)
  end
  if A then
    speedVector += vector3.new(0,0,-.75)
  end
  if W then
    speedVector += vector3.new(.75,0,0)
  end
  if S then
    speedVector += vector3.new(-.75,0,0)
  end
  cameraPart.CFrame = cameraPart.CFrame:Lerp(cameraPart.CFrame + Vector3.new(x, 0, z), .75)
end)
1 Like

After some testing I found out what is the problem. The LookVector is also considering world space directions, so when I look exactly on the +Z axis, for example, pressing A will cause the part to just move along that axis and since the x value is close to zero, it creates the wrong motion. Not really sure why W and S are completely fine, but I’ll try to make this LookVector relative to the part and work things out. I’ll update this thread if anything clears. Thanks for your input, I appreciate it.

Found the solution. It was just the matter of using RightVector and LeftVector of the own camera, figuring out the direction. Here’s the code:

function inputBegan(input, gameProcessed)
	if not gameProcessed then
		if input.KeyCode == Enum.KeyCode.A then
			while UserInputService:IsKeyDown(Enum.KeyCode.A) do
				local direction = -Camera.CFrame.RightVector -- Left Vector
				local x, z = clamp(direction.X, -1, 1), clamp(direction.Z, -1, 1)
				cameraPart.CFrame = cameraPart.CFrame:Lerp(cameraPart.CFrame + Vector3.new(x, 0, z), .75)
				task.wait()
			end
		elseif input.KeyCode == Enum.KeyCode.D then
			while UserInputService:IsKeyDown(Enum.KeyCode.D) do
				local direction = Camera.CFrame.RightVector
				local x, z = clamp(direction.X, -1, 1), clamp(direction.Z, -1, 1)
				cameraPart.CFrame = cameraPart.CFrame:Lerp(cameraPart.CFrame + Vector3.new(x, 0, z) , .75)
				task.wait()
			end
		elseif input.KeyCode == Enum.KeyCode.W then
			while UserInputService:IsKeyDown(Enum.KeyCode.W) do
				local direction = -Camera.CFrame.LookVector
				local x, z = clamp(direction.X, -1, 1), clamp(direction.Z, -1, 1)
				cameraPart.CFrame = cameraPart.CFrame:Lerp(cameraPart.CFrame + Vector3.new(-x, 0, -z), .75)
				task.wait()
			end
		elseif input.KeyCode == Enum.KeyCode.S then
			while UserInputService:IsKeyDown(Enum.KeyCode.S) do
				local direction = -Camera.CFrame.LookVector
				local x, z = clamp(direction.X, -1, 1), clamp(direction.Z, -1, 1)
				cameraPart.CFrame = cameraPart.CFrame:Lerp(cameraPart.CFrame + Vector3.new(x, 0, z), .75)
				task.wait()
			end
		-- Rotation
		elseif input.KeyCode == Enum.KeyCode.E then
			-- Rotate to the right
			while UserInputService:IsKeyDown(Enum.KeyCode.E) do
				rotation -= 2.5
				task.wait()
			end
		elseif input.KeyCode == Enum.KeyCode.Q then
			-- Rotate to the left
			while UserInputService:IsKeyDown(Enum.KeyCode.Q) do
				rotation += 2.5
				task.wait()
			end
		end
	end
end

function onRenderStepped(dt)
	local partPos = cameraPart.Position
	local offset = CFrame.new(OFFSET, OFFSET, OFFSET)
	local cf = cameraPart.CFrame * CFrame.Angles(0, math.rad(rotation), 0) * offset
	Camera.CFrame = CFrame.new(cf.p, partPos)
end

Either way, thank you for your suggestions.

2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.