Open joshuarobs opened 1 year ago
You can use the flecs documentation and manual for general flecs related questions.
The FlecsSubsystem in the project contains commented source code with 2 simple systems (the system that makes the corns grow and the system that copies them to unreal's ISM renderer) you can look at as a reference.
If you want something more in-depth you can check out the flecs space battle tutorial or the flecs C++ examples
Unfortunately, there's no tutorial series or docs on how to build off of this specific template, it was made more as a barebones minimal viable implementation for people who already have C++ and/or flecs/ecs experience just haven't used flecs with unreal before.
@PreyK Is FlecsTest
the folder we need to copy and paste so we can make our own modules from it? e.g. we can do FlecsMovement
or FlecsDamage
as custom modules. Or do we need to remove the Corn related functionality and put them into their own files? Because I'm trying the latter, but struggling to do so.
Its kind of confusing to me, because UFlecsSubsystem
seems to be doing 1) general Flecs things and 2) corn related things. It looks like its doing 2 things together, and I'm trying to split them up so I can make this more modular and so I can understand how the code works.
It would be nice to have a simple list of instructions on how to add your own modules, e.g.:
FlecsTest
folderThats just an example. I actually don't know what I'm supposed to do to extend functionality and to split them into different files. It seems like all I can do is just dump them all in the same file alongside the corn stuff, which doesn't seem optimal
FlecsTest
is the unreal project's name.
The FlecsTest
folder contains the "Game" C++ code, This is the main game module where all your game-related C++ code goes by Unreal convention.
The FlecsLibrary is an unreal library that gets linked to your "Game" library, in this case, FlecsTest
, so you can use it in your Unreal project.
The FlecsSubsystem
is an Unreal Engine world subsystem that in this case is responsible for everything flecs related. (corn logic is flecs related as it's implemented as a flecs system)
There is no go-to way to do this, you can split it out into different files based on what are your working conventions and your project requirements but it's mostly just boilerplate. If all you want is pure entities, components, and systems all you need is (based on the corn example):
Entity:
//make a new entity, add the FlecsCorn component
auto entity = GetEcsWorld()->entity().set<FlecsCorn>({0});
Component:
struct FlecsCorn
{
float Growth;
};
System:
//this system processes the growth of our entities
auto system_grow = GetEcsWorld()->system<FlecsCorn>("Grow System")
.iter([](flecs::iter it, FlecsCorn* fc) {
float GrowthRate = 20*it.delta_time();
for (int i : it) {
//if we haven't grown fully (100) then grow
fc[i].Growth+=(fc[i].Growth<100)*GrowthRate;
}
});
With the ECS logic, everything you want to implement you need to break out into Entity
Component
and System
Component
only stores data, it doesn't have logic.
System
iterates over all the relevant entities and processes the Component
's data, System
is responsible for your logic.
Entity
is well, an entity that can have Component
s
ECS
is a purely functional programming concept, you don't "have" FlecsMovement
or FlecsDamage
modules, classes, etc..
You would have for example
Entities
:
//make a new entity, add DamageComponent component
auto entity = GetEcsWorld()->entity().set<DamageComponent>({0});
Components
:
struct DamageComponent
{
float CurrentDamage;
};
And systems
:
//this system "slowly" heals the damage on our entities
auto system_heal_damage= GetEcsWorld()->system<DamageComponent>("Damage Heal System")
.iter([](flecs::iter it, DamageComponent* dc) {
float HealRate = 20*it.delta_time();
for (int i : it) {
//if we haven't healed fully (damage>0) then reduce damage
if(dc[i].CurrentDamage>0)
{
dc[i].CurrentDamage-=HealRate;
}
}
});
And you can interact with them, for example add some damage to an entity:
auto GivenDamage = 50;
GetEcsWorld()->entity(YourEntityId).set<DamageComponent>({GivenDamage});
Edit:
As for where it all goes it's completely up to you.
You could make a world subsystem that's only responsible for handling the flecs world and adding entities and make FlecsDamage
as a separate file where you define all your Components
and Systems
that are responsible for the "damage".
You could also put all your Components
in one file (like a Components.h
) and all your Systems
in a separate file and that's a completely valid approach too.
If you only want to use flecs for one specific part of your game (like growing a lot of corn) you could make one world subsystem that handles everything related to that specific part (like in this case corn)
It's more like a coding convention problem than an optimization problem, all the above examples will run equally fast.
I wish the readme would give an idea on how and where to add new systems, so you can build off this template, since I'm new to flecs and I don't know where to start to add my own functionality