Choosing a Direction Based on Camera Angle

Hi, currently I’m working on making a system where you fire cannons on a ship on whichever side your camera is closest towards facing. For example, if your camera was oriented to the left of your ship, it’d fire the cannons on the left side. The base concept looks like this:

The highlighted part would be the side that the ship’s cannons would fire on if you were to fire.

This is the code that I have so far for it, where it’s implied that the direction the ship’s pointing at is always an orientation of (0,0,0):

game.Workspace.CurrentCamera.Changed:connect(function()
	game.Workspace.CamPart.CFrame = game.Workspace.CurrentCamera.CFrame
	
	local Dir = game.Workspace.CamPart.Orientation.Y
	
	game.Workspace.Forward.BrickColor = BrickColor.new("Medium stone grey")
	game.Workspace.Right.BrickColor = BrickColor.new("Medium stone grey")
	game.Workspace.Left.BrickColor = BrickColor.new("Medium stone grey")
	game.Workspace.Backward.BrickColor = BrickColor.new("Medium stone grey")
	
	if (Dir >= 0 and Dir <= 45) or (Dir <= 0 and Dir >= -45) then -- Forward
		game.Workspace.Forward.BrickColor = BrickColor.new("Lime green")
	elseif (Dir >= 45 and Dir <= 135) then -- Left
		game.Workspace.Left.BrickColor = BrickColor.new("Lime green")
	elseif (Dir <= -45 and Dir >= -135) then -- Right
		game.Workspace.Right.BrickColor = BrickColor.new("Lime green")
	elseif (Dir >= 135 and Dir <= 180) or (Dir <= -135 and Dir >= -180) then -- Backwards
		game.Workspace.Backward.BrickColor = BrickColor.new("Lime green")
	end
end)

But naturally a ship has the ability to turn, and with how this code is written, the side that is chosen depends on the camera’s orientation alone, not the camera’s orientation in relation to the ship’s. So when the ship turns, say 90 degrees, this happens:

The issue is that I’m not sure how to make the camera select a side based on the camera’s orientation in relation to the ship’s, and not the camera’s orientation alone. How do I do this?

Thanks.

Make the Dir relative to the orientation of some part of the ship.

local ShipDir = game.Workspace.Ship.MastOrSomthing_Part.Orientation.Y
local Dir = game.Workspace.CamPart.Orientation.Y - ShipDir

So if the Ship rotates 90 degrees to the camera will be oriented 90 degrees. However, ShipDir is also 90 degrees, so the final relative Dir = 90-90 = 0.

I actually tried that once before, and doing it again gave me this result. This is with the ship’s direction being 90.

https://i.gyazo.com/2e5898e8c02c41035e6d7944bd2fd8a3.mp4

There’s a gap where no side is selected when one should always be.

https://i.gyazo.com/f416aa35fb415895621b7f2d2769dbf2.mp4

Demo place.
OwO.rbxl (16.0 KB)

function GetClosestSide(Sides) --Table of instances
	local ClosestSide, Comparison
	
	for _, Side in pairs(Sides) do
		local CameraOffset = game.Workspace.CurrentCamera.CFrame:PointToObjectSpace(Side.Position).Unit
		local DotProduct = CameraOffset:Dot(Vector3.new(0, Camera.CFrame.LookVector.Y, 0))
		
		if ClosestSide then
			if DotProduct <= Comparison then
				Comparison = DotProduct
				ClosestSide = Side
			end
		else
			Comparison = DotProduct
			ClosestSide = Side
		end
	end
	
	return ClosestSide
end
1 Like

That’s awesome. Thanks a lot for your help.