If you want to have the Component.Auto() function to work, you can use Wally and add "Component = “sleitnick/component@1.1.0"” instead of "Component = “sleitnick/component@2.1.0"” as a dependency. otherwise, you will not be able to use the Auto function, and you will have to just go over the children in the folder and add all of the components manually.
Is there a way to get older versions? Seems kinda bad to have it automatically update and have a dozen things change, get removed, etc. I can’t imagine the anger I’d have if I had 40-50k lines of code and then the framework changes overnight and i have to rewrite everything
If you are using Wally, you can just install an earlier version (“sleitnick/component@1.1.0”), If not, I could send you the older version if you would like.
Here is the Auto function that is in the older version of Component:
--[=[
@param parent Instance
@return RBXScriptConnection
Scans all descendants of `parent` and loads any ModuleScripts found, then
calls `Component.new` on those loaded modules.
Each component module class must have a `Tag` string property to map it
to the proper tag.
]=]
function Component.Auto(parent)
local function Setup(moduleScript)
local m = require(moduleScript)
assert(type(m) == "table", "Expected table for component")
assert(type(m.Tag) == "string", "Expected .Tag property")
Component.new(m.Tag, m, m.RenderPriority, m.RequiredComponents)
end
for _,v in ipairs(parent:GetDescendants()) do
if v:IsA("ModuleScript") then
Setup(v)
end
end
return parent.DescendantAdded:Connect(function(v)
if v:IsA("ModuleScript") then
Setup(v)
end
end)
end
Trying to run this function with the new version on Component will not work now though as Component.new() now takes in new parameters, and a class like the old one took in is not one of them.
It seems to have changed indeed. I would join the Roblox OSS Discord and ask it in #knit. The creator of the framework is quite active in the chat. You can find an invite in the footer of the Rojo home page.
Component.Auto() was removed in favor of manually requiring the components in Knit’s bootstrap code like so:
Knit:Start():andThen(function()
for i, component in pairs(script.Parent.Components:GetChildren()) do
if component:IsA("ModuleScript") then
require(component)
end
end
end):catch(warn)
What’s the point of using the Component Util if I just can use CollectionService myself and save the hassle? It seems like more work unless the Components can be seen via the client and vice versa, I see no reason to use it.
This is true but with Knit Components you have metatables which is nice to have in a component. When you do it normally with CollectionService it is not as powerful. Obviously there is ways to have metatables with the “normal” way but in this case Knit does it for you so you don’t have to do all the extra stuff.
And tbh its not that much code, it may even be less than if you are doing it with CollectionService
local Component = require(ReplicatedStorage.Packages.Component)
local MyComponent = Component.new({
Tag = "MyComponent";
})
function MyComponent:Construct()
-- New Component
end
function MyComponent:Stop()
-- Component Destroyed
end
return MyComponent
Typically when I use components they act as singletons, It’s just a weird way to look at it for me since I’m using to calling Object.new() instead of Object:Construct()
Is there any getting started/tutorial related to the current version of Components? I can’t find anything which tells me how to use the current version, and the docs have been cropped down to basically a list of methods.
I figured out how to use components through trial an error as the documentation is pretty much non-existent. But it was well worth it; I now use components all the time. It’s actually much simpler to use than it appears. Here’s a quick start guide:
I load all the components after the Knit server has started like this:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Knit = require(ReplicatedStorage:WaitForChild("Packages"):WaitForChild("knit"))
local Components = script.Parent:WaitForChild("Components") -- PUT YOUR OWN PATH TO COMPONENTS FOLDER!
Knit.Start():andThen(function()
Knit.Components = {}
for _, c in pairs(Components:GetChildren()) do
Knit.Components[c.Name] = require(c)
end
end):catch(warn)
You could just require each component, but for me it’s useful to be able to access them all in one place, so I store the required components into a new “Components” variable on the Knit instance.
Then create components into the Components folder, such as Health.lua:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Component = require(ReplicatedStorage:WaitForChild("Packages"):WaitForChild("component"))
local Health = Component.new({
Tag = "Health",
})
function Health:Construct()
self.value = 100
end
function Health:Start()
print(self.Instance.." now has a health component")
end
function Health:Stop()
end
function Health:HeartbeatUpdate(dt)
end
function Health:SteppedUpdate(dt)
end
function Health:RenderSteppedUpdate(dt)
end
return Health
Now anything with a “Health” tag added to it will have this component. Pretty simple.
If you wanted to access all the instances which have health from anywhere else in your code (from server) you could just do this:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Knit = require(ReplicatedStorage:WaitForChild("Packages"):WaitForChild("knit"))
Knit.OnStart():await() -- Make sure Knit server is already started
local allHealth = Knit.Components.Health:GetAll()
for _, health in pairs(allHealth) do
print(health.Instance," has Health of ", health.value)
end
As far at inheritance goes you can do it with components like this. Let’s say you have Car and Truck which are both Vehicles. You’d create a Vehicle component. You’d then have a “Car” component, and a “Truck” component, which can access the Vehicle which is attached to their instance.
You’d need to add both a “Vehicle” tag and a “Truck” tag to a truck, and a “Vehicle” tag and a “Car” tag to a car.
While this is not inheritance in the OOP sense, it is essentially the same thing.
Vehicle Component:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Component = require(ReplicatedStorage:WaitForChild("Packages"):WaitForChild("component"))
local Vehicle = Component.new({
Tag = "Vehicle",
})
function Vehicle:Construct()
self.speed = 0
end
return Vehicle
Truck Component:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Component = require(ReplicatedStorage:WaitForChild("Packages"):WaitForChild("component"))
local Knit = require(ReplicatedStorage:WaitForChild("Packages"):WaitForChild("component"))
local Truck = Component.new({
Tag = "Truck",
})
function Truck:Construct()
end
function Truck:Start()
self.vehicle = Knit.Components.Vehicle:FromInstance(self.Instance)
self.vehicle.speed = 10
end
return Truck