Unity Game Engine Modules/Projects

This topic is 733 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Hi there,

I recently started writing a small game engine, mainly for educational purpose not intending to sell it, but i do intend to use it (hopefully). I have got to a point where it has enough features to make a basic game, but i can't really think of any way to make a game with it without tying game-specific code to the engine.

I would like to have 3 projects setup like this:

·         Engine [Lib/DLL]

·         Game [EXE]

·         Editor [EXE]

Im not quite sure how to achieve this or if this is even the correct approach. I'm also not entirely sure, lets say this is the correct approach, whether or not i compile the engine into a static library or a dynamic library. I have read a little about static libraries vs DLLs but i'm still not sure which one would actually better as they both have their disadvantages.

The game world in this engine is composed of actors(Game Objects) which can have components attached to them, just like unity and UE4 (more so like UE4) and i would like to be able to easily define actor and component types in the game project.

Also please note i am hoping to make this cross-platform (the editor side of things at least, so i can edit the game on linux).

Share on other sites
I would like to have 3 projects setup like this:

Why? What are your goals in choosing this particular approach?

Share on other sites

Do what works for you, If you find a reson do have a DLL "engine" do a dll engine. If you need an externel editor write an editor, that it basically.

If you have 2 choices where you struggle to weight the pros and cons, we will be happy give you our opinion

Edited by imoogiBG

Share on other sites

Work on a game, and as you make that game and (hopefully) make others, you will be able to abstract your code in such a way that it will resemble a very small subset of a commercial engine, where you see things like having a solution for your editor and a solution for your game.  My best advice for you is don't let these things stand in your way from making a game, unless you just want to make an engine then thats a different story.

DR

Share on other sites

I know the common saying is to make games not a game engine, but there are some things that you may not learn by simply making games and i would like to learn about those things, which is why i would prefer to make a game engine.

I would like to have 3 projects setup like this:

Why? What are your goals in choosing this particular approach?

To have an engine that i can use to make basic games in and use as a test platform for learning new things (more specifically, low level aspects). It also means i can easily modify the engine while working on games.

Do what works for you, If you find a reson do have a DLL "engine" do a dll engine. If you need an externel editor write an editor, that it basically.

If you have 2 choices where you struggle to weight the pros and cons, we will be happy give you our opinion

I'm not sure which one will work better though. Ideally, i would like people who have had past experience with this to comment on their experience and possibly what mistakes they made and why they think their way is better.

Share on other sites

I know the common saying is to make games not a game engine, but there are some things that you may not learn by simply making games and i would like to learn about those things, which is why i would prefer to make a game engine.

That advice also means that if you make a game from scratch, you will automatically end up with an engine by the end, but if you make an engine in isolation, it will be a jack of all games and master of none.

As for DLLs vs static libs, use static by default and DLL when forced to. DLLs are a lot more complex and only give a few benefits - dynamic loading (and potentially reloading) ability to be replaced without recompiling the game (assuming the DLL was written in C, not C++...).

Having "engine" (shared, reusable) code in a library, shared by multiple EXEs is a fairly common approach.

Share on other sites

I know the common saying is to make games not a game engine, but there are some things that you may not learn by simply making games and i would like to learn about those things, which is why i would prefer to make a game engine.

That advice also means that if you make a game from scratch, you will automatically end up with an engine by the end, but if you make an engine in isolation, it will be a jack of all games and master of none.

As for DLLs vs static libs, use static by default and DLL when forced to. DLLs are a lot more complex and only give a few benefits - dynamic loading (and potentially reloading) ability to be replaced without recompiling the game (assuming the DLL was written in C, not C++...).

Having "engine" (shared, reusable) code in a library, shared by multiple EXEs is a fairly common approach.

So do you think, given what i said before, that it would still be more beneficial for me to try and create some specific games first?

Also if I were to start out compiling to a static lib and then find out down the line that I need to compile to DLL I would need to make quite a few code changes wouldn't I? also if iI wanted to have c# as the primary scripting language I would have to compile to a DLL wouldn't I?

