Making the character movement to not be relative to the camera

So I have a topdown camera system in my game. Thing is, it works based off of the camera, which I don’t want. Let me explain what I mean.

When I press and hold W, I get this

But I wan’t it to work like I am holding both W and A/S and D, like this

My question is, how do I make the camera movement not base it off of my custom camera placements.

So far, I’ve tried to set the Cameras CameraSubject to the HumanoidRootPart, and change the CFrame of the camera to my custom one. Hasn’t worked. I’ve also looked around on the DevForum and on Google. Haven’t found a solution over there either. My next solution, which I’m not sure how I would pull off is to change Roblox’ default camera system. Not sure how it works though, so not gonna change that just yet.

Here’s my code I used

LocalScriot under StarterPlayerScripts.Client (made my own Client folder under StarterPlayerScripts)

print("StarterPlayer Client")

-- Essentials
local Client = script.Parent
local Player = game.Players.LocalPlayer
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")

-- Modules
local TDIsoCamera = require(Client:WaitForChild("TDIsoCamera"))

The TDIsoCamera module:

-- Essentials
local TDIsoCamera = {}
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local ContextActionService = game:GetService("ContextActionService")
local WR = workspace:WaitForChild("Resource")
local doTDIsoCamera = true
local Camera = WR:WaitForChild("Camera")
local CurrentCamera = game.Workspace.CurrentCamera

function TDIsoCamera.SetCameraToPart(Part, Offset) -- Offset should be a Vector3
	CurrentCamera.CameraType = Enum.CameraType.Orbital
	Camera.Position = Part.Position + Offset
	CurrentCamera.CameraSubject = Part
	CurrentCamera.CFrame = Camera.CFrame
end

local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
Player.CharacterAdded:Connect(function(c)
	Character = c
end)

RunService.RenderStepped:Connect(function()
	if doTDIsoCamera == true then
		if Character:FindFirstChild("HumanoidRootPart") then
			TDIsoCamera.SetCameraToPart(Character.HumanoidRootPart, Vector3.new(-14,19,14))
		end
	end	
end)

-- this part is just so I can toggle my topdown camera system, don't worry too much about it.

UserInputService.InputBegan:Connect(function(input, gameProcessingEvent)
	if not gameProcessingEvent then
		if input.KeyCode == Enum.KeyCode.X then
			doTDIsoCamera = not doTDIsoCamera
			if doTDIsoCamera == false then
				CurrentCamera.CameraSubject = Character.Humanoid
				CurrentCamera.CameraType = Enum.CameraType.Custom
			end
		end
	end
end)

--[[ContextActionService:BindActionAtPriority("NoRMBDrag", function()
	return Enum.ContextActionResult.Sink
end, false, Enum.ContextActionPriority.High.Value, Enum.UserInputType.MouseButton2)--]]

return TDIsoCamera

Sorry if you don’t understand, let me know if you want me to try to explain better. Also, this is my first dev forum post, so let me know if I need to change the catagory or anything.
Thanks!

2 Likes

Mean’t for it to be CurrentCamera.CameraType = Enum.CameraType.Scriptable, forgot to change this from testing. My bad!

2 Likes

The built-in control script has no way of doing this. You’ll have to program your own controls. Here’s a super simple ControlScript that you can put in StarterPlayerScripts that does more or less what you want:

local RunS = game:GetService("RunService")
local InputS = game:GetService("UserInputService")

local UP = Vector3.new(0, 1, 0)
local WALK_FRONT_VECTOR = Vector3.new(0, 0, -1).Unit
local WALK_RIGHT_VECTOR = WALK_FRONT_VECTOR:Cross(UP) --perpendicular to front direction

local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()

player.CharacterAdded:Connect(function(_character)
  character = _character
end)

local function getWalkDirection()
  local walkDir = Vector3.new()

  if InputS:IsKeyDown(Enum.KeyCode.W) then
    walkDir += WALK_FRONT_VECTOR
  end

  if InputS:IsKeyDown(Enum.KeyCode.S) then
    walkDir -= WALK_FRONT_VECTOR
  end

  if InputS:IsKeyDown(Enum.KeyCode.D) then
    walkDir += WALK_RIGHT_VECTOR
  end

  if InputS:IsKeyDown(Enum.KeyCode.A) then
    walkDir -= WALK_RIGHT_VECTOR
  end

  if walkDir.Magnitude > 0 then --(0, 0, 0).Unit = NaN, do not want
    walkDir = walkDir.Unit --Normalize, because it's not a Unit vector if more than 1 movement key is pressed
  end

  return walkDir
end

local function updateMovement()
  if character and character:FindFirstChild("Humanoid") then
    local walkDir = getWalkDirection()
    character.Humanoid:Move(walkDir)
  end
end

RunS.RenderStepped:Connect(updateMovement)

You can change the WALK_FRONT_VECTOR to any direction you like, and that will be the direction you walk in when you press W.

1 Like

Turns out there is some code you can change in the built-in control scripts! All I had to do was to get in play test, copy the PlayerModule, then leave and paste it in StarterPlayerScripts.Then I’d go to PlayerModule > ControlModule > BaseCharacterController, and under the BaseCharacterController.new() function, there’s a variable called moveVectorIsCameraRelative, if I set it to false, it’s the way I want it! Thanks for spending your time writing me a solution anyway, I really appriciate it!

11 Likes

Damn cool, didn’t know that was a thing! Definitely easier than rolling your own control script form scratch xD Especially considering mobile / controller support and all that.

2 Likes