I have been following a youtube video for a FPS viewmodel. I have placed the viewmodel inside a Folder in ReplicatedStorage. I also added a ModuleScript stored in a Folder in ReplicatedStorage. I then made a Folder with a LocalScript inside it.
I was just wondering if there was any way I could improve these codes:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local ViewModel = ReplicatedStorage:WaitForChild("ViewModels"):WaitForChild("ViewModel"):Clone()
local ViewModelConfigurationModule = require(ReplicatedStorage:WaitForChild("ModuleScripts"):WaitForChild("ViewModelConfiguration"))
local Camera = workspace.CurrentCamera
ViewModel.Parent = Camera
function PositionViewModel()
ViewModel:SetPrimaryPartCFrame(Camera.CFrame * ViewModelConfigurationModule.OffsetFromCamera)
end
RunService.RenderStepped:Connect(PositionViewModel)
local RunService = game:GetService("RunService")
local Workspace = game:GetService("Workspace")
local CurrentCamera = Workspace["CurrentCamera"]
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ModuleScripts = ReplicatedStorage:WaitForChild("ModuleScripts")
local ViewModelConfig = ModuleScripts:WaitForChild("ViewModelConfiguration")
local Configuration = require(ViewModelConfig)
local Folder = ReplicatedStorage:WaitForChild("ViewModels")
local ViewModel = Folder:FindFirstChild("ViewModel"):Clone()
do
ViewModel["Parent"] = CurrentCamera
end
RunService["RenderStepped"]:Connect(function()
ViewModel:SetPrimaryPartCFrame(CurrentCamera["CFrame"] * Configuration["OffsetFromCamera"])
end)
Logic inside of a “do end” executes in a new local scope. Let’s say we have a variables “x”, it allows you to separate the “x” from the rest of the outside logic.
Example 1:
do
local x = 5
end
print(x)
--[[
If we try to print out x, it will just print nil,
because the x was never defined outside the local scope.
]]
--Output: nil
Example 2:
local x
do
x = 5
end
print(x)
--[[
If we try to print out x, it will print 5.
]]
--Output: 5
So it’s still the same as just defining things in a scope? But without the need for any connections?
local part = script.Parent
part.Touched:Connect(function(otherpart)
print(otherpart) -- prints something
end)
print(otherpart) -- prints nil
As interesting as it is i don’t think i understand any use cases for defining locals in another scope that i may/or may not be using, at least from my experience.
You can use do ends to basically seperate different scopes, it’s helpful if you are working with variable scopes and garbage collection. Most of the times, you don’t need to use it, but it’s nice to be able to use it here and there for better readability.
We can delimit a block explicitly, bracketing it with the keywords do - end . These do blocks can be useful when you need finer control over the scope of one or more local variables.
It can also provide a micro optimisation, as do-end reduces the size of a scope (helping with environment indexing speeds). My knowledge of this comes from LuaJIT and Lua. So I’m unsure if LuaU does some sort-of compiler optimisations, making this redundant.
You have very well explained what’s the purpose of a do end, and since there’s no variable declaration in it, it’s not necessary.
Also, indexing properties with the bracket notation when it’s possible to use dot notation isn’t idiomatic, so is adding unnecessary whitespace to align equal signs.
Yes, I was trying to imply that there is no need for a do end, but I still used it for better readability. Also, I have gotten so used to using the notations instead of periods that I try to avoid switching back because it will create a lot more work and mess up all the organization in my previous logic(s) and it also looks cleaner to me than using periods to index properties.