I’m creating a Quest System for a project, in which the NPCs have a ClickDetector that will pop up a dialogue upon clicking. depending on the answers, the NPC will give you different quests to complete.
So i made this script: (located in the NPC model)
local Figure = script.Parent
local Humanoid = Figure:WaitForChild("Humanoid")
local ClickDetector = Figure:WaitForChild("ClickDetector")
local Start_Dialogue_Bindable = game:GetService("ReplicatedStorage").Start_Dialogue
ClickDetector.MouseClick:Connect(function(player)
--Start_Dialogue_Bindable:Fire(player,npc_name)
Start_Dialogue_Bindable:Fire(player,script.NPC_Name.Value) -- StringValue
end)
That would work, but i realize the project will have lots of NPCs to keep the player busy and that means one script for each NPC.
So i came up with a solution to reduce the amount of scripts, which is simply creating a single script in ServerScriptService that does this:
local Start_Dialogue_Bindable = game:GetService("ReplicatedStorage").Start_Dialogue
for index,npc in pairs(workspace.Npcs:GetChildren()) do
local ClickDetector = npc:WaitForChild("ClickDetector")
ClickDetector.MouseClick:Connect(function(player)
--Start_Dialogue_Bindable:Fire(player,npc_name)
Start_Dialogue_Bindable:Fire(player,npc.NPC_Name.Value)
end)
end
What is the best practice in this case? (1 script for each NPCor1 script for ALL)
There’s a programming principle, DRY. Don’t Repeat Yourself. If you have to change some behavior, add some things here or there, and have 100 different scripts in 100 different objects, that’s going to inconvenience you.
Things like CollectionService exist so you can tag all instances with a certain identifier and retrieve them later. It really helps for things that share behaviors.
Even better for things that share behaviors is a programming paradigm known as OOP.
Sure, with one script for all you can have all NPCs share that behavior, but at the same time, what if some NPCs are different? What if there are small variations in behavior? What if it depends on certain things like what data they hold? OOP allows to create classes and subclasses that share common behavior but you can add layers and layers of overriding and defaults that allow you to create a ton of different behaviors yet sharing everything that should be shared.
As mentioned before, OOP is definitely a great way to program. It can turn a mess of a framework for communication into something as simple as:
local npc = NPC.new("Carl", NPCType.Friendly, npcSpawnPos)
npc:LoadDialog(DLG.Welcome_game)
npc:OnSay(function(player, result)
if result == DLG.Welcome_game_end then
player:MoveTo(gameStart)
end
end)