How to Make My Placement System Compatible with Mobile Devices

Hi, I am using a placement system obtained from EgoMoose: Creating A Furniture Placement System

My issue is that I want this system to work on computer and mobile devices but this system only works on computers.

I’ve looked on dev forum but I didn’t see anything exactly like my question or that could help me.

This is the only thing I’ve tried. In the ClientPlacement LocalScript if you scroll all the way down to where the ContextActionService:BindAction() statements are, I add a new statement saying

game:GetService(“ContextActionService”):BindAction(“place”, onPlace, false,Enum.UserInputType.Touch) --I added Touch instead of MouseButton1. This actually works for when a user taps on their mobile device, but then the placement for computer doesn’t work.

Anyways that’s what I tried. I’m open to any suggestions or ideas on how to allow this placement system to work both on computer and mobile.

It may be easier for you to help me if you have experience with this particular placement system before or you go to the link I provided and look at all the components to gain a better understanding.

This is the ClientPlacement LocalScript:


local canvas = game.Workspace:WaitForChild("ExampleCanvas")
local remotes = game:GetService("ReplicatedStorage"):WaitForChild("Remotes")
local furniture = game:GetService("ReplicatedStorage"):WaitForChild("Furniture")
local pieces = furniture:GetChildren()

local placementClass = require(game:GetService("ReplicatedStorage"):WaitForChild("Placement"))
local placement = placementClass.fromSerialization(canvas, remotes.DSPlacement:InvokeServer(false, false))
placement.GridUnit = 2

local mouse = game.Players.LocalPlayer:GetMouse()
mouse.TargetFilter = placement.CanvasObjects

local rotation = 0
local modelCount = 0
local model = nil

--

local function onSwitch(actionName, userInputState, input)
	if (userInputState == Enum.UserInputState.Begin) then
		if (model) then
			model:Destroy()
		end
		modelCount = modelCount + 1 > #pieces and 1 or modelCount + 1
		model = pieces[modelCount]:Clone()
		model.Parent = placement.CanvasObjects
	end
end

local function onRotate(actionName, userInputState, input)
	if (userInputState == Enum.UserInputState.Begin) then
		rotation = rotation + math.pi/2
	end
end

local function onPlace(actionName, userInputState, input)
	if (userInputState == Enum.UserInputState.Begin) then
		local cf = placement:CalcPlacementCFrame(model, mouse.Hit.p, rotation)
		placement:Place(furniture[model.Name], cf, placement:isColliding(model))
	end
end

local function onClear(actionName, userInputState, input)
	if (userInputState == Enum.UserInputState.Begin) then
		model.Parent = nil
		placement:Clear()
		model.Parent = mouse.TargetFilter
	end
end

local function onSave(actionName, userInputState, input)
	if (userInputState == Enum.UserInputState.Begin) then
		placement:Save()
	end
end


--

onSwitch(nil, Enum.UserInputState.Begin, nil)

game:GetService("ContextActionService"):BindAction("switch", onSwitch, false, Enum.KeyCode.E)
game:GetService("ContextActionService"):BindAction("rotate", onRotate, false, Enum.KeyCode.R)
game:GetService("ContextActionService"):BindAction("place", onPlace, false,Enum.UserInputType.Touch) -- I added this line.
game:GetService("ContextActionService"):BindAction("place", onPlace, false, Enum.UserInputType.MouseButton1)
game:GetService("ContextActionService"):BindAction("clear", onClear, false, Enum.KeyCode.C)
game:GetService("ContextActionService"):BindAction("save", onSave, false, Enum.KeyCode.F)

game:GetService("RunService").RenderStepped:Connect(function(dt)
	local cf = placement:CalcPlacementCFrame(model, mouse.Hit.p, rotation)
	model:SetPrimaryPartCFrame(cf)
end)

Please do not ask people to write entire scripts or design entire systems for you. If you can’t answer the three questions above, you should probably pick a different category.

could you do something like this before binding to context action service?

local UserInputService = game:GetService("UserInputService")

if UserInputService.TouchEnabled and not UserInputService.MouseEnabled then --Using touch screen and no mouse connected
    game:GetService("ContextActionService"):BindAction("place", onPlace, false,Enum.UserInputType.Touch)
else if UserInputService.MouseEnabled then
    game:GetService("ContextActionService"):BindAction("place", onPlace, false, Enum.UserInputType.MouseButton1)
end

(I haven’t tested this)

Also most placements use a gui button to place on mobile so players can still see the preview when tapping instead of immediately placing.

The code you provided only works on computer.

Are you suggesting that I make a designated button for mobile devices so when that button is acting on it will place the item?

After reading the documentation couldn’t you just do something like this?

ContextActionService:BindAction("place", onPlace, false, Enum.UserInputType.MouseButton1, Enum.UserInputType.Touch)

And yeah, some games use a seperate button (tap screen to move preview, tap button to place) but it really depends on what you want your placement system to do. so you could just do:

ContextActionService:BindAction("place", onPlace, true, Enum.UserInputType.MouseButton1)

which would create a button for you.

Again haven’t tested though (am away from computer)

This still doesn’t work. Do you have any other ideas?

Weird… I’m implementing a similar system using a version of EgoMoose’s furniture placement system (I converted it to typescript) and the multiple input types in the same binding worked for me:

ContextActionService:BindAction("place", onPlace, false, Enum.UserInputType.MouseButton1, Enum.UserInputType.Touch)

I just needed to double tap for it to place.

1 Like

So you are saying that that code you wrote above is working for you?

I just tested it. It works now! Thank you so much.

1 Like