How to approach making a custom joystick?

I am confused as to what stuff I can use to create a custom mobile joystick. Is there a function to check if the player is touching the screen? Perhaps some rather reliant events? What resources should I check? Thank you very much for your time!

8 Likes

Creating Mobile Buttons use this post. U ll need a script which moves a frame to finger position.

2 Likes

I have implemented mobile joysticks a couple of times. First and foremost, reference the roblox movement scripts since the entire default mobile thumbstick code is in that. https://github.com/Roblox/Core-Scripts/blob/master/PlayerScripts/StarterPlayerScripts/ControlScript/MasterControl/Thumbstick.lua

Anyways, yea just use UserInputService or detect InputEvents on the thumbstick GuiObject. They key insight is that to make sure you are tracking the correct touch input (in the case there are multiple fingers touching the screen at once), the input object will have the same reference everytime it is passed in a touch event. This allows you to bind to a touch ended and check if it was the original thumbstick touch input.
For example:

local UserInputService = game:GetService("UserInputService")

local thumbstickGuiObject -- could be the entire thumbstick frame or just the small dragger part

local usingThumbstick = false
local currentTouch: InputObject

thumbstickGuiObject.InputBegan:Connect(function(inputObj: InputObject, gp)
	if not usingThumbstick and inputObj.UserInputType == Enum.UserInputType.Touch then
		usingThumbstick = true
		currentTouch = inputObj
		-- handle the rest of the thumbstick starting drag logic
	end
end)

UserInputService.InputEnded:Connect(function(inputObj: InputObject, gp)
	 if usingThumbstick and inputObj == currentTouch then
		 usingThumbstick = false
		 currentTouch = nil
		 -- handle the rest of the thumbstick end drag logic
	 end
end)
14 Likes

I see what you mean here, however, what if I wanted to use two joysticks? How would I read the positions on the screen?

In that case, when a drag starts, you would want to listen to the UserInputService Changed event and listen for touch movements. Again, compare the input objects to the touch objects to confirm you are reading the correct input. The input object will also have a position field. You can use this to find the offset from the center of the joy/thumbstick in pixels and from there calculate a 2d vector as the input from the joystick.

1 Like

Hey, I’m having some issues with dragging and snapping back in place, could you help me by providing a sample code of how you can make the drag happen?

You would need to calculate the position, by using such properties as AbsoluteSize and AbsolutePosition as well as by checking the position of the Input object obtained from InputBegan every time it changes (Input.Changed). When you stop the input, just set the thing’s position back to the inicial one.

Also, @wafflechad, I managed to make it work, tysm for the help! 2022-07-07 18-46-13 (streamable.com)

1 Like

Nice work, yeah I already made it yesterday, however, on actual mobile, I cannot control both joysticks at once because roblox is only detecting one joystick at a time.

1 Like

I am guessing it is due to you only being able to attain one input object. If you can make an invisible GUI or such, I recommend you use GuiObject.InputBegan, so you can handle different inputs at the same time.

1 Like

can i ask a question?, how did u make the character move based on the thumbstick?

2 Likes

To be based off it? I got the AbsolutePosition of the stick and base objects and got the unit vector between them. For example,

local BasePosition = UIBaseObject.AbsolutePosition -- Gives vector2 of its position on the screen
local StickPosition = UIStickObject.AbsolutePosition -- Gives vector2 of its position on the screen

local Difference = StickPosition - BasePosition
local Direction = Vector3.new(Difference.X, 0, Difference.Y)
Humanoid:Move(Direction, true) -- second parameter refers to "relative to camera", 
-- thus if you were to make a 2.5D game, as I am doing, you would set it to false

Of course you would run this snippet in a RunService event or some other criteria you would set, but I think you get the point. Hope this helped!

1 Like

woah that cool but can i ask you another question how did u manage to keep the red button follow your mouse while keeping the button inside the frame? cuz i been trying to make the same its kinda complicated and i think i need to use unit or magnitude

You would do something like this:

local BasePosition = UIBaseObject.AbsolutePosition -- Gives vector2 of its position on the screen

local DifferenceVector = InputPosition - BasePosition
local DesiredAbsolutePosition = DifferenceVector.Unit * math.min(DifferenceVector.Magnitude, UIBaseObject.AbsoluteSize.Y / 2)

You would then use Udim2 and what not to set the position of the stick to the absolute position in the variable DesiredAbsolutePosition.

1 Like

so here’s my own version the joystick is a frame and joystick.button is inside the joystick like a ball in the joystick u know what i mean so the problem is the button goes off the joystick like in the video

robloxapp-20231107-2132522.mp4 (1.6 MB)

	while task.wait() do
		if Type == "JoyStick" then
			local range = JoyStick.AbsoluteSize.X/2
			local centreOfWheel = JoyStick.AbsolutePosition
			local mousepos = Vector2.new(Mouse.X - centreOfWheel.X, Mouse.Y - centreOfWheel.Y)
			local distanceFromWheel = (mousepos - centreOfWheel)

			local DesiredAbsolutePosition = distanceFromWheel.Unit * math.min(distanceFromWheel.Magnitude, range)

			local Difference = JoyStick.Button.AbsolutePosition - centreOfWheel
			local Direction = Vector3.new(Difference.X, 0, Difference.Y)

			if joybuttonclicked == true then
				Humanoid:MoveTo(Direction)
				if distanceFromWheel.Magnitude <= range  then
					Humanoid:MoveTo(Direction)
					JoyStick.Button.Position = UDim2.fromOffset(Mouse.X - centreOfWheel.X, Mouse.Y - centreOfWheel.Y)
				elseif distanceFromWheel.Magnitude >= range then
					JoyStick.Button.Position = UDim2.fromOffset(DesiredAbsolutePosition.X,DesiredAbsolutePosition.Y)
				end
			else
				Humanoid:MoveTo(Chracter.PrimaryPart.Position)
			end
		end
	end

sorry about the low quality video this pc is old

Are your anchor points set correctly?

yes its set to 0.5,0.5 both of them i worked on ui’s before its so weird it does this bug and btw is my script correct?

I see nothing wrong with it. Haven’t tested it either, though.

well i can send you the game

I know this post is really old but there are no other posts talking about this so i wanted to ask how did you make the joysticks on the right? How did you make the character face the joystick’s angle?