Creating my own framework

I plan this framework to be build customly for my game (meaning it is not barebones).

I’ve been wondering about things like networking, intellisense and structure (such as MVC).

If you have built your own framework or have any advice/ experience you want to share please do!

Thank you.

2 Likes

Im currently trying to develop my own framework to and ive been having a lot of fun making my intellisense replicate closely to how roblox does it ive also been working a lot with type checking and stuff like that

Also ive been using a loader sort of model where you have two main scripts (one for the client, and one for the server) that loads and initalises a bunch of core modules.

the framework the you decide to develop is basically all up to you and how you work in studio. I think that It should be built around your workflow so that it is easy to add onto it and understand after coming back from breaks

Goodluck with ur framework :face_holding_back_tears::face_holding_back_tears:

I’m used to writing ModuleScripts for every little project i make, but the general requirement I frequently ask is whenever a feature is gonna be reused in other parts of the project.

Recently i’ve been making a Procedural Texture Generation plugin and I started using a modular structure in order to make the Node system work as I wanted.

As an example, if you plan in making a combat system where stats modifiers or (de)buffs is a core feature, you’re guaranteed going to make a module which handles said feature, otherwise Humanoid:TakeDamage() is all you’re gonna need.

Modular Approach its the best, as for netwroking, its just realtime remote creation and utilization, nothing special, I kinda got inspired by Knit, but more intellisense friendly, instead of .GetService() its just require()

Good questions.

As for intellisense, beware custom module requirers (i.e. something like local DumbService = loader.require("DumbService")) to circumvent typing out the actual path — autocomplete won’t work for that. So, while a lot of custom frameworks include a module loader, I wouldn’t recommend it, especially if you value your intellisense.

As for networking, you can either create your own networking module or use one of the several already out there (BridgeNet, ByteNet, Red, NetRay, Replica, etc.). There are different benefits and drawbacks to each of these; you just gotta choose the one you like best. Alternatively you can make your own. That’s the option I went with — it took several iterations to make something I REALLY liked, but as someone who’s gone that route, I can confirm that once you reach the sweet spot it’s really nice to have a tool that complements how your brain works. Your decision though — you gotta balance between performance, ease of use, and feature support (i.e. is it a glorified remote event wrapper or a replicated state manager with custom serialization and middleware support and all the bells and whistles).


As for structure, gather around children and pay attention:

Don’t lock yourself into any one structure/paradigm with your framework.

Different games, and different systems within a game for that matter, are solved better with different paradigms. Use OOP when OOP makes sense. Use ECS when ECS makes sense. Use event-driven when event-driven makes sense (which is most of the time but yk). If you want to create utilities for any given structure or paradigm, go for it, but I’d caution against making anything that makes it too hard to deviate from any given paradigm.

Also i’m not gonna lie to you my “framework” is just a collection of utility modules and loose conventions for game structure. That’s why I can do anything I want with it — it provides tools to support the patterns I like to use, but doesn’t lock me in to anything.

2 Likes

You have your own intellisense? Is that using exported type definitions? Or are you directly requiring the module and exporting types through there?

I see. That does actually make sense as I have some modules that serve nothing besides like 1-2 module scripts.

1 Like

Personally, a modular structure is a little too “loose” for me. I will admit that sometimes I have very modular systems that can be easily forked and reused by vastly different components. However I like things to be “hard coded” so I don’t have to always figure this and that out and can just code it while only thinking about the functionality.

Instead of :GetController or :GetService I just created a table that constructs itself after every service and controller has Initialized its functions and gone through the proper life cycle.

This makes requiring stuff a lot easier by just accessing the main framework module and calling .Controllers or .Services

Dude
image

I thought so. I just don’t really know a lot about networking (atleast advanced networking) and I’m an avid knit.createsignal abuser. Any advice on how to make your own?

My vision is to have a framework that does sorta “lock you” but only for convenient purposes. Obviously I’d make it so it could be easily modified for different games but I’m not really into the whole no definitive thing as I really like just coding functionality not questions.

local test = {}

--[[
    function notes

    <strong>param</strong>: describe what param does
]]
function test.randomFunction(param: any)

end

return test

having comments directly above your function gives it these cliff notes when you try using them

Ahhhh… I see.
When did roblox add that? I never noticed it lol

(Im accursed btw)

I found it while reading this devforum post that someone had sent me

Yes. My personal advice is to aim for simplicity. A simple implementation is good so that you can test it (you’re going to want to make SURE this thing works always). A simple interface is good so that you don’t hate your life when you’re using it down the road.

  1. Decide what features you want. Middleware? Buffer serialization? Async requests? Unreliable remotes? All cool stuff, just keep in mind that it’s more to test as well as more complexity. Nothing wrong with that though if you’re willing to take on the task of figuring out how to get that to work.
  2. Decide what practices you want to promote and what practices you want to demote. For instance, I’m never a fan of the syncronous nature of remote functions, so I don’t implement their functionality in my networking library.
  3. Come up with a nice, simple interface for it. Keep in mind that you’ll need different interfaces for client and server. You could do this by having two separate modules, or you could have one module that returns a different table of functions depending on whether it’s being run on the client or the server. The interface for my networking module looks a little like this:
Network, on the client:
        .Send(eventName: string, data: any)
        .SendUnreliable(eventName: string, data: any)
        .Listen(eventName: string, callback: function)
        .ListenUnreliable(eventName: string, callback: function)

Network, on the server:
        .Send(playerOrPlayers: Player | {Player}, eventName: string, data: any)
        .SendUnreliable(playerOrPlayers: Player | {Player}, eventName: string, data: any)
        .SendAll(eventName: string, data: any)
        .SendAllUnreliable(eventName: string, data: any)
        .SendExcept(playerOrPlayers: Player | {Player}, eventName: string, data: any)
        .SendExceptUnreliable(playerOrPlayers: Player | {Player}, eventName: string, data: any)
        .Listen(eventName: string, callback: function)
        .ListenUnreliable(eventName: string, callback: function)
        

I find it to be nice and intuitive, and it does everything that I need it to do. Others might not like it so much. You have to design your module in a way that makes sense to you.

  1. Test. Make sure it works. You don’t want to build a whole game on it just to later realize it doesn’t work.

  2. If you don’t like it, change it. My first ever networking system sounded like SUCH a great idea in my head until i made it, used it, and then realized i hated it. So I changed it. Your first iteration is probably gonna be hot garbage to use. That’s fine.

  3. Dealing with performance — for most use cases, you won’t have to worry, IF you learn how to deny the good idea fairy (n. - a mythical creature that visits every developer, telling them “oooh, let’s add this!” and “Let’s do it this fancy way rather than this simple way!”). If you’re not sure, send a lotta stuff through and benchmark. Mayb use packet profiler or smt.

Those are just my amateur tips.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.