Share on other sites

Make a list of logical operations that your engine would have to perform to create a game. Anything that is not related can be its own reusable library. Rendering and physics are the two easiest examples of libraries that should be decoupled, creating a reusable framework on which to build future titles.

Share on other sites

I know the common saying is to make games not a game engine, but there are some things that you may not learn by simply making games and i would like to learn about those things, which is why i would prefer to make a game engine.
What "some things" do you mean here?

If you don't use a game engine (that is, make a game from scratch) you implicitly have to implement a game engine as well. Depending on where you put the focus, you could "make a game" (where the engine is a sort-of by-product), a "game+engine" (try to consciously split specific game code from general code), an "engine+game" (where the game is a sort-of by-product), to "game-engine" (no game at all).

The more you shift focus to the engine, the more precise you need to know what it should provide. Do you have an understanding of what exactly the engine should do, ie what is its API?

If you know this exactly, you can at least in theory, build the engine. If you don't exactly know, maybe it's better to use a game as use case, and co-develop it.

To have an engine that i can use to make basic games in and use as a test platform for learning new things (more specifically, low level aspects). It also means i can easily modify the engine while working on games.
Euhm, not really.

If you have a common engine for a set of games, and you change the engine, all games die, and you have to fix all games for the changes that you make in the engine. In other words, the engine connects all games to each other, and you have to drag everything along with each change.

The alternative is to not share the engine between games, and just make a copy of the engine when you start a new game. It's a valid solution, depending on how bad you think it is to have some games use an older version of the engine.

Share on other sites
To have an engine that i can use to make basic games in and use as a test platform for learning new things (more specifically, low level aspects). It also means i can easily modify the engine while working on games.

This does not really have much to do with your stated organization of DLL/EXE/EXE though. Which means you're likely overcomplicating your approach for no reason. You have not stated a compelling reason why your project needs to use that approach, so you shouldn't (since it is a more complicated approach).

A static library will be significantly simpler to start out with, and can be easily adapted to a DLL if needed later. However starting out with a DLL, unless you're familiar enough with their production (and I don't think you are since you had to ask the question in the first place) will introduce a lot of boilerplate code, such as the necessity to expose a C-style ABI for your engine and do the appropriate marshaling and/or data hiding that gets in the way of accomplishing your actual goal of making something.

Share on other sites

Strictly speaking you can also live dangerously and take the approach that the engine DLL and the game simply need to be compiled with the same C++ compiler, and therefore allow working through C++ ABI directly instead of making a proper C API (C4 engine, and some graphics libraries like Ogre work this way.)

But I agree that dynamic libraries are a complication and the OP likely doesn't need them right now.

Share on other sites
Strictly speaking you can also live dangerously and take the approach that the engine DLL and the game simply need to be compiled with the same C++ compiler, and therefore allow working through C++ ABI directly instead of making a proper C API (C4 engine, and some graphics libraries like Ogre work this way.)

Very true, but at that point (in case the OP is interested) I feel like you are abandoning enough of the benefits of a DLL that you still have to raise the "why bother" question.

Share on other sites

This does not really have much to do with your stated organization of DLL/EXE/EXE though. Which means you're likely overcomplicating your approach for no reason. You have not stated a compelling reason why your project needs to use that approach, so you shouldn't (since it is a more complicated approach).

It does because i cant make the game as well at the moment because i have no way of separating the game from the engine.

A static library will be significantly simpler to start out with, and can be easily adapted to a DLL if needed later. However starting out with a DLL, unless you're familiar enough with their production (and I don't think you are since you had to ask the question in the first place) will introduce a lot of boilerplate code, such as the necessity to expose a C-style ABI for your engine and do the appropriate marshaling and/or data hiding that gets in the way of accomplishing your actual goal of making something.

After what I've been reading recently I would prefer to compile to a static lib to begin at least because it is simpler, I agree with that.

Share on other sites

It does because i cant make the game as well at the moment because i have no way of separating the game from the engine.

You can do this entirely within a single .exe project if you have good engineering discipline about it. If you'd like an extra layer of protection against you're making mistakes (a reasonable idea), a static library works fine (it will be a separate project). The DLL aspect is what I'm objecting to here.

Share on other sites

You can do this entirely within a single .exe project if you have good engineering discipline about it. If you'd like an extra layer of protection against you're making mistakes (a reasonable idea), a static library works fine (it will be a separate project). The DLL aspect is what I'm objecting to here.

That is what I have been aiming to do. Initially I just made the Engine project compile to a static lib and had the game as the EXE but i couldn't come up with a way to make that work without having the entry point in the game project and have that load the engine, which means i have to write that main function for every game i ever want to make with the engine

Share on other sites
which means i have to write that main function for every game i ever want to make with the engine

You'll (generally) have to write a main function for all of your games, since the games are the .exes where your main entrypoint has to be. However you can reduce the amount of boilerplate to something like:

int main () {
MyAwesomeGame game;
return game.run();
}

or similar with a bit of work (here "MyAwesomeGame" is a subclass of "YourEngine::Game" or whatever which implements only the game-specific logic, the boilerplate stuff being taken care of by the YourEngine::Game base class from your static library. Is that what you were going for? Where did you run into trouble along that path?

(there are ways to avoid having to write a main function, including a paradigm where you engine is the .exe and your games are shipped as DLLs, but again, that's probably overcomplication).

Edited by Josh Petrie

Share on other sites

which means i have to write that main function for every game i ever want to make with the engine

You'll (generally) have to write a main function for all of your games, since the games are the .exes where your main entrypoint has to be. However you can reduce the amount of boilerplate to something like:

int main () {
MyAwesomeGame game;
return game.run();
}

or similar with a bit of work (here "MyAwesomeGame" is a subclass of "YourEngine::Game" or whatever which implements only the game-specific logic, the boilerplate stuff being taken care of by the YourEngine::Game base class from your static library. Is that what you were going for? Where did you run into trouble along that path?

(there are ways to avoid having to write a main function, including a paradigm where you engine is the .exe and your games are shipped as DLLs, but again, that's probably overcomplication).

I have a class that basically brings all the main subsystems together such as the graphics manager, the timer, the world manager, the game loop (which does essentially what a main function would do)

int GameLoop::Run()
{
m_pTime = m_pEngine->GetTime();

MSG msg = { 0 };

while(!m_bWantToQuit)
{
if(PeekMessage(&msg, (HWND)m_pWindow->GetHandle(), 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

if (msg.message == WM_QUIT)
break;

m_pTime->Tick();
m_pEngine->Update(m_pTime->GetDeltaTime());
m_pEngine->Render(0);
}

return 0;
}


I did this to allow me to abstract the platform specific code so all implementation is in the cpp file and there are different ones for each platform.

would the Engine class be the one you are talking about? Or are you saying to make a separate class that starts up the Engine class so to speak?

Share on other sites

No, what you've got there seems like a fairly reasonable implementation of the idea I was talking about (just using different names or terminology than my example).

Your earlier posts seemed to imply there was some difficulty with this approach that led you to have to rewrite a lot of code for every "game" using your engine, but I'm not clear now what that difficulty was?

Share on other sites

No, what you've got there seems like a fairly reasonable implementation of the idea I was talking about (just using different names or terminology than my example).

Your earlier posts seemed to imply there was some difficulty with this approach that led you to have to rewrite a lot of code for every "game" using your engine, but I'm not clear now what that difficulty was?

That class is tied into the engine project not a separate one its part of the platform abstraction layer the header and class declaration resides in Core/Platform/GameLoop.h and the definitions reside in Core/Platform/Windows/GameLoop.cpp where windows would be the platform for which the game is being compiled. this makes it a fundamental part of the engine, which means i can't put it in the game project

Share on other sites

Ah, but you could write a Game class in your engine, one that is basically an abstract base class:

struct Game {
virtual void OnSetup() = 0;
virtual void OnUpdate (float elapsed) = 0;
virtual void OnRender (float elapsed) = 0;
virtual void OnShutdown () = 0;
};

Then you expect the "user" of the library to create code that subclasses the Game object, implementing each function to perform the appropriate actions. Then you expect your game loop to be given a pointer to the user's game object when it runs:

struct MyAwesomeGame : Game {
... implement functions...
};

int main ()
MyAwesomeGame game;
GameLoop::Run(game);
}

And your "run" method takes a Game&, which allows dynamic dispatch (you could do a Game* if you wanted, but a reference works and enforces the idea that you have to pass one, you can't pass nullptr). At the appropriate points in your "run" method you call the appropriate methods of the game object, e.g., you call OnStartup before you enter the loop proper, OnShutdown right before you return, and OnUpdate and OnRender during the actual loop.

The above is a simplified form of the idea (you'd probably want to take a closer look at what goes on in what is currently your m_pEngine->Update() calls and the like, but it gets the basic point across. In "real world" implementation  you might use a non-virtual interface idiom to ensure that things that are "supposed" to happen on Update or Render happens regardless of what the user puts in their derived implementation. But essentially what you're doing here is using the game class to provide the basic required functionality of the game engine (this may be what your 'engine' class currently does) and use inheritance to allow user code to implement methods that are called at the right point to supply custom, game-specific behavior.

Then you have only the game-specific code in the game project, and the general part of the code (the Game base class and/or the Engine class, the GameLoop class, etc) in the engine library.

Share on other sites

Ah, but you could write a Game class in your engine, one that is basically an abstract base class:

struct Game {
virtual void OnSetup() = 0;
virtual void OnUpdate (float elapsed) = 0;
virtual void OnRender (float elapsed) = 0;
virtual void OnShutdown () = 0;
};

Then you expect the "user" of the library to create code that subclasses the Game object, implementing each function to perform the appropriate actions. Then you expect your game loop to be given a pointer to the user's game object when it runs:

struct MyAwesomeGame : Game {
... implement functions...
};

int main ()
MyAwesomeGame game;
GameLoop::Run(game);
}

And your "run" method takes a Game&, which allows dynamic dispatch (you could do a Game* if you wanted, but a reference works and enforces the idea that you have to pass one, you can't pass nullptr). At the appropriate points in your "run" method you call the appropriate methods of the game object, e.g., you call OnStartup before you enter the loop proper, OnShutdown right before you return, and OnUpdate and OnRender during the actual loop.

The above is a simplified form of the idea (you'd probably want to take a closer look at what goes on in what is currently your m_pEngine->Update() calls and the like, but it gets the basic point across. In "real world" implementation  you might use a non-virtual interface idiom to ensure that things that are "supposed" to happen on Update or Render happens regardless of what the user puts in their derived implementation. But essentially what you're doing here is using the game class to provide the basic required functionality of the game engine (this may be what your 'engine' class currently does) and use inheritance to allow user code to implement methods that are called at the right point to supply custom, game-specific behavior.

Then you have only the game-specific code in the game project, and the general part of the code (the Game base class and/or the Engine class, the GameLoop class, etc) in the engine library.

This is the sort of thing I attempted when I first tried it, but I can't remember why it didn't work. I'll give it another go and see what results I get!

Thanks for the help Josh!

Share on other sites

This is the sort of thing I attempted when I first tried it, but I can't remember why it didn't work

I remember now! it is because i have a component factory that uses static initialization, which if the statics are defined in the static library, don't get initialized :(

Share on other sites

I remember now! it is because i have a component factory that uses static initialization, which if the statics are defined in the static library, don't get initialized

Lots of libraries use statics and wouldn't work at all if they didn't get initialized. Can you provide an example of what your code looks like when this doesn't appear to work as you expect?

Share on other sites

I was given this code by another member of this forum a while ago. I still don't thoroughly understand it which may be what is impeding me in overcoming this.

namespace ComponentRegistry
{
typedef Component* (*CreateComponentFunc)();
typedef std::map<std::string, CreateComponentFunc> ComponentRegistry;

inline ComponentRegistry& getComponentRegistry()
{
static ComponentRegistry reg;
return reg;
}

template<class T>
Component* createComponent()
{
return new T;
}

template<class T>
struct RegistryEntry
{
public:
static RegistryEntry<T>& Instance(const std::string& name)
{
// Because I use a singleton here, even though COMPONENT_REGISTER
// is expanded in multiple translation units, the constructor
// will only be executed once. Only this cheap Instance function
// (which most likely gets inlined) is executed multiple times.

static RegistryEntry<T> inst(name);
return inst;
}

private:
RegistryEntry(const std::string& name)
{
ComponentRegistry& reg = getComponentRegistry();
CreateComponentFunc func = createComponent < T >;

std::pair<ComponentRegistry::iterator, bool> ret =
reg.insert(ComponentRegistry::value_type(name, func));

if(ret.second == false)
{
// This means there already is a component registered to
// this name. You should handle this error as you see fit.
}
}

RegistryEntry(const RegistryEntry<T>&) = delete; // C++11 feature
RegistryEntry& operator=(const RegistryEntry<T>&) = delete;
};
}


And then for each component i have this macro in the .cpp file

#define COMPONENT_REGISTER(TYPE, NAME)  \
template<class T>                                                     \
class ComponentRegistration;                                          \
\
template<>                                                            \
class ComponentRegistration<TYPE>                                     \
{                                                                     \
static const ComponentRegistry::RegistryEntry<TYPE>& reg;       \
};                                                                    \
\
const ComponentRegistry::RegistryEntry<TYPE>&                       \
ComponentRegistration<TYPE>::reg =                                \
ComponentRegistry::RegistryEntry<TYPE>::Instance(NAME);     \


When i run the version where the engine is static lib and the game and executable the component registry is empty

Share on other sites
IMHO this kind of automatic registration via initialization of static globals, is an anti-pattern and should be avoided. The standard says that any of these statics that are never used, may also be never initialized, so the compiler is free to optimize them out of the program completely.
Rewrite it to not use globals and it will work (or to actually reference those globals from somewhere else so they're actually used by the program).

• Similar Content

• Hello everybody! 💡
So this is my first such game for android. I tried to mix the mechanics of 2048 games and three in a row. I came up with an idea, painted, animated, wrote music and put it all together on Unity.
Thank you! Peace! ✌
Free on Google PLay: Stones Of Engar

• Hey guys!
Check out the trailer of Airavat. It's a minimalist, space survival game (and hard, very hard)

• Hey, we are new around here!
Our team spent the last year developing a prototype game called Rise of The Fey, a game that focuses on a dramatic story with a fast paced gameplay.
Rise of The Fey is a third-person action-adventure RPG set within a fantasy world called Perrah. In Rise you control Kall, a young spaunian looking for revenge after the death of his beloved.

We would appreciate if you could take a look at our stuff, tell us what you think and possibly help us out on Indiegogo.
The prototype is in portuguese, sorry about that!
Have a good one!
• By juglar
Hi guys, we are developing a game called BiteOff! based on Zombies topic. BiteOff! is based on a game strategy mechanics, free to play, where the player has a bunch of zombies and he can distribute them along the map landscape to be able to bite and transform all humans into each level. Humans are controlled by artificial intelligence and they differ each other on capabilities based on different weapons that give them three different levels of aggressiveness to defend against the zombies. The zombies are also presented in three types and they are differentiated by their attack, speed, strength and resistance abilities. Through different achievements, (time to eat all humans, score, among others) the player can access four extra skills that can enhance your attack in real time on next levels as power-ups.
We are launching a crowdfunding campaign in kickico and we need some helps please visit us on the crowdfunding page https://www.kickico.com/es/campaigns/17824/biteoff-the-videogame