Hello there! Your issue is common to many and unique to none. We should be able to get your script working pretty quickly. I'll just list the issues here for a quick overview:
You assume that a while
loop keeps checking after the condition is determined to be false.
You are using KeyDown
, a deprecated event.
You are defining the character through the workspace, which is not good practice.
You have a wait(5)
at the top of your script for no reason.
I couldn't find anything about LowerTorso
. I'm not sure if it exists. I'll be using the HumanoidRootPart
instead.
Now that I've listed the problems, let's go about solving them. First of all, your while loop will stop checking the condition once it's false. Here's a simpler example so you can see why:
As you can see, this won't work for what you are trying to do. There are two alternatives to your problem (I will include examples at the end of my answer):
1.)
Put the while loop in a function that is called whenever q
is pressed.
2.)
Put the while loop in the event listener directly.
The next problem is that you are using KeyDown
, a deprecated event. If you look here, you can see a message that says, "Mouse events have been superseded by UserInputService
which should be used in all new work." Clearly, we are intended to use UserInputService
instead. For this answer, I'm just going to cover how to detect a key being pressed(If you want a button to pop up for a mobile user, you may want to consider using ContextActionService
instead). Here's an example of how you would implement UserInputService
to detect the q
key being pressed with InputBegan
:
05 | local userInputService = game:GetService( "UserInputService" ) |
07 | userInputService.InputBegan:Connect( function (inputObj, gameProcessed) |
08 | if not gameProcessed and inputObj.KeyCode = = Enum.KeyCode.Q then |
Quick note about the gameProcessed
parameter from the API reference:
Indicates whether the game engine internally observed this input and acted on it. Generally this refers to UI processing, so if a button was touched or clicked from this input, gameProcessedEvent
would be true. This is also true for input events connected via ContextActionService
.
Finally, that wait(5)
at the top of your script is unnecessary. If you're using the proper methods in their proper places, there is no need to yield. You can use the :Wait()
method of the CharacterAdded
event to wait for the character to load in, if it hasn't already.
Ok, here you are. Your final script should look like one of these two options:
03 | local players = game:GetService( "Players" ) |
04 | local userInputService = game:GetService( "UserInputService" ) |
08 | local player = players.LocalPlayer |
10 | local character = player.Character or player.CharacterAdded:Wait() |
11 | local wall = workspace.TransparentTestWall |
16 | local function Round(Number) |
17 | return math.floor((Number / RoundNumber) + 0.5 ) * RoundNumber |
20 | local function changePos() |
24 | local torsoPos = character.HumanoidRootPart.Position |
29 | wall.Position = Vector 3. new(Round(x), y+ 7.8 , Round(z) - 16.5 ) |
35 | userInputService.InputBegan:Connect( function (inputObj, gameProcessed) |
36 | if not gameProcessed and inputObj.KeyCode = = Enum.KeyCode.Q then |
or
03 | local players = game:GetService( "Players" ) |
04 | local userInputService = game:GetService( "UserInputService" ) |
08 | local player = players.LocalPlayer |
10 | local character = player.Character or player.CharacterAdded:Wait() |
11 | local wall = workspace.TransparentTestWall |
16 | local function Round(Number) |
17 | return math.floor((Number / RoundNumber) + 0.5 ) * RoundNumber |
20 | userInputService.InputBegan:Connect( function (inputObj, gameProcessed) |
21 | if not gameProcessed and inputObj.KeyCode = = Enum.KeyCode.Q then |
30 | local hrpPos = character.HumanoidRootPart.Position |
35 | wall.Position = Vector 3. new(Round(x), y+ 7.8 , Round(z) - 16.5 ) |
Personally, I prefer the former, but it's really up to you.
I hope this helps. Have a great day scripting!