the problem with that If statement, is that throttle might not be nil, but currentThrottle apparently is, and you’re not checking it due to the OR
perhaps that should be AND
the problem with that If statement, is that throttle might not be nil, but currentThrottle apparently is, and you’re not checking it due to the OR
perhaps that should be AND
I think its not finding your attribute, maybe your parent.parent… isn’t getting the right object which contains the attribute. I suspect this because:
Function of:
Description:
This function returns the attribute which has been assigned to the given name. If no attribute has been assigned then nil is returned.
JESUS CHRIST LORD ALMIGHTY SIR.
That is a BIG ERROR. I hope this was marked solved without, ahem… the lag issue.
The reason I react as such is as follows:
local RunService = game:GetService("RunService")
local usp = game:GetService("UserInputService")
local throttle = script.Parent.Parent.Parent:GetAttribute("Throttle")
local currentThrottle = script.Parent.Parent.Parent:GetAttribute("currentThrottle")
throttle = 0
local function throttle(step) -- this is being called every frame.
wait(0.5) -- yields do not work in the RunService pipeline events.
local function Input(userinput) -- wait a minute...
if currentThrottle > 100 then -- redundant
currentThrottle = 100 -- redundant
end -- redundant
if currentThrottle < 0 then -- redundant
currentThrottle = 0 -- redundant
end -- I've said it enough so let me explain.
-- There's an awesome math library that has been expanded by ROBLOX;
-- so remove all that redundancy and do this simple one-liner
currentThrottle = math.clamp(currentThrottle, 0, 100) -- Ta-da!
-- separating these input checks is going to make it always eval twice
if userinput.KeyCode == Enum.KeyCode.LeftShift then
throttle = 1
end
-- elseif, remove the end above this. no point in separation here.
if userinput.KeyCode == Enum.KeyCode.LeftControl then
throttle = -1
end
-- okay so let's discuss why you were pointed towards RunService..
-- ..pipeline events.
-- They are more reliable than "wait" (btw use task library task.wait)
-- and two, they provide the frametime (deltatime/step)
-- you may be asking: "Ok, so what? What does that allow for?"
-- well my student, let me tell you.. (this is what you likely wanted)
-- CurrentThrottle + ((ThrottlePerSecond*Step)*throttle)
-- Your CurrentThrottle will increase by ThrottlePerSecond due to
-- the fact that deltatime is time between the frames.
-- This means, the product of UnitsPerSecond * dt (deltatime)..
-- will ALWAYS take a second. And it will be about as smooth as
-- the client FPS. 1/60 is roughly 0.0166~7 so 20*(1/60) will be a
-- 1/3 increase to the currentThrottle per frame, adding up to the
-- previous number of 20 after 60 frames, or 1 second of time.
currentThrottle = currentThrottle + throttle -- Anyways, there's a much
end -- bigger issue at hand here.
usp.InputBegan:Connect(Input) -- oh dear god no. this. this is the lag.
-- you're connecting this event 60 times per second (at first, which then
-- quickly drops you to FAR below 60 frames per second.)
-- You should have the input handle the throttle variable, and then this
-- event handle the CurrentThrottle calculations based on the
-- value of throttle.
-- Meaning, the input is handled outside of the throttle function. This is
-- simply dependant on the input changing the "throttle" variable.
end
RunService.RenderStepped:Connect(throttle)
-- also the error was caused because you named your function "throttle."
-- you cannot ever overlap variables in the same scope and expect it to work.
-- in function throttle, "throttle" is not defined before the function.
-- Basically the function overwrites it, but due to it being localized, the
-- functions scope cannot actually see it, and determines it as nil.
while wait(0.3) do -- task.wait is pretty pog.
print(currentThrottle, "Throttle")
end
Not trying to be rude, just a lot of “What am I looking at right now?!”
I hope this helps, though I hope far more that it wasn’t needed and you did actually get it figured out.
EDIT: foggy sleepy brain mistakes
that’s the program I first tried… I fixed the lag but the error still happens
My current script: (line 22 is where the error is (currentThrottle = currentThrottle + throttle))
Any help?
local usp = game:GetService("UserInputService")
local throttle = script.Parent.Parent.Parent:GetAttribute("Throttle")
local currentThrottle = script.Parent.Parent.Parent:GetAttribute("currentThrottle")
local function throttleFunction()
local function Input(userinput)
if userinput.KeyCode ~= Enum.KeyCode.LeftControl and userinput.KeyCode ~= Enum.KeyCode.LeftShift then
throttle = 0
end
if userinput.KeyCode == Enum.KeyCode.LeftShift then
throttle = 1
end
if userinput.KeyCode == Enum.KeyCode.LeftControl then
throttle = -1
end
currentThrottle = currentThrottle + throttle
print(throttle)
end
usp.InputBegan:Connect(Input)
end
RunService.Heartbeat:Connect(throttleFunction)
I’m sorry but you completely missed why I replied before; and yes I will assist you.
I did not at any point send you modified code in that post. I simply wrote instructions (comments are not useless,) that you did not read; so –
please read the following very carefully.
You are connecting an event that does not disconnect itself. You are not disconnecting it anywhere.
Not only that, you are then connecting it to RUNSERVICE, an event tied to every frame rendered.
FPS Unlocker would make it very evident that after a while, the lag will return and ultimately crash the ROBLOX player, possibly even Studio (although studio is 64 bit so it can handle much more ram. Unlikely to happen.)
Now here’s the catch:
This is not only awful practice, it’s a memory leak. If you didn’t know: a memory leak, is hell. It can cripple a game because of its existence. Tapping Gods (post rewrite) is an example of this. Player base hated it, rework is much nicer.
Your error is caused because you’re connecting the local function Input to UserInputService in a unique scope (from heartbeat/renderstepped/or stepped) which does not automatically grab the environment values you’re trying to access, meaning the Input function doesn’t actually have access to “throttle” or “currentThrottle.”
Now, moving along. You should fix your script like so.
local uInputService = game:GetService("UserInputService")
-- code is structured logic. be descriptive with variable name scheme, you want
-- your code to be easily maintainable. 'uInputService' v. 'usp'
local This = script.Parent; -- this is something you absolutely must get the
-- hang of. Repetitively relying on absolute paths is a clear sign of a novice
-- which is undesirable for even the freshest of learners to the eldest of such.
local ThatFirstParent = This.Parent;
local ThatSecondParent = ThatFirstParent.Parent;
local ThrottleDirection = ThatSecondParent:GetAttribute("Throttle") or 0
local ThrottleValue = ThatSecondParent:GetAttribute("currentThrottle") or 0
local MaxThrottle = 100
local ThrottleIncPerSecond = 20 -- 4 seconds to get to 100.
local KeysDown = {
LShift = false,
LCtrl = false
} -- this will be used later on.
-- now this is where it gets from light teaching to a full lecture, read along
-- and I'll teach you why your original code will never,
-- yes, I repeat; never work.
local LeftShiftKey = Enum.KeyCode.LeftShift -- first tidy up these, not needed but
-- very nice and easy to maintain.
local LeftControlKey = Enum.KeyCode.LeftControl
local function HandleKeyPressed(Input, Handled)
if Handled then return end -- you do not want your control keybinds to fire
-- if a textbox is being typed in, or if the user presses a button.
local Key = Input.KeyCode
-- Now, I will demonstrate everything that you need to do.
if Key == LeftShiftKey then
KeysDown.LShift = true -- key buffer so we can make accurate calculations.
elseif Key == LeftControlKey then
KeysDown.LCtrl = true -- see above comment
end
end
local function HandleKeyReleased(Input, Handled)
if Handled then return end -- same ordeal as the previous function; typing/button = halt user input
local Key = Input.KeyCode
-- Now, I will demonstrate everything that you need to do on this part.
if Key == LeftShiftKey then
KeysDown.LShift = false -- upon release we will set the buffer values false
elseif Key == LeftControlKey then
KeysDown.LCtrl = false -- see above comment
end
end
local function UpdateThrottleValue(Deltatime)
ThrottleDirection = (KeysDown.LShift and 1 or 0) + (KeysDown.LCtrl and -1 or 0)
local Current = ThrottleValue; -- hold our current state
local Goal = Current + (ThrottleIncPerSecond * ThrottleDirection)
ThrottleValue = math.clamp((1-Deltatime) * Current + (Deltatime * Goal), 0, MaxThrottle)
-- Let me explain the above line.
-- The formula here is 1 - Alphatime * Start + Alphatime * Goal
-- Also known as, linear interpolation! (lerp)
-- Alphatime is an arbitrary term for: It can be anything from range0 to range1; 0-1 in this case
-- inline function: function(x0,x1,a) return (1-a)*x0+(a*x1) end
-- Anyways, this could've been simplified, but I'm doing this for learning purposes.
-- I hope this has taught you something, if not; sad boy hours I suppose.
-- QuickFIX: Adding attribute update code
ThatSecondParent:SetAttribute("currentThrottle", ThrottleValue)
end
RunService.Heartbeat:Connect(UpdateThrottleValue)
local InputBegan = uInputService.InputBegan:Connect(HandleKeyPressed)
local InputEnded = uInputService.InputEnded:Connect(HandleKeyReleased)
-- Oh right, and finally we connect the update function to Heartbeat; and connect our input handlers!
-- EDIT: ThrottleValue is the equivalent variable to currentThrottle
-- QuickFIX: Forgot to clamp the value! Fixed that, MaxThrottle is the correspondent max value!
I tried that but on line 59 it gives me this,
Sorry this was an error on my part, give it a second to update and I’ll have it fixed (with the original variable formatting)
I forgot to define CurrentThrottle
EDIT: I forgot I renamed CurrentThrottle
All issues have been fixed. The code should operate as intended now.
EDIT: Also, I may have come off a little rude on my lecture session, but I was tired when I first drafted that reply. My apologies.
Maybe I overlooked something, but where are the functions HandleKeyPressed and HandleKeyReleased called? Is there more to the script that isn’t shown?
Oh my god. I must be going senile. Thank you.
Yes, I forgot the UserInputService connections; holy.
EDIT: This is now fixed. The code should be 100% functional now; although I have not tested it.
Alright, thanks so much! Works like a dream.
Okay, so there’s a problem I ran into a problem… (before I go any further I just want to state this is in a local script but you probably already know this) I added a print that shows all the throttle values and it seems to be adding up, and for the velocity, I made a different script that does this:
local throttle = script.Parent.Parent:GetAttribute("throttleInput")
local currentThrottle = script.Parent.Parent:GetAttribute("currentThrottle")
while wait() do
script.Parent.Parent.BodyVelocity.Velocity = script.Parent.Parent.CFrame.LookVector * currentThrottle
end
but, It doesn’t seem to be working…
You’re only getting the currentThrottle value once; and my script didn’t update it.
I’ll edit my script to update the attribute, and you should use
ObjectWithAttribute:GetAttributeChangedSignal("currentThrottle"):Connect(function()
ObjectWithAttribute.BodyVelocity.Velocity = ObjectWithAttribute.CFrame.LookVector * ObjectWithAttribute:GetAttribute("currentThrottle")
end)
Note: Remove your wait() loop. Do NOT put this inside of it. Just replace the loop with this.
Also do not forget to change ObjectWithAttribute to your reference.
And again, you absolutely need to get into the flow of defining variables references, not writing them out all the time.
It does the following:
Although this is just constructive criticism, please do not take it harshly.
I’m not going to turn because you haven’t started; but please consider it.
local throttle = script.Parent.Parent:GetAttribute("throttleInput")
local currentThrottle = script.Parent.Parent:GetAttribute("currentThrottle")
local ObjectWithAttribute = script.Parent.Parent
ObjectWithAttribute:GetAttributeChangedSignal("currentThrottle"):Connect(function()
ObjectWithAttribute.BodyVelocity.Velocity = ObjectWithAttribute.CFrame.LookVector * ObjectWithAttribute:GetAttribute("currentThrottle")
end)
Doesn’t seem to be working…
(Oh, and that picture is while the playtest is running by the way.)
Oh yeah, and when I look at the attribute in the properties tab, the value doesn’t change but when I print it out in the output it does.
Sorry I had to leave for a moment, I didn’t edit my code; let me add that to it real quick.
This code is now updated; it will:
I tried that but it doesn’t seem to be working…
The attributes still don’t change as well, I’ve tried some different things that don’t give errors and its still acting weird.
Sorry, I won’t be able to assist further than this anymore; dealing with some personal matters.
I’m also not exactly sure what’s going wrong. I can’t really help much further than this.
Sorry that I couldn’t solve your issue.
Regards,
IDoLua
truth is, attributes suck
(in this situation don’t use them, it is what broke it.)