VectorToObjectSpace() not working as intended

Im trying to make a custom swimming system. And for that I need to get a movedirection that’s relative to the camera. So for that I used VectorToObjectSpace()

The issue however is that it’s working in a really weird way? I am just moving in random directions. I have used VectorToObjectSpace() in the past to make MoveDirection relative to the camera and it has always worked so I am not sure what’s the issue here…

I have tried looking for solutions and none of them worked. I tried just using MoveDirection and well, of course, it worked.

Here’s the entire code that makes it all work:

local runservice = game:GetService("RunService")
local collectionservice = game:GetService("CollectionService")

local swimvelocity = nil
local swimdirection = Vector3.zero
local water = false

local swimspeed = 0

local player = game.Players.LocalPlayer
local char = player.Character
local hum = char:WaitForChild("Humanoid")

runservice.RenderStepped:Connect(function()
	for _, item: BasePart in pairs(collectionservice:GetTagged("Water")) do
		local camerapos = item.CFrame:PointToObjectSpace(workspace.CurrentCamera.CFrame.Position)
		local checking = (math.abs(camerapos.X) <= item.Size.X/2) and (math.abs(camerapos.Y) <= item.Size.Y/2) and (math.abs(camerapos.Z) <= item.Size.Z/2)

		local charpos = item.CFrame:PointToObjectSpace(char.PrimaryPart.Position)
		local charchecking = (math.abs(charpos.X) <= item.Size.X/2) and (math.abs(charpos.Y) <= item.Size.Y/2) and (math.abs(charpos.Z) <= item.Size.Z/2)

		if charchecking then
			if not water then
				water = true

				hum.WalkSpeed = 0
				hum.AutoRotate = false
				hum.JumpHeight = 0

				local attachment1 = Instance.new("Attachment", char.HumanoidRootPart)
				local alignorientation = Instance.new("AlignOrientation", char.HumanoidRootPart)

				alignorientation.Name = "SwimOrientation"
				alignorientation.Mode = Enum.OrientationAlignmentMode.OneAttachment
				alignorientation.Attachment0 = attachment1
				alignorientation.Responsiveness = 15
				alignorientation.MaxTorque = math.huge
				alignorientation.MaxAngularVelocity = 50

				swimvelocity = Instance.new("LinearVelocity", char.HumanoidRootPart)

				swimvelocity.Attachment0 = attachment1
				swimvelocity.ForceLimitMode = Enum.ForceLimitMode.PerAxis
				swimvelocity.ForceLimitsEnabled = true
				swimvelocity.VelocityConstraintMode = Enum.VelocityConstraintMode.Vector
				swimvelocity.MaxAxesForce = Vector3.new(100000, 100000, 100000)
			end
		else
			if water then
				local alignorientation : AlignOrientation = swimvelocity.Parent:FindFirstChild("SwimOrientation")

				water = false

				hum.WalkSpeed = 16
				hum.AutoRotate = true
				hum.JumpHeight = 7.2

				swimvelocity.Attachment0:Destroy()
				swimvelocity:Destroy()
				alignorientation:Destroy()
			end
		end
	end

	if swimvelocity then
		local alignorientation : AlignOrientation = swimvelocity.Parent:FindFirstChild("SwimOrientation")
		
		if alignorientation then
			local movedirection = hum.MoveDirection

			if hum.MoveDirection.Magnitude > 0 then
				swimdirection = workspace.CurrentCamera.CFrame:VectorToObjectSpace(hum.MoveDirection)

				alignorientation.CFrame = CFrame.new(Vector3.new(0, 0, 0), swimdirection)

				swimspeed = math.lerp(swimspeed, 40, 0.01)
			else
				swimspeed = math.lerp(swimspeed, 0, 0.01)
			end

			swimvelocity.VectorVelocity = swimvelocity.VectorVelocity:Lerp(swimdirection * swimspeed, 0.1)
		end
	end
end)

Humanoid.MoveDirection is world space. I’d recommend starting with the input vector by reading the player scripts. Then you can do camera:VectorToWorldSpace(moveVector) to get the world direction you want your character to move in.

That should make your alignorientation work, but to get your swimvelocity working you’ll need to either convert the world direction to humanoid root part space rootPart.CFrame:VectorToObjectSpace(worldMove) or switch the LinearVelocity.RelativeTo property to world.

local controls = require(game.Players.LocalPlayer.PlayerScripts.PlayerModule):GetControls()

local move = controls:GetMoveVector()
local worldMove = workspace.CurrentCamera.CFrame:VectorToWorldSpace(move)

alignorientation.CFrame = CFrame.lookAt(Vector3.zero, worldMove)
local swimdirection = rootPart.CFrame:VectorToObjectSpace(worldMove)
1 Like

Thanks for the response! I’ve tried but it still doesn’t seem to work :confused: I remember making a script where I made the MoveDirection relative to the Camera and it worked well but now it just doesn’t?

Making it relative to the camera doesn’t make sense. The align and linear velocity instances do not apply their forces relative to the camera.

Maybe I’m not recalling correctly you can try making the align orientation relative to the root part as well?

I think I have fixed it…? Only thing that wasn’t working correctly was the LinearVelocity for some reason. The AlignOrientation worked fine (Sorry for the poor wording, made it look like the entire thing didn’t work!). I basically just made the direction AlignOrientation.CFrame’s LookVector and it works! Again thank you for the response!

1 Like

Yep I see why now.

Instance.new("LinearVelocity").RelativeTo == Enum.ActuatorRelativeTo.World

I assumed it was defaulting to Enum.ActuatorRelativeTo.Attachment0.

Your final code should be:

local controls = require(game.Players.LocalPlayer.PlayerScripts.PlayerModule):GetControls()

local move = controls:GetMoveVector()
local worldMove = workspace.CurrentCamera.CFrame:VectorToWorldSpace(move)

alignorientation.CFrame = CFrame.lookAt(Vector3.zero, worldMove)
local swimdirection = worldMove
1 Like

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