When You Can't Use Unreal Engine To Make A Game
Вставка
- Опубліковано 28 чер 2024
- Brilliant link to get 30 days free and 20% off an annual subscription
brilliant.org/JamesLambert/
I teach you principles that I have learned over the years to help you succeed in making your own game engine when you can’t use out of box engines like Unity, Unreal Engine, and Gadot.
Patreon
/ jameslambert - Наука та технологія
The more mature I become as a programmer, the simpler the code I write
The more mature I become as a programmer, the better code I can make chatgpt generate XD
@@Evgeny1 I've found myself settling into descriptive, almost functional patterns, over time. Tends to read more like telling the computer what I want it to do, rather than how to do it.
It's the bell curve of experience wojack meme
Looking at my past work, yeah that tracks! LoC isn't a good measure turns out
Same happens to writers
As someone that's been writing games without engines for many years, I can say that all of this is excellent advice. Component systems in particular are *the* way to go for scaleable, dynamic, complex behaviours without spaghetti appearing in the code logic. The 'make a game, not an engine' advice is superb too: avoiding over-engineering is essential to make headway in this space.
there are so many people on the internet spreading bullshit about how "oh you should never make your own engine" "if you want to make a game you should only use one of the big popular engines", it's so absurdly refreshing to just see a video going "i make my own engine, here's some tips on how to do it" lol
It's a good advice for 99% of the people trying to make a game. Finishing a game is extremely hard, adding a game engine from scratch multiplies the time needed to finish it by a factor of 3 at least.
If you want to finish all your games or are trying to get a job in the industry then don't code an engine. If you like to tinker and have total control over your game then make an engine
@@ramoncf7 Yeah I wrote a 3d renderer and model loader in C++/OpenGL for an assignment for college (it had to have geo with normals, diffuse and specular textures, the world needed multiple light sources, a 3d user controlled camera) and just making that was a nightmare (we had 6 weeks and I had other classes and a job which didn't help!). Imo 99% of people who want to make a game would give up way before actually making anything besides a 3d camera in a blank void with some boxes and triangles cuz like... if that weren't a graded assignment I would of stopped after making a triangle spin around or something.
@@orangy57Wouldn't having made a decent engine be good on a résumé?
Ok, guess it depends on the capabilities, considering how simpler games can run on horrid spaghetti that makes god weep.
(Note that I'm just a random person on the internet with very little game dev and zero industry experience.)
literally the only sensible sponsorship from brilliant on youtube, even for some maths education channels - why would you need an online education course - but for programming, specifically for n64? you'd definitely need to not just grasp, but also master those concepts
For anyone wondering: the approach that unity uses is generally called Entity Component System (ECS), and it's not even associated with OOP, rather tending to be used alongside data-oriented design (the approach could be summarized as: for every subsystem responsible for a given component, build a flat array of the relevant data from the relevant entities, that is then simply looped over without any pointer chasing)
I love how he shows examples to explain the concepts he talks about
You're by far one of the coolest people out there.
You're not the only one critical of object-oriented programming. I've heard that many authors of high-performance game engines eschew object-oriented programming. Instead they do what's called data-oriented design. They say it is more performant because it reduces memory accesses and improves cache locality. In some cases, it makes it possible to use SIMD instructions.
I liked the old thumbnail and title better because it was more understandable
Yooo, the king of the N64 is back! 👏🤠
You always give off “smartest and most relaxed college professor” vibes. Always great videos!
I was looking for a way to code games on my phone so I could hopefully shift mindless reddit scrolling time into game dev. I found a simple text editor that would let me write html and js with syntax highlighting and run it in the browser. Then I just started writing. It took maybe a couple of hours to have an interactive thing and then a handful more before to have a simple game.
Technically I guess I'm writing a game engine. I feel like people have a warped idea of what that means though because of things like unity and unreal. The advice to focus on making the game and only develop the engine features as you need them is excellent
The rules mentioned sounds a lot like "The Rules of Programming" by Chris Zimmerman, a tech lead for Suckerpunch, making Sly, Infamous and Ghost of Tsushima 😅.. can definitely recommend
The last time I asked a game dev what tips they had in regards to making a game engine was... (assuming you are doing to develop a game, and not just for the sake of making an engine)
Dont...
Or only do it if the game you want to develop has a requirement that cannot be reasonably met by current engines. Using Noita as an example, due to every pixel being simulated stuff.
Really good tips in this video! I agree that it's very important to just make something work, instead of worrying about issues you don't even have yet. Obviously it's good to think about the future, but I have personally noticed that it honestly usually isn't even too much work to rewrite certain parts when problems show up, even if the code is badly written.
Excellent discussion! I have, as many many of us have, definitely spent more time writing the game engine instead of writing the game. It always feels like if I get that out of the way first I'll be able to breeze through writing the game. TBH, your mentioning that has kindled a small bit of motivation to work on a personal project that's been sitting idle for a few years now...
Though, I will bring everyone back to a critical point from the Zen of Python:
> There should be one-- and preferably only one --obvious way to do it.
> Although that way may not be obvious at first unless you're Dutch.
I remember an old Gamasutra article talking about a game having a lot of issues with its physics engine. A new person came in and made the observations that even though it was a 3D game, all the collisions could be done in 2D instead. The new code was simlle and efficient and got the job done. I think about this kinda thing a lot when people talk about using off the shelf game engines. How much is your engine doing that is unnecessary for your game?
I'm not sure I want to go back and refactor my code but this makes a lot of sense. Especially the entity ID system.
Sounds like Bevy’s ECS model. Entities, Components, Systems.
Welp, now I got to look at refactoring parts of my Pico-8 game. Half of my systems use references to find entities and the other use IDs. Kind of a mess 😅
Writing re-usable code is hard, because you don't know how you'll want to re-use later, and you're likely to end up with code that's annoying to use twice. It's much easier to write the same-ish code twice, and compress them into one if it makes sense.
Pointers are Ids. The only difference is that pointers have byte granularity. Pointers can be set to null. If we divide the memory too down as on a C64, we can use pages. So a byte only. Every indirection is bad on RAMBUS. If you have typed arrays and use them as pools, you can get away with smaller pointers (typed indices). So gameobjects with references fit into cache or registers.
Malloc and free work the same for ids and pointers. You go through your pool and search for a free (deleted) slot. Search while you vsync.
Pointers are IDs the same way pointers are also optional types. The key difference is that if you hold a pointer, there is nothing stopping you from dereferencing it, whereas if you only hold an entity ID, you have to pass it to a system that enforces checking before you can anything with the referenced object if it even still exists.
@@MopeyMoon I never had problems with invalid pointers. I guess I used too much Java, C#, and smart pointers in C++. Often I end up with double links because I need the cascade effect right there.
With IDs and an in memory database we can use a b-tree to manage memory and defragmentate it. In Java H2 is such a Database. For C there is SQLite?
So IDs would live forever? Sounds like a memory leak to me.
@@ArneChristianRosenfeldtIDs are just integers that don't have any lifetime associated with them, so I don't see how that could cause a memory leak.
For example, say that entity 1 has an "attacking_id" field with an ID integer of 2, then it doesn't really matter whether entity 2 has already been killed or not in terms of memory leakage
@@sanderbos4243 but then you could just as well use pointers to attack types. Is this about serialisation? I mean, in code you try to avoid using “type1”, but you write “low poking attack” . The compiler then can either use enums to compile this to IDs , or static fields to compile to pointers.
@@ArneChristianRosenfeldt When I used "attacking_id" as an example, I meant "what entity ID am I attacking?", not "what type of attack am I performing?". It doesn't really matter whether it's an int or a pointer or a double, but the point is just that you don't want to have it be a pointer to a raw memory location that you dereference. The blog post "Handles are the better pointers" goes in much greater detail of the many advantages of it, so I highly recommend checking that :)
appreciate the insight! excited to see more from your new project
big fan of your strategy game mission lost control.
such good advice, and explained so well. thank you.
i probably will never understand why people care this much about the n64, but i'm glad people are working on it anyway.
Great advice! Thanks for making these videos!
It is perhaps noteworthy that the components pattern mentioned around 3:40 is also possible in C, even though C is not an object oriented language.
Simply by using instances of structs and pointers. E.g. have a struct GameObject, which has pointers of structs Damageable etc. If the damageable pointer is NULL, the gameobject doesn't have that component and so on. In this particular case of an N64 game this exact implementation of the pattern might be inefficient due to memory limitations though (not sure).
I'm not a programmer and I understood what you said. Thank you! And looking forward to more of your game updates.
"You might be optimizing code that only gives you nanoseconds of improvement."
Kaze Emanuar: And?
The second rule in my opinion is the most important rule in all of programming.
At my work, we have a colleague who was tasked with making an automation script for our infrastructure, related to our monitoring.
I had a couple other colleagues berate him with feature requests. I kept telling him, if a feature is not needed for the usability of the task, it can be made later.
I am now re-writing it from scratch because it became a complex unmovable and unusable spaghetti code with hard-coded values that were inflexible, and dependant on external systems.
I wrote the entire thing in 3 classes, and can be configured with 1 configuration file.
I have added 2 features since, which allow us way more flexibility and not only automate what needed to be automated, but we can extend the original capabilities of what we were using.
Simple, is better than capable.
Hello, what practices are you planning 🎉
6:27 to be fair, the number still is a reference, its just a managed one.
That is true
Yeah stale refference manipulation is what breaks OOT its serious stuff
would love more videos kinda like this :)
I'm just a tinkerer who fell into the hole of writing an engine. It's really good! Anyway I wanted to write something new and I banned myself from my own engine, just use something that exists and get on with it. I've made more progress on my ideas than I ever have before lol
If you get rid of stale references you at least need to make sure that you forget to cap backwards moving speed
One tiny but smart thing I picked up looking at other game engines is that EntityID can just be pointer. No need to keep a special count. On modern hardware you might incur a pointer indirection and caching issue but even then sometimes it's no biggie.
Nice video james. I want to get into n64 programming. I am an experienced c programmer but know nothing about n64 programming or graphics. Is the official sdk running on xp a good way to start? Thx
Nice one.
Out of curiosity, why do you hold a microphone stand that was meant to put on at able in your hand, bashing the cable into it? Is this programming ASMR? 😀
More like a reverse ASMR. The constant noise was very distracting thoughout the video.
That is very much like my current ECS works (in PHP. OOP is definitely overrated) 👍🏻
I wish i would've had that advice earlier, I've always added more and more features 😅 Though, i have developed that behavior because i kept rewriting everything in my code, especially APIs
Cool! Was this your main job?
My full time job is web development but I have been making games as a hobby for a very long time
This is the way. Just having a main job and making games on the side, web development specifically sounds like a drag, like working a job where you just make excell sheets all day.
yeah i try to stick to C and think around stuff like OOP. While people love C++, C#, and Python; C (to me) allows the most flexibility in the long run regardless of project.
My bonus tip would be: know whether you want to make a game or a game engine. Sometimes you just want to make a game engine and that's fine. That can be a lot of fun as well. Just make your goals clear.
A question about one entity doing something to another one (eg. damage). Is an unit authoritative enough to direct apply damage to another one? Or that's up to another system?
I would say that depends on what your game needs. I found it typically works fine for one actor to directly apply damage to another.
I'm not sure if you can publish a game that used proprietary engine on steam without contacting them directly...
do you think a game like Zelda: Phantom Hourglass for the NDS would run on N64?
The games I write for retro systems almost always end up using a "game object behaviour" system. Then there is also rendering and audio systems to implement too.
I'm a data scientist who uses high-level languages, and I want to learn a lower-level language for game design as a hobby. I can't decide between C and Rust. Thoughts?
Rust is amazing but it takes a long time to get good at managing all those types. Maybe start with C since its surface area is a lot smaller, then when you got the hang of pointers and stuff you can start with Rust. But of course it depends on what your level is now and how much time you got to spend. I would go straight to Rust again, coming from node/npm i feel right at home with cargo and crates.
If you're coming from high level languages, I would probably recommend jumping straight into Rust - it has one of the best type systems you will ever use. Rustlings is a great starter resource, though there are of course plenty of other ways to learn
I haven't used Rust, but I've heard from other game developers that it's slow to iterate and experiment in Rust because of things like the borrow checker that try to make you program things "correctly", when what you want in game development is the ability to program things stupidly at first so you can rapidly try things out. Someone wrote an in-depth article on this called "Leaving Rust gamedev after 3 years".
I would offer two alternative recommendations: Odin and Zig. Both are more powerful than C but not as complex as rust.
where'd you get the shirt??
I wish i had the skill, i’ve been trying to re create all the effects and texturing techniques for modern game engines and making encoding and light baking tools in blender
we love ECS in this house
Wouldn't bitflag array of let's say 16bits (elements) be simpler and quicker?
In the specific examples he showed here that's absolutely the way to go, assuming you won't need more than 64 bits. In terms of ECS, he explained tagging stuff, but you usually also want to be able to store information in the tag, which is called a component. So think of having a "health" component that you can slap onto anything and just contains a double.
btw, what do u think about embedding a scripting lang, like Lua, in a N64 environment? Would that even be possible? 🤔
What do you want to Skript? Events in the level?
maybe possible but it would really be a better idea to create a custom scripting system for the specific purpose
embedding lua into an n64 game is overkill imo
@@randomcatdude the Lua runtime is rather compact, plus it has a nice C interface. It would be much easier to make the mentioned entity system in a dynamic type lang, than in C
@@Raspredval1337 and we be slow as hell. Static types give you speed, especially in an Array.
@@ArneChristianRosenfeldt maybe, since the N64 bottleneck is memory access and dynamic type langs add significant memory overhead. Still, it might be ok for some tasks. Plus, it can be as performant as C code with a JIT compiler.
And now to make it scalable use a message queue paradigm 🤣🤣
Edit: I'm mostly joking because I don't know what N64 systems are capable of and most of my game dev knowledge comes from server-side code. I'm nevertheless curious if zeromq or the like can run on N64. Tho given that N64 seems to be single-threaded I doubt there's much efficiency to gain here, except maybe to simplify the code required for batch processing of multiple events as an optimization.
Is it possible to hack the processor on a real Nintendo 64 console and increase the frame rate per second like MiSTer FPGA does? turns on the Turbo BOOST
If you ever need a writer for a game I'd love to send in some work as an audition! 😁
Send me a message on discord and we can talk. I don't have a huge need for writing right now as I am still working on gameplay mostly but I wouldn't mind the help later on.
lambertjamesd#3921
@@james.lambert Awesome! Thanks for responding! I couldn't find a way to message so I sent a friend request. I hope that's okay, I've never really used Discord before 😅
I like the animations in the untitled game.
To be fer the are many stuff in game engine like unity that you forsh to use,
That you don't have to use in every component if you make your own game with your own engine,
For the transform many system like 2D sounds don't need transform in the order to work,
This just only one off the multiple examples
The Truth game engine are great and easy to work especially wean you Solo developer like my self and try to make big project,
However the have very specific architecture and if your trying to make big project like I did you may end up found the limitesion those software's have.
For example I'm using unity to make this fps game and I have already found multiple limitesion this game engine have.
My tip for writing a game for a limited system is to A) don't do it B) if you really insist then use one of the open source engines such as Doom [1-3] or Quake [1-3] and go from there.
However, I do completely disagree with you regarding object oriented programming in C. You absolutely can do it and I do it all the time. There are only two concepts in programming that you should always say no to using and that's recursion and recursion. For all else, moderation is the key. Use a moderate amount of the concepts, only as they apply to the problem you're trying to solve. Towards that end, you absolutely can create an object system for your game engine, but if you're targeting an N64, maybe consider something much more simple.
You could potentially use a pool of pre allocated data in an array and use their position in the array as entity id, then have a bit array of the same size indicating whether a given entity is in use or not, thus avoiding the hashmap look up. In c you don't have classes but you still have structs, which are essentially the same thing, only that you would have the methods/functions operating on a struct outside and no inheritance which is looking every day more like a good thing really. I'm just rambling out loud in case anyone didn't know this XD
Why are your structs all the same size? Any strings?
Sounds a lot like an archetype ECS :P
4:23 HOT TAKE!
(I agree!)
Why do you think so? Genuinely curious.
I always find it painful to see how many massive budget games are still just made with the Unreal engine.
These games have so many resources yet they're still not building an engine that would specifically serve the game they're creating. I really wonder how many unnecessary calculations are constantly being made.
"Write reusable code" conflicts with "only solve problems you have right now" and "keep it simple." The desire to write reusable code is what causes writing a game engine instead of a game.
The way I avoid this is by extracting reusable code. I write code without thinking about reuse, and if I notice duplication, I remove it by refactoring. This is easy to do in the refactor step of the Red-Green-Refactor TDD loop.
Well, "keeping it simple" is hard. And "writing reusable code" is hard, so that you have then a simpler time ;)
Tips for making your own game engine: don't.
🤣
out of bounds, is 6tf UNDER OUT OF BOUNDS
Can I get those 30 days free in a bag for later, please?
Well first you gotta know how coding works...
Hence I’m not making my own engine
OOP is overrated. *gasp* Yes. Yes it is.
You can do object-oriented programming in C. It's an abomination, but it's possible.
You made C++ sad.
man described ECS (Entities-Components-Systems) and complains at not having OOP, for some reason
game objects follow an oop behaviour tho. ecs is basically just game objects but without the class component. though they're inherently a completely terrible idea both implementations for a game on the n64 since memory bandwidth is awful at best.
@@snesmochaRamBus goes vroom. C structs and arrays are localised. Align to 16 byte cache boundaries. The bad thing about MIPS is that it blocks on a cache miss, while AtariJaguar only blocks when we access the register which we load to.
@@snesmochaECS is not inherently OOP, nor is GameObjects. At least based on most metrics of OOP you can go by, clean code, solid, filled with inheritance etc. However, it is correct that ECS can have a performance impact as nothing beats a linear array of cache friendly memory. That's why Archetype based ECS stores things in section of linear memory (which his is currently sadly not which is okay because of what he calls rule 2). ECS is especially good for a middle strategy approach. That is, in the beginning linear array is easiest to program, then when it gets hard to maintain, go ECS. At some point performance concerns hits, and you pull some of it back. Thus the reason I'm calling it a middle strategy