You need to use the Knit Game Framework(A template to help get started using Knit)

Knit
Module Github Documentation

[A base game made using Knit](https://www.roblox.com/games/8272396896/Game-Knit-Game-Framework(Editing Is Enabled))

  • A lightweight framework that simplifies communication between core parts of your Roblox experience and seamlessly bridges the gap between the server and the client. Getting Started

Why should you use Knit?

  • It simplifies Client-Server communication. In knit you will never be interacting directly with remote events. Client functions can be created in services and remote events will be created in the background.

  • Unlike Aero Game Framework Knit allows developers to write their bootstrapping code to start and configure Knit, which gives developers the freedom to extend how Knit functions.

  • A lot of developers don’t know how to structure their game and a lot of the time I’ve seen developers make an entire game using one script for performance benefits(Viable but not worth it). Knit structures your code using the Service(Script) Controller(LocalScript) Paradigm which scale’s quite well.

  • It modularizes your code. Knit Services and Controllers are tables by default meaning you can inject properties that will be assessable from almost anywhere.


Tutorial

  1. Next, we need to make the folders to contain our Services, Controllers, and Components on the server and the client
Server

Screen Shot 2021-12-17 at 10.22.53 AM

Client

Screen Shot 2021-12-17 at 10.22.29 AM

  1. Next we’re going to need the main game script to start knit on the server and the client after you place the knit module in replicated storage make a script in ServerScriptService called Runtime and a script on the client called ClientRuntime.
Server
local Knit = require(game:GetService("ReplicatedStorage").Packages.Knit)
local Component = require(Knit.Util.Component)

Knit.AddServices(script.Parent.Services)

Component.Auto(script.Parent.Components)

Knit.Start():andThen(function()
	warn("Server Started")
end):catch(warn)
Client
local Knit = require(game:GetService("ReplicatedStorage").Packages.Knit)
local Component = require(Knit.Util.Component)

Knit.AddControllers(script.Parent:WaitForChild("Controllers"))

Component.Auto(script.Parent.Components)

Knit.Start():andThen(function()
	warn("Client Started")
end):catch(warn)

That’s it for setup next is learning to make Services, Controllers, and Components.


Services

Services are singleton provider objects that serve a specific purpose on the server. For instance, a game might have a PointsService, which manages in-game points for the players.

A game might have many services. They will serve as the backbone of a game.

Example
local Knit = require(game:GetService("ReplicatedStorage").Packages.Knit)

local TestService = Knit.CreateService{
	Name = "TestService",
	Client = {}
}

function TestService:KnitInit()
	print("Test Service Initialized")
end

function TestService:KnitStart()
	print("Test Service Started")
end

return TestService
AdvancedExample(This example uses a module that I have added to knit util if you would like to text this here is a link
local Players = game:GetService("Players")

local Knit = require(game:GetService("ReplicatedStorage").Packages.Knit)
local Promise = require(Knit.Util.Promise)
local SaveStructure = require(script.SaveStructure)
local ProfileService = require(Knit.Util.ProfileService)
local ReplicaService = require(Knit.Util.ReplicaService)

local Profiles = {}
local Replicas = {}
local PlayerProfileClassToken = ReplicaService.NewClassToken("PlayerData")
local ProfileStore = ProfileService.GetProfileStore("PlayerData", SaveStructure)

local DataService = Knit.CreateService {Name = "DataService"}

function DataService:GetReplica(Player: Player)	
	return Promise.new(function(Resolve, Reject)
		assert(typeof(Player) == "Instance" and Player:IsDescendantOf(Players), "Value passed is not a valid player")

		if not Profiles[Player] and not Replicas[Player] then
			repeat 
				if Player then
					wait()
				else
					Reject("Player left the game")
				end
			until Profiles[Player] and Replicas[Player]
		end

		local Profile = Profiles[Player]
		local Replica = Replicas[Player]
		if Profile and Profile:IsActive() then
			if Replica and Replica:IsActive() then
				Resolve(Replica)
			else
				Reject("Replica did not exist or wasn't active")

			end
		else
			Reject("Profile did not exist or wasn't active")
		end
	end)
end

local function PlayerAdded(Player: Player)
	local StartTime = tick()
	local Profile = ProfileStore:LoadProfileAsync("Player_" .. Player.UserId)

	if Profile then
		Profile:AddUserId(Player.UserId)
		Profile:Reconcile()
		Profile:ListenToRelease(function()
			Profiles[Player] = nil
			Replicas[Player]:Destroy()
			Replicas[Player]= nil
			Player:Kick("Profile was released")

		end)

		if Player:IsDescendantOf(Players) == true then
			Profiles[Player] = Profile
			local Replica = ReplicaService.NewReplica({
				ClassToken = PlayerProfileClassToken,
				Tags = {["Player"] = Player},
				Data = Profile.Data,
				Replication = "All"
			})

			Replicas[Player] = Replica
			warn(Player.Name.. "'s profile has been loaded. ".."("..string.sub(tostring(tick()-StartTime),1,5)..")")
		else
			Profile:Release()
		end
	else
		Player:Kick("Profile == nil") 
	end
end

function DataService:KnitInit()
	for _, player in ipairs(Players:GetPlayers()) do
		task.spawn(PlayerAdded, player)
	end

	Players.PlayerAdded:Connect(PlayerAdded)

	Players.PlayerRemoving:Connect(function(Player)
		if Profiles[Player] then
			Profiles[Player]:Release()
		end
	end)
end

function DataService:KnitStart()

end

return DataService

Game


Controllers

Controllers are singleton provider objects that serve a specific purpose on the client. For instance, a game might have a CameraController, which manages a custom in-game camera for the player.

A controller is essentially the client-side equivalent of service on the server.

Example
local Knit = require(game:GetService("ReplicatedStorage").Packages.Knit)

local TestController = Knit.CreateController{
	Name = "TestController",
}

function TestController:KnitInit()
	print("Test Controller Initialized")
end

function TestController:KnitStart()
	print("Test Controller Started")
end

return TestController

Server <> Client Communication

Knit allows you to make remote events without really making remote events and the many annoyances of using WaitForChild and invoking events.

Let’s make a remote event that we can listen to. Anything in the client table will be replicated to the client this is where we place events and functions. We can also have a function that can be called by the client.

Server
local Knit = require(game:GetService("ReplicatedStorage").Packages.Knit)

local TestService = Knit.CreateService{
	Name = "TestService",
	Client = {
		SomeThingHappened = Knit.CreateSignal(); -- Create the signal
    }
}

function TestService.Client:GetPoints(player)
    return 0
end

function TestService:KnitInit()
	print("Test Service Initialized")
end

function TestService:KnitStart()
	print("Test Service Started")
end

return TestService
Client
local Knit = require(game:GetService("ReplicatedStorage").Packages.Knit)

local TestController = Knit.CreateController{
	Name = "TestController",
}

function TestController:KnitInit()
	print("Test Controller Initialized")
end

function TestController:KnitStart()
	local TestService = Knit.GetService("TestService")

	local function SomeThingHappened(points)
	    print("My points:", points)
	end

	TestService:GetPoints():andThen(PointsChanged)
	TestService.SomeThingHappened:Connect(SomeThingHappened)

	PointsService.GiveMePoints:Fire() end

	print("Test Controller Started")
return TestController

Components

Bind components to Roblox instances using the Component class and CollectionService tags.

Components can be placed in the server or the client depending on what it is…

Server/Client
--You need to have the tag editor plugin here is the link https://www.roblox.com/library/948084095/Tag-Editor

local Knit = require(game:GetService("ReplicatedStorage").Packages.Knit)
local Component = require(Knit.Util.Component)

local MyComponent = {}
MyComponent.__index = MyComponent
MyComponent.Tag = "MyComponent"

-- CONSTRUCTOR
function MyComponent.new(instance)
	local self = setmetatable({}, MyComponent)
	-- Add more properties to self before returning like self.TimeCreated = tick()
	return self
end

-- OPTIONAL LIFECYCLE HOOKS
function MyComponent:Init()--> Called right after constructor
	local instance:Part = self.Instance
	instance.Color = Color3.fromRGB(51, 255, 0)
	print(MyComponent.Tag.. " has been applied to ".. self.Instance.Name.. " on the client")
	-- Self.Instance --> instance with tag 
end        

function MyComponent:Deinit()--> Called right before deconstructor
	-- Self.Instance --> instance with tag 
end                   

function MyComponent:HeartbeatUpdate(DeltaTime)  end    --> Updates every heartbeat
function MyComponent:SteppedUpdate(DeltaTime)  end      --> Updates every physics step
function MyComponent:RenderUpdate(DeltaTime)  end       --> Updates every render step

-- DESTRUCTOR
function MyComponent:Destroy()
	--> Clean up connections or better yet use trove in the knit util folder
end

return MyComponent

Miscellaneous Game Development Tools
https://www.roblox.com/library/5012883501/SwapUI

https://www.roblox.com/library/1614059092/Instance-Serializer

https://www.roblox.com/library/4987562465/InCommand-versatile-adaptable-command-execution

https://www.roblox.com/library/3619526449/Get-Object-Path
https://www.roblox.com/library/4369062118/Easy-Crop

42 Likes

I’ve looked at Knit a few times and still never really understood the appeal behind using it.

From reading the Knit Documentation & your Post, it seems like the core appeal of Knit is that it saves you time/confusion of having to create RemoteFunctions & Events.

You also mention

Which seems to be a benefit for below even the newest Developers. I’ve never seen a game that is made with one script, nor have I ever seen anyone recommend this on the DevForums, or YouTube.

I’m not trying to bash Knit, I’m mostly trying to understand how this can benefit competent Roblox Developers, who don’t face any of the issues you mentioned.

  • RemoteEvent & Functions aren’t complicated or much of a hassle to deal with, once you’ve worked with them for a bit.
  • If you’re writing an entire game in one single file, your time would be much better spent learning how to properly program.

Hopefully, I’m missing the actual benefits it provides, because I always love learning new things which make my life easier.

10 Likes

Yeah, personally not a fan because it just seems like it’d make codebases harder to understand (does this data come from the client or the server? what script does it come from)

Maybe because I’ve never used it (and the library I do use has been abandoned), I’m just blind to how obviously great this is, but I don’t see this as such a great thing, let alone something I need to use, like the title makes it out to be

Of course, if it works for you, use it, don’t let me stop you! But most of the reasons suggested in the OP can already be done with much simpler libraries & functions

9 Likes

I agree with what you said, and I wanted to add to it slightly.

Using this Framework could negatively impact you if you wanted to expand your team and begin working with others. Only a very small portion of the Community will be familiar with this Framework, so it’s basically adding a brand new barrier to entry when you’re looking for others to work on your project with.

Considering how minuscule the benefits of using this Framework seem to be, hopefully, people really compare those with the downsides before using it, or you could get really deep into a project and then regret it.

On the opposite end, this Framework doesn’t seem like it’s too much to learn, so people could definitely pick it up if they wanted to work on your project, but still would require time and effort.

The only similar ‘tool’ to Knit I’ve seen is Roblox-TS. If I was going to invest time into using a Framework, which would require time learning it all, I believe you’d benefit much more from investing that time into learning Roblox-TS.

Maybe I’m wrong about the benefits of Knit. I’m still curious and not sure what huge benefits this Framework provides. I made the slight comparison to Roblox-TS because it’s the closest thing I’ve seen in the community, which does actually provide significant advantages, but I believe it is also very different than Knit, which seems to be a very simple Framework in comparison.

3 Likes

I rly liked this post. I had been trying to understand knit for a while and it wud b great if u made a short tutorial on it.

2 Likes

From experience, Knit just slowed me down in development compared to just using RemoteEvents and normal scripts. It just over-complicates things imo (especially with its server-client communication model, which creates a mess of a stack trace with more required scripts).

3 Likes

I’m glad you made this. Knit is an awesome framework that I use in every project I work on.

I made a fairly complex trading system without knit once, it was a painful experience… I had like 10+ line of code just referencing remote events and then some other mess. I remade the system in knit few months later and the code was much cleaner/easier to understand, implementation took less time and it worked better overall. Knit also comes with some useful utility modules like janitor, promise, signal, TableUtil, etc. They are essential to me and not having to manually insert each of them is rather handy.

I could go on all day but in a nutshell it’s a super helpful framework and I definitely recommend it to anyone.

3 Likes

Knit’s networking system is only one of it’s features. It is pretty powerful and gives you the ability to implement inbound and outbound middleware functions which you can use to drop requests or serialize data.

The real benefit that comes from using Knit is how the code communicates with each other; it turns more into a discussion about single script architecture vs having a million scripts everywhere. Knit is a powerful framework for single script architecture workflows.

Roblox-TS simply transpiles TypeScript into Roblox Lua and isn’t at all some kind of alternative to Knit. In fact, Knit is very popular among Roblox-TS workflows.

Hope that clears things up.

1 Like

Knit’s networking system returns Promises, so, you can implement your own system for catching errors!
Promises do have a pretty long chain in Knit, but I’ve found that they help me pinpoint exactly where these errors are happening in my code.

2 Likes

Just added the video to the post.

1 Like

I would have to disagree with your statement. As a developer who uses Roblox-TS, it isn’t a framework at all. It’s a compiler that converts Typescript into Roblox Luau. Which, of course, does not stop you from using Knit within Roblox-TS.

The benefits of using Knit are apparent once you use it. It follows the idea that the main scripts controlling your code are singletons (Controllers and Services). Those who have previously used AeroGameFramework (or Flamework for Typescript users) should be somewhat familiar with this concept. However, the client has access to certain functions and data the developer intentionally exposes within a service, which allows the client to call server functions far more intuitively. Knit follows Roblox’s style of Singletons, and you can retrieve services and controllers using:

// Service:
Knit:GetService("ServiceName")

// Controller:
Knit:GetController("ControllerName")

There are also in-built packages that would be very useful for developing (such as Janitor, signals, table utility, and more). It’s also much easier to read as it splits your game into very readable singletons. I’d recommend any Roblox developer that codes in Lua to use Knit.

However, as a Roblox-TS user, I prefer Flamework (another framework) over Knit as it is designed explicitly for TS and follows TS guidelines better.

5 Likes

cc: @TayIorRobinson
Hopefully the reply I made above can explain the appeal of Knit to many developers.

1 Like

Many developers don’t need to see the appeal of Knit as it just makes creating stuff more complicated. A basic few lines of code can make client-server connection simple and easy without needing the clutter of a whole “Game Framework” to do it.

A small example of how simple it needs to be:

local functions = {}
RemoteEvent.OnClientEvent:Connect(function(called, ...)
	if(functions[called])then
		functions[called](...)
	end
end)

local FireEvent = function(call, ...)
	RemoteEvent.FireServer(RemoteEvent, call, ...)
end

This is Roblox we are talking about, almost everything you can make can be done simply in a few lines of code. This is why I never understood the appeal of massive frameworks when most developers are not creating huge, over the top games 99% of the time.

Few other opinions that I think share the same feeling.

td:lr This most likely will not appeal to many developers on a platform such as Roblox.

4 Likes

I can understand the sentiment. Knit does not make stuff more complicated, though, so unless you’re making a very bare-bones basic game, the Knit framework doesn’t affect code complexity as much as you may believe.

Regarding networking, the snippet you provided honestly looks less appealing than if one was to design it with Knit.

Ex, Knit Service with networking:

local Knit = require(game:GetService("ReplicatedStorage").Packages.Knit)

local MyService = Knit.CreateService {
    Name = "MyService";
    Client = {};
}

function MyService.Client:CallableFunction()
end

function MyService:KnitStart()
end

function MyService:KnitInit()
end

return MyService

That’s precisely one of the reasons many developers like Knit. The exposed framework is not nearly as massive as you might imagine! Knit is almost excessively unopinionated and can just be used as a utility.

I must also disagree with you there, Knit is getting a minimum download of dozens weekly. Even reaching up to 280 and more! This is merely the downloads for the Typescript version as well, if we also count the downloads of the main package, I’m sure there will be an impressive amount of developers using Knit.
image
I do know that there is a possibility of re-downloading and etc, but even if we only count 25% of the total, it will still remain a sizeable amount.

To sum it up, while some of the structuring benefits are less evident when working on more simple games, there aren’t any drawbacks to using Knit either!

3 Likes

I already said Roblox-TS wasn’t the same as Knit at all

Even with your explanation of Knit, I still cannot see why it’s worth a competent Developer’s time to learn the entire Knit framework, to simplify already simple things.

Lets looks at the normal vs Knit example

Normal

Knit

The normal really isn’t much different than the Knit one. It’s not significantly larger than the Knit one, (it’s actually smaller).

I also believe you’re extremely wrong here. To say Knit has absolutely no drawbacks is either ignorance or disingenuous.

Frameworks that aren’t extremely simple and are fully implemented into your Codebase, will certainly require any new Team Members you invite to take their time and first learn how to use the Framework.

Since you seem so passionate about Knit, maybe you should try explaining further how it would actually help Developers. The previous explanations you created still didn’t make me see any advantages at all from the Framework. It feels like you’re pushing Knit as being a revolutionary Tool for Roblox Devs, like Rojo, and for that to be true, Knit must do a much better job at explaining what benefits it can actually offer the majority of Roblox Developers.

2 Likes

Disclaimer: I am a fan of the creator of Knit and have nothing against the framework itself.

I am not sure of the full capabilities of what Knit can do but I do have some comments regarding networking. Roblox already massively simplifies and abstracts stuff dealing with the network. Frameworks that wrap this system could arguably make it more complicated than it has to be.

I am also sure other people can agree with me that they don’t like wrapping their entire game in a framework in general (depends on what people consider a framework).

Again I have nothing against any frameworks or their creators, I just have opinions on if they are actually of use to myself. If anyone is interested in using Knit there is no shame or issue in doing so.

4 Likes

I’m pretty sure you did indeed imply that Roblox-TS is a framework. As shown here:


In regards to this point, don’t forget that you still have to instantiate events and the events very loosely organized. While in Knit, the only code needed to make a remote event is:

function MyService.Client:CallableFunction()
end

The rest of the code I’ve shown are just rather simple bootstrap code that may be used for more features.


Please remember to keep your tone polite here. I say that Knit has absolutely no drawbacks is because it takes only 2 minutes for experienced developers to understand how to use someone else’s Knit code in theirs. Not to mention that new team members don’t even necessarily need to know Knit to assist development progress (As previously mentioned, whether something should just be a script or a Knit singleton is completely up to you)


I’m afraid you misunderstood my intent here. I’m pushing Knit as a useful and optional tool for developers to use for organizing code and events. The usage (or lack of usage) of Knit purely depends on your personal preferences. I’m mainly explaining why people like Knit. Personally, I don’t even use Knit, I use Roblox-TS and Flamework to make my games.

3 Likes

I think one big takeaway from Knit is the components module. It’s very powerful and basically makes Roblox the source of truth for your code and manages state very well. It’s pretty much the same thing as Quenty’s Binders (and maybe with some add-ons, but idk) if you are aware of those.

2 Likes

It looks like you have removed the second video tutorial from YouTube, Do you have another link to it?

Dan

1 Like

He moved it to his main channel.

1 Like