(math.pi?) Calling all mathematicians, need help with spherical aim/target formula!

What I want to achieve is very complex (at-least for me) and it must involve a-lot of math.

Please bare with me as I already feel as a burden posting on the forum, and even more trying to explain this.

So basically, when controlling a joystick (for example) I am wanting the resulting character walk to position/destination to be angled relative to the camera view/ray. For example, like in water, pulling up and over on a joystick on a mobile device makes you go forward and up (and the upward amount is depending on how the camera angle is).

Below in the pictures (IGNORE THE PINK AND GREEN CIRCLES IN THE BACK), the green cylinder is what I am meaning and the result I want. It is not specifically that radius that I am looking for, any radius is fine, but the resulting ratio from the X and Y and Z to be the same is what I want to be able to use and calculate the red dot, but its like it’s on a plane line of the camera view.

The blue cylinder is all I can do at the moment with this current line of code (I’ve tried many others but this is the most simplest one) and it is very flat, notice how the Y positions would be different:

h is Humanoid and hrp is HumanoidRootPart

“hs.movedir.CFrame = CFrame.new(hrp.Position) * (CFrame.new(h.MoveDirection.X * 10,0,h.MoveDirection.Z * 10))”

FLAT RESULT:


DESIRED RESULT:


I hope someone can help.

1 Like

Like this?

image

It’s not too complicated:

local RunService = game:GetService("RunService")

-- How far to move the target from the HRP
local TARGET_OFFSET_CF = CFrame.new(0, 0, -10)

local Character = script.Parent
local RootPart:Part = Character:WaitForChild("HumanoidRootPart")

local Camera = workspace.CurrentCamera

local Target = Instance.new("Part")
-- Otherwise, there will be the "Studs" texture
Target.BottomSurface = Enum.SurfaceType.Smooth
Target.TopSurface = Enum.SurfaceType.Smooth
Target.Color = Color3.new(0, 0, 1)
Target.Shape = Enum.PartType.Ball
Target.Size = Vector3.one * 2
Target.Transparency = 0.8

Target.CanCollide = false
Target.CanQuery = false
Target.CanTouch = false
Target.Anchored = true

Target.Name = "LookTarget"

-- Make it easier to see
local Highlight = Instance.new("Highlight")
Highlight.FillTransparency = 1
Highlight.Adornee = Target
Highlight.Parent = Target

Target.Parent = Character

RunService.PreRender:Connect(function()
	-- A CFrame at the HRP's position, looking in the same direction as the camera
	local LookingCF = CFrame.lookAlong(RootPart.Position, Camera.CFrame.LookVector)
	-- Offset it forward
	local TargetCF = LookingCF * TARGET_OFFSET_CF
	
	-- Move the sphere to the target smoothly
	Target.CFrame = Target.CFrame:Lerp(TargetCF, 0.5)
end)
1 Like

i suggest ControlModule:GetMoveVector() which returns a unit vector that represents the movement input of the local player. it’s more versatile than Humanoid.MoveDirection and is also readable from all input platforms

---game/StarterPlayer/StarterCharacterScripts/LocalScript.client.lua

local RunService = game:GetService("RunService")

local Player = game:GetService("Players").LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local RootPart = Character.PrimaryPart or Character:WaitForChild("HumanoidRootPart")

local ControlScript = require(Player:WaitForChild("PlayerScripts").PlayerModule:WaitForChild("ControlModule"))

local Camera = workspace.CurrentCamera

local VisualRadius = 6
local VisualPart = Instance.new("Part")
VisualPart.Size = Vector3.one
VisualPart.Anchored = true
VisualPart.CanCollide = false
VisualPart.Shape = Enum.PartType.Ball
VisualPart.Material = Enum.Material.Neon
VisualPart.Parent = workspace
local Highlight = Instance.new("Highlight")
Highlight.Adornee = VisualPart
Highlight.Parent = VisualPart

local function ToCameraSpace()
	return Camera.CFrame:VectorToWorldSpace(ControlScript:GetMoveVector())
end

RunService.Heartbeat:Connect(function()
	VisualPart.Position = RootPart.Position + (ToCameraSpace() * VisualRadius)
end)
2 Likes

Hopefully I understood your question correctly, here’s what I came up with:

https://gyazo.com/c04fc200d7a025dd3628688ca12a76de

The math really just boils down to three lines of code.

local TARGET_DISTANCE = 5

local playerModule = require(player.PlayerScripts:WaitForChild("PlayerModule"))
local controls = playerModule:GetControls()

local function GetTargetPosition(characterPosition)
    local inputVector = controls:GetMoveVector()
    local objectSpace = camera.CFrame.Rotation * inputVector
    return characterPosition + objectSpace * TARGET_DISTANCE 
end

It’s essentially what @overflowed just posted but it takes pitch rotation into account.

1 Like

Thank you very much, it is exactly what I needed. Thank you all for your responses, this resulted more than I expected! If I could, I would mark all 3 as the solution.

1 Like

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