Hey! I’m currently making a spray can feature for my game. Its where you have a tool and when you click on an object (such as a wall), it puts a SurfaceGUI on the part and the side the mouse is on. Its supposed to put the GUI where the mouse is, but I don’t know how
I’m using a SurfaceGUI instead of creating a new part for one main reason. With SurfaceGUI, I can make it so the decal cuts off on corners, and actually stick to the part. I tried creating a new part instead, but I like SurfaceGUI more.
Once again, the issue with SurfaceGUI is that I have no idea how to actually position the GUI to where the mouse is. I’ve tried just using the X and Y of the mouse but this happens:
https://gyazo.com/6144fd6fdba6e9110b598b55e3fd2c13
Code:
local mouse = player:GetMouse()
local sprayPos = UDim2.new(0, mouse.X, 0, mouse.Y)
spray.Position = sprayPos
I’ve also tried setting the scale position instead of offset, but it just doesn’t show up
I’m pretty sure I need to find the mouse position relative to the GUI but I’m not sure.
Are there any solutions to this? Any help is appreciated!
(Also, sorry if anything is messed up! I just got access to the devforum yesterday and wanted to post this question as soon as I could!
)
1 Like
local sprayPos = UDim2.new(0, mouse.Position.X, 0, mouse.Position.Y)
1 Like
Sadly this gives an error!
“Position is not a valid member of PlayerMouse Instance”
just set the mouse icon of the mouse to the gui wanted. Here is a post covering this: Mouse | Roblox Creator Documentation
also might want to have a closer look at the mouses properties on the wiki.
1 Like
I don’t think setting the image of the mouse will help much with surface guis, but I’ll look at the wiki again!
I’ve been looking at the wiki for a while and still dont seem to have a good solution to fix this. Any other tips?
It took me awhile to wrap my head around the solution, but here is what I came up with.
Full code
--belongs in starter character scripts
local tool = Instance.new("Tool")
tool.RequiresHandle = false
tool.Name = "Spraycan"
tool.Parent = game.Players.LocalPlayer.Backpack
local player = game:GetService("Players").LocalPlayer
local mouse = player:GetMouse()
local sprayTemplate = Instance.new("ImageLabel")
sprayTemplate.Name = "spray"
sprayTemplate.BackgroundTransparency = 1
sprayTemplate.Image = "http://www.roblox.com/asset/?id=77515058"
sprayTemplate.Size = UDim2.fromOffset(100,100)
--Enum.NormalId."Surface".Name
--direction, vectorDirection
local surfaceNormals = {
Top = {1, "UpVector"},
Bottom = {-1, "UpVector"},
Right = {1, "RightVector"},
Left = {-1, "RightVector"},
Front = {1, "LookVector"},
Back = {-1, "LookVector"}
}
function onActivation()
if mouse.Hit then
local mouseWorldPosition = mouse.Hit.Position
local target = mouse.Target
local surface = mouse.TargetSurface
local surfaceGui: SurfaceGui
for _, child in ipairs(target:GetChildren()) do
if child:IsA("SurfaceGui") then
if child.Face == surface then
surfaceGui = child
break
end
end
end
if not surfaceGui then
surfaceGui = Instance.new("SurfaceGui")
surfaceGui.Face = surface
surfaceGui.Adornee = target
surfaceGui.ClipsDescendants = true
surfaceGui.SizingMode = Enum.SurfaceGuiSizingMode.PixelsPerStud
surfaceGui.Parent = target
end
local surfaceCFrame = target.CFrame * CFrame.new(target.CFrame[surfaceNormals[surface.Name][2]] * surfaceNormals[surface.Name][1] * target.Size)
local surfaceHit = surfaceCFrame:PointToObjectSpace(mouseWorldPosition)
local spray = sprayTemplate:Clone()
local sprayPosition = UDim2.fromScale(0.5,0.5) - UDim2.fromOffset(spray.AbsoluteSize.X/2, spray.AbsoluteSize.Y/2)
--converting the surfaceHit vector3 to a UDim2, this bit is a pain
local surfaceName = surface.Name
local pixelsPerStud = surfaceGui.PixelsPerStud
if surfaceName == "Top" then
sprayPosition += UDim2.fromOffset(-surfaceHit.Z * pixelsPerStud, surfaceHit.X * pixelsPerStud)
elseif surfaceName == "Bottom" then
sprayPosition += UDim2.fromOffset(-surfaceHit.Z * pixelsPerStud, -surfaceHit.X * pixelsPerStud)
elseif surfaceName == "Front" then
sprayPosition += UDim2.fromOffset(-surfaceHit.X * pixelsPerStud, -surfaceHit.Y * pixelsPerStud)
elseif surfaceName == "Back" then
sprayPosition += UDim2.fromOffset(surfaceHit.X * pixelsPerStud, -surfaceHit.Y * pixelsPerStud)
elseif surfaceName == "Right" then
sprayPosition += UDim2.fromOffset(-surfaceHit.Z * pixelsPerStud, -surfaceHit.Y * pixelsPerStud)
elseif surfaceName == "Left" then
sprayPosition += UDim2.fromOffset(surfaceHit.Z * pixelsPerStud, -surfaceHit.Y * pixelsPerStud)
end
--rotate the image
if surfaceName == "Top" or surfaceName == "Bottom" then -- face player
local playerPos = player.Character.PrimaryPart.Position
local direction = (Vector3.new(playerPos.X, mouseWorldPosition.Y, playerPos.Z) - mouseWorldPosition).Unit
local rotation = math.deg(math.atan2(direction.Z, direction.X))
if surfaceName == "Bottom" then
rotation += 180
end
spray.Rotation = rotation
else --upward rotation
local up = Vector3.new(0,1,0)
local targetUpVector = target.CFrame.UpVector
local rotation = math.deg(math.acos(up:Dot(targetUpVector)))
spray.Rotation = rotation
end
spray.Position = sprayPosition
spray.Parent = surfaceGui
end
end
tool.Activated:Connect(onActivation)
Spraycan.rbxl (30.8 KB)
Here is the game, find the code in the starter character scripts or above. Hope this helps. I am happy to answer any questions you may have aswell.
2 Likes
Wow thanks! I’ll check it out later today!
I just checked it out and it works amazingly!! I’m gonna edit the code a bit then use it! Thanks a ton! 