Jump to content

  • Log In with Google      Sign In   
  • Create Account


Member Since 12 Mar 2005
Offline Last Active Today, 08:11 PM

#5198084 Need advice on C++ reflection system

Posted by frob on 14 December 2014 - 02:03 AM

I think we're agreeing with each other here, but just to beat a dead horse... don't reflect stuff like that. There's no reason to automatically reflect every hash table. I'm not even sure how'd you do that in C++ without using an external tool that intentionally scans for template instantiations which would be insanely difficult if you're not plugging into Clang or the like.



You should though follow the rule of reflecting only what you need.


You write there is no reason to do it. 


You write that you should only reflect what you need.


So that means we are still in disagreement.  I feel both these statements are incorrect.




Reflection is heavily used in nearly all modern languages. Not just C# and Java. Objective-C, JavaScript, Python, ActionScript, Ruby, PHP, Go, and many more. The type of thing you are talking about is a far cry from what reflection is or what it enables.


For lack of another authoritative definition, I'll use the one from Wikipedia: Reflection allows inspection of classes, interfaces, fields and methods at runtime without knowing the names of the interfaces, fields, methods at compile time. It also allows instantiation of new objects and invocation of methods.


Reflection does not mean partial metadata, knowing only a part of the interfaces, a few of the fields, a subset of the methods, or invocation of the methods the linker happened to leave in place.  Reflection means you can programatically access another system and completely reuse the entire functionality of classes and other parts..



In modern languages there is a very strong, compelling, and language-mandated reason to export every part of the public interface.  Modern reflection mechanisms provide the complete functionality to any program that is allowed to observe or modify the system. 


In C++ there is a language-preferred reason not to expose anything. The overhead and additional costs involved are exactly the reason the language does not want it.


This is one of the radical differences between what modern languages use for reflection and what older languages do.





More realistic systems would reflect only...


That is where I strongly disagree.  Your "more realistic" means "a tiny piece of support compared to others".


Reflection in modern languages is very different from, and incompatible with, the old compilation model used by C and C++.  Microsoft has invested a fortune into it building C++/CLI. Even after spending untold millions on the system across more than a decade, it still only partially works and they cannot get it to the same level of quality found in any modern language.  


Large ecosystems have developed around reflection, with plugin architectures and external modifications being some of the biggest benefactors.  


This is one of the big pieces of functionality that helps other languages advance far beyond C++ outside of systems-level work, and is a painful hole when doing systems work when your system must integrate with other systems. Back in the mid to late 1990s COM objects and DCOM objects became popular and profitable, as businesses could get components, drop them into their programs, and gain programmatic access and interoperability. There was (and still is) some overhead in figuring out exactly what should be exposed and how to expose it.   Then there was an explosion of other languages with reflection. That is available for free with modern languages. Now in these modern languages you can pull down just about any functionality you want from any of a large number of public repositories, download only the final executable/library build, and have full access to everything you would have without need source, without needing to rebuild with different compiler options, without needing to account for ST/MT versions, without needing to account for dependencies.


C++ is a wonderful language for systems-level work and HPC because of the level it works at.  But with an ever-expanding collection existing engines and tools, the lack of reflection continues to grow as one of C++'s serious flaws and missing features. The cost and effort of making a C++ program that plays well with others is painfully high. Every time there is a new library or new engine, or even an update to an existing component you've integrated into your library, the flaw becomes that much more apparent. In reflection-supporting languages you download a new final build and verify in the documentation that the public interface has not changed in breaking ways. In C++ such a change can require several days of integration efforts.  


Like you, I've worked with many enormous code bases. I've maintained build systems, run the integration of many working parts, and even for one game cycle had the horrible job of keeping a large collection of C++ libraries updated with EA's massive corporate collection of systems for all the libraries used by the game, the tools, the build chain, and everything else. I currently work for a different company doing similar things but with a mostly Java codebase. The ability to simply point to nexus and pull down the latest final build, and having programs designed to automatically bind with any build I specify... Well, that is me and our codebase relying on the modern reflection mechanisms. The build chain automatically notifies the team when updates are available, and if we chose to take the updates we can usually integrate them by typing in a new version number and telling the build server to run the test suite. Having seen what reflection enables, I hope to never again need to manage dependency trees as is still done in C++. 



TL:DR: About the closest C++ can get to reflection is with COM objects or DLL exports or similar extracted or programmer-maintained systems. While these are useful alternative interfaces, they are worlds away from reflection as it is used everywhere.

#5198058 Mobile Arcade

Posted by frob on 13 December 2014 - 07:27 PM

Here is my question. Does anyone know the Paypal API and how I could interface with it to allow the user to make a payment from my site and then trigger IP address addition to the database?


It is well documented on the PayPal web site, developer.paypal.com.


It is not too hard to use. You provide formulaic URLs to your users for them to use.


When the payment is completed the system includes both an automatic ping-back from the servers that you can handle, and you can also query into their system.

#5197931 C++: Easiest way to implement an in-game Time/Date system?...

Posted by frob on 13 December 2014 - 01:30 AM

I've tried a few different things using QPC()/QPF() and come to a point where the seconds seem to be progressing quite smoothly in general, but there's still a definite, though probably significantly rarer than before, occasional time when a second visibly hangs for a moment before the next second shows up and goes by more quickly to compensate.


Scrolling back up to my earlier wall of text, use the results of QPC as a stopwatch. Tiny error in individual frames will work itself out over a larger time frame. Don't try to convert it back to milliseconds or do fancy division or averaging, just leave it at the high performance clock values. 


The only time you really need to stop that clock is when the elapsed time is obviously out of bounds.  Usually that happens when you stop the game in the debugger or the system otherwise has stalled.  That is easy enough to handle as a special case, along the lines of

elapsedTime = GetTimeSinceLastUpdateWithQPC();
if(elapsedTime > WAY_TOO_LONG) {
    elapsedTime = DEFAULT_TIMESTEP;
    Logger::Log( Simulator, Logger::Info, "Excessive time between updates exceeded, possibly from an OS stall or a debugger. Resuming with a sane time step.");
accumulatedTime += elapsedTime;
while(accumlatedTime >= SIMULATOR_FREQUENCY)
  accumlatedTime -= SIMULATOR_FREQUENCY;

Without that kind of protection you quickly fall into an update death spiral. One update takes more time than you allow, and when you come through the next time two updates need to run to catch up. Then because you spent more time it needs to run three, then four, then soon the game is doing nothing but trying to catch up.


Since I'm sure you have followed the route mentioned above to decouple your rendering loop from your simulation loop happy.png it doesn't matter if the renderer has problems since you can simulate multiple times in a row, and if your simulator is running slow your renderer can interpolate between the two values. Fixing your time step is an important part of having a reliable simulation.

#5197930 Need advice on C++ reflection system

Posted by frob on 13 December 2014 - 01:00 AM

I don't see how that follows. The translation mechanism of C++ works just perfectly fine with reflection, optimizations and all. I have a few multi-million line codebases and more than a few bases of much smaller size floating around as testament to that.

You should though follow the rule of reflecting only what you need. For instance, with a class, there's little good reason to automatically reflect every member variable or function. Reflecting the ones that you need to serialize to disk or expose to GUI editors or bind to the scripting language, however, will by its very nature never be able to keep dead code or data alive (the non-reflection approach would've linked in the class and any of the bound function symbols as well, and member variables can't be elided by the compiler anyway).

You may be right or not about "little good reason", but the reasoning is not what I was referring to.


Reflection in languages like C# and Java is very different from, and incompatible with, the old compilation model used by C and C++.



Reflection in modern languages embeds every potential function, every data member, every generated item. Even if you never reference it in your code the items are generated.  If you use generic/template elements every variant is generated and enumerable. You can open the executable and see every generated function, every private function, anything that was coded. It will all be there by default.  You can take steps to disable it but most people don't. Many games that use the languages know full well that others will use it, and they serve as a launching pad for the modding community.


The object and library/archive model eliminates everything that is not used in the final program. Uncalled functions are eliminated. Template methods that are not used are never expanded, and sometimes those that are used are completely expanded inline and never generate a signature. Archives and libraries do not bring over the full contents, instead only bringing over the bare minimum the linker deems necessary. You can take steps to ensure items are generated but that is rarely done. If you want to allow others to poke into your game you need to expressly provide that functionality yourself.


Going for a concrete example.


In C#, you can use something like HashSet<foo> myHash = new HashSet<foo>;  Then in your code you add items, iterate over the items, and nothing else. Build it, open it up in the right reflection tools, and you can see every method that would be available to HashSet<foo>.  You have access to functions you didn't call, functionality like Clear(), Contains(), SelectMany(), or whatever you want. The functions you used, like Add() and GetEnumerator() will also be there. If you want to attach with the right tools and call functions that were not used in your program like Count() or First(), those functions can easily be found by reflection. The whole class in its entirety all exist in the end product and can be called by an attached program unless you take rather extreme steps to remove them. You can repeat this with your own generic classes as well, build what you want and it will all be present in the final executable by default.


In C++, you can use roughly the equivalent unordered_set<foo> myHash; Then you code you also write stuff that adds items, iterates over the items, and does nothing else.  Build it, open it up in your favorite tools or just look over the map file ... and you will probably find zero addressable function calls for it, perhaps you may find a small number of internal utility functions.  The template items like clear(), find(), equal_range(), they do not exist. They were never generated. They cannot be addressed nor can they be called with a tool attempting to reflect in to the code. The functions you did use like add() and begin() also probably do not exist as functions with addresses, they were almost certainly moved inline. If you attach to the code by some unknown reflection method, the functions you didn't use like count() and find() were never generated and therefore cannot be called. Practically nothing from the class exists in the end product unless you take rather extreme steps to the signatures specifically and ensure they are all addressable. You can repeat this with your own classes and custom libraries as well, build what you want and only the absolute minimum required will be present in the final executable by default.


This is the hurdle you need to overcome if you want to have modern reflection in the old archive-based compilation model that C++ uses. 


It is something that can be overcome if you need to with sufficient compiler support.  Microsoft did it with C++/CLI and it took them nearly a decade to get it mostly working okay, but even so it is incomplete for a huge amount of code. If some specific functionality is missing you can special case it into the reflection mechanism.  There were some attempts in GCC to get reflection working but the code branch died roughly in 2005 due to lack of interest and demand.



That is why I wrote originally, "it is important to ask how you intend to use the system".  If your intention is to be able to call a limited number of functions and look up the names and offsets of specific variables, that is one thing and it can be accomplished. That is how C++ game engines open themselves up to modding communities. It takes effort but can be done.  If your goal is to make generic C++ do what Java and C# do with reflection, that will require rewriting large chunks of the compiler and linker.


So far only Microsoft has spent the time, effort, and money necessary to get it working, starting in to the project around 2001. It was pretty horrible until around 2008. They still tinker with it, and today in 2014 (over a decade since they started on it) the compiler's C++ reflection-generation system mostly works okay, but is far from perfect.

#5197883 Need advice on C++ reflection system

Posted by frob on 12 December 2014 - 04:50 PM

In Microsoft land, C++/CLI has some reflection built in, and if you are mixing your code with other .net stuff this can be easy and powerful.



Reflection is a great tool, but is contrary to the nearly sixty-year-old compilation model. The model used by C++, C, and even older Cobol and Fortran, favors eliminating unused stuff and minimizing data. Optimizations by the compilers will eliminate dead code, exclude things that the compiler doesn't see is useful, and eliminate intermediate elements whenever possible.



For C++ specifically, it is important to ask how you intend to use the system. Some features are limited to compile-time only, others are dynamic-only, some you could access differently for both.


For instance, at compile time and at link time you might be able to leverage SFINE to potentially implement some reflection-like features. Depending on your compiler choices you can provide weak symbols as alternatives to help you call functions that may or may not be present when the module is built, but are present at link time.



Beware about using self-registering code like you suggested.  I've seen that handled as a class that creates a single global instance, and as part of the constructor the registration takes place. Optimizing compilers frequently choose to not generate code if they don't have to. This can have a side effect that even though you wrote code for a template and created an instance, only a small number of the functions are actually available. Or if you rely on side effects that are difficult for the compiler to track, the compiler may not see them and decide to elide the code in a way that breaks your intention. 


Even if you require registration it can be possible for functions to be eliminated by the compiler or linker. I've been on projects where we used self-registration systems where the overly-smart compilers dumped the functions and globals at link time since it assumed they were unused, and we needed to resort to various linker options to force the system to mark them as used.

#5197861 is there an easy way to do this?

Posted by frob on 12 December 2014 - 03:39 PM

unfortunately, only 60 to 80% need to be changed. and who the current_actor is depends on the context from which msg() is called. which leaves specifying the current_actor variable (if used) on a case by case basis as i do a "find next" through all ~101K lines of code.
is there some way to design code so this sort of thing doesn't happen?

Yes, there are ways to do it better.


Being "Easy" depends on how much you are doing. 

If your game is only going to have roughly 600 strings forever, and the engine will never be reused, then your approach with minimal modification is probably the easier choice.

Studios with global text databases and localization teams tend to develop robust solutions to it.  There is some up-front cost to developing a good system, but in the long run it is worth it.  
Commonly it involves a text replacement system with embedded formatters and optional parameters. In C++ that generally means VA_ARG style "..." parameters since although it adds a bit of complexity and risk, the comprehensive testing of the game and a careful implementation should prevent problems.
You (the programmer) pass in a key, then append any parameters you need.  Some parameters can also be standard, like always having a pointer to the speaker (current actor) and a pointer to the target game object.
So you might have a prototype of the format:

UiTextFeedbackResult Speak( TextNoticeId messageToDisplay, GameObject *source, GameObject *target, size_t count, ...);

Then you would call it with something like: 

DialogEngine::Speak( TextNotice::AllFull, mCurrentPlayer, mObjectStack.items[0], mObjectStack.count() );

The dialog engine could then do the work to figure out things like the appropriate genders and numeric agreement.

It would look it up in the localization system, which has a line something like this:

enum TextNotice {
 AllFull = 42;

Then in a data table somewhere you have all your localized text strings that include the English variants:
42, "1", "mf", "Your {1.ObjectName} is full."
42, "0,2+", "mf", "All your {1.ObjectName} are full."
with variations for each language, and possibly variations for each gender.

Your text display system would go through a similar step to get the speaker's name, likely with a localized prefix of perhaps
173, "0+", "mf", "{0.ObjectName}:  "


Combine them all and the UI system can 


Some systems will use text strings rather than enumerated values, but the net result is the same, gaining some additional processing cost for the benefit of easy addition of items but the risk of typos and missing text lines. That's a design tradeoff.


It can take a bit of work to set up the first time, but localization systems like this are very extensible. The are even more powerful if you have ways to convert items in the parameter lists into additional items by using dynamic casts or similar mechanisms. In the various systems I've used, the source of the message is {0}, the target (or null) is {1}, and the additional optional parameters are numbers starting at {2}.


For example, you could pass lists of items and have a collection of strings in the UI:

123, "0", "mf", "Nothing collected."

123, "1", "mf", "{2.ObjectCount} {2.ObjectName} collected."

123, "2", "mf", "{2.ObjectCount} {2.ObjectName} and {3.ObjectCount} {3.ObjectName} collected."

123, "3", "mf", "{2.ObjectCount} {2.ObjectName}, {3.ObjectCount} {3.ObjectName}, and {4.ObjectCount} {4.ObjectName} collected."

123, "4+", "mf", "{2.ObjectCount} {2.ObjectName}, {3.ObjectCount} {3.ObjectName}, {4.ObjectCount} {4.ObjectName} and additional items collected."


Then for troublesome languages with huge object names, use "0", "1", "2", and "3+" variants.


Other types are things like time values, giving {2.Hours}, {2.HoursMinutes}, {2.HoursMinutesSeconds}. Numbers so you can put in the proper commas or dots or apostrophes or other punctuation, {2.Money}, {2.Number}. Sometimes it is useful to have uppercase and lowercase variants, {2.ObjectName} and {2.objectName}. 


Depending on how your localization team wants to handle things, various languages differ on how to handle gender and numeric alignment. Sometimes there are differences between men talking to men, men talking to women, women talking to men, and women talking to women, so if you are targeting any of those languages (often these are Asian languages) you'll need to account for that as well.  It can get tricky because an object that is masculine in one language can be feminine in another.  



Another aspect of the extensibility for this type of system is natural variety and randomization of the text lines. If you have multiple matches in your localization database select randomly from the result set. The design or localization team can go wild with variants for frequently-used lines:


1234, "0+", "mf", "Understood."

1234, "0+", "mf", "Acknowledged."
1234, "0+", "mf", "On my way."
1234, "0+", "mf", "Yes."
1234, "0+", "m", "Yes, sir."
1234, "0+", "f", "Yes, ma'am."
This can help (but won't eliminate) some of the tedium of certain dialog systems. 
I could go on and on for benefits of a good text localization system, but this should be enough for the basics.  It has an up-front cost, but in the longer term it is quite a valuable tool.

#5197514 How to model and program in the correct scales?

Posted by frob on 10 December 2014 - 11:13 PM

Rescaling things dynamically can have problems. When you mix very large items with very small items, things start to break. Sometimes they break subtly, like z-fighting, other times they break more severely.


It is far better from a correctness viewpoint to simply model everything at the same scale.


Very often games use a 1-meter scale.


The six decimal digits of precision at that scale gives you micrometer precision, which is about 1/3 the width of a hair, and about the size of many bacteria.  You won't want to use that level of precision since error would quickly accumulate to catastrophic levels, but the models could have that level at import.

#5197284 "defer": is this silly / broken?

Posted by frob on 09 December 2014 - 05:27 PM

This only delays until the destructor is called at the end of the scope. There may be times when you want to schedule for a different time.


In most games and engines, there is a collection of functions that can be run at a specific time. A common one is a general function pool after the simulation code is complete that allows you to destroy objects or otherwise manipulate the simulation's details that could be problematic mid-update. It is fairly common to find pre-update and post-update, pre-render and post-render, and less common to have additional hooks in asset management and other functionality. 


Scheduling some bit of processing for later can be a very useful bit of code. They always have some caveats, and as others mentioned, your use of destructors for this comes with its own pitfalls. 


As you wrote you are doing driver development, scheduled code may not be something already in your toolkit.  It is useful to have.

#5196746 Why is math transformation taxing to most CPUs?

Posted by frob on 07 December 2014 - 01:29 AM

2)  This calculation process is called transformation is extremely taxing to most CPUs.
Question 2: Is it because the CPU cannot process the address of the data quickly per frame? Does it lead to a slow frame-rate in the game?

This one is actually still true.


Matrix-matrix multiply and matrix-vector multiply are a big cost. A few really smart math geeks have greatly reduced the costs, and some really smart hardware geeks have moved a portion of the cost over to the graphics card rather than the CPU.  However, the operations are not free and they are the most common basic functions used in graphics and physics and other systems. 


Done poorly a game can still overload the CPU with badly-written math operations. It is a known concern. Faster processors and good libraries can help reduce and mitigate the concern, but it is still something you will see quite visibly on profiling numbers.


A simple naive matrix multiplication, a 4x4 multiplied by another 4x4, is rather costly.  Multiply each row by each column (using a dot product) to compute each one of the 16 necessary results.  That is 64 floating point multiplications and 48 floating point additions. While an individual matrix multiply isn't overly taxing, doing many of them quickly reaches an unacceptable cost.


With a little bit of math magic and some SIMD instructions you can reduce it to the oft-cited code snippet of 16 multiplications, 12 additions, and 16 "shuffles" that let you reuse some of the intermediate results. It ends up about 5x to 6x faster depending on implementation details of the naive implementation.  I'm not sure where it came from or what the proper name for it is, but it has been floating around the web for about a decade now. There are many similar speedy specialized algorithms for various vector-matrix operations for both column-based and row-based vectors. 


While that is a reduction in the number of steps, the cost of matrix multiply is still one of the more costly low-level operations you can do.  Graphics operations rely heavily on it.  Every time you move or position something in 3D space you need to run a series of matrix multiplies all the way through that portion of your scene.  You've got the Model or World, the View, and the Projection matrices that ultimately needs to be pushed out and multiplied to every pixel that gets rendered. You'll need to do quite a few of those matrix multiplies on the CPU, but fortunately you can pass the pre-multiplied values out to the GPU and allow the card with its specialized hardware to do the rendering and heavy lifting. 


Physics relies heavily on it, every time you move a physics object you also rely heavily on this math  Much like the graphics APIs, there are physics libraries (e.g. PhysX) that take advantage of hardware to do the more costly parts. Most physics simulations work on bigger primitives rather than point clouds so they often require less total matrix operations, but it can still require a hefty portion of the CPU budget.

#5196515 Intros

Posted by frob on 05 December 2014 - 04:44 PM

So I use the DirectX SDK .. I don't have to spread NVIDIA logos all over my game now ? Or is DirectX working together with NVIDIA, because DirectX is a interface, working with NVIDIA ?


PhysX and DirectX are unrelated. The only minor similarity is that both have the letter "X" at the end of their name.


PhysX is a hardware-accelerated physics library from nvidia, that uses a chunk of the graphics card to process physics.

#5196505 Intros

Posted by frob on 05 December 2014 - 03:25 PM

As a prime example of this, the nvidia Physx public license has this wonderful section:

6. Attribution Requirements and Trademark License. You must provide attribution to NVIDIA.

A. You will include a reference to the PHYSX SDK and NVIDIA in any press releases for such Game that relate to NVIDIA, or in-game physics, and will identify NVIDIA as the provider of "PHYSX" (or such other term or phrase as indicated by NVIDIA from time to time).

B. For Games, Demos, and Videos that incorporate the PHYSX SDK or portions thereof, the NVIDIA
logos must appear:

a. on the back cover of the instruction manual or similar placement in an electronic file for the purpose of acknowledgement/copyright/trademark notice;
b. on external packaging;
c. during opening marquee or credits with inclusion of “NVIDIA”;
d. must appear on title marketing feature list with a specific call-out of NVIDIA PHYSX Technology
e. on the credit screen; and
f. in the “About” or “Info” box menu items (or equivalent) of all Physics Games or Applications using any portion of the PHYSX SDK.

C. Provide a quote citing the Licensee’s integration of the PHYSX SDK into the Game or Application for NVIDIA’s use in press materials and website.

D. Refer to NVIDIA’s PHYSX SDK in all press coverage referring to the use PHYSX in the development of any Game or Application.

Failure to provide attribution pursuant to this Section shall be considered a material breach of this agreement.

#5196504 Intros

Posted by frob on 05 December 2014 - 03:20 PM

They play them because they got some sort of contract allowing a benefit from the company and part of the deal was that the game developer would advertise.


Commonly that could be early access to hardware and to drivers, and direct support from the driver development teams.


The game company doesn't say "I really want to play the nvidia logo on my game".  Instead they have some specific thing they want to take advantage of and the logo becomes part of the contract for that access.

#5196287 C++: Easiest way to implement an in-game Time/Date system?...

Posted by frob on 04 December 2014 - 12:10 PM


...  maybe a real-life second is an in-game minute or some such, and time acceleration allows it to progress faster...
Is it just me or posts here are assuming the in-game time  will increase at a more or less constant rate?


If you plan to run the simulation for a lot of time with "time scale" changes, I suggest against using a single reference point in time. In the past I've had some nasty things with accumulation errors and I cannot be completely sure the new frameworks solved them. Keep around a list of "time speed" changes and reset your time reference to last time multiplier change.



That is an (important) implementation detail.


If you have simulation clock based events, you need to make sure all the simulation clock events trigger.  It doesn't matter if the rate is one simulator tick per wall-clock second, or a thousand simulator ticks per wall-clock second, or a "skip two weeks" debugging cheat code, your implementation needs to ensure that anything tied to the clock is handled "properly", for whatever your game's definition of that means.


For example, if you've got an event that a player's buff gets cancelled after 525600 ticks, and you jump your simulator clock by a million ticks through a cheat code, you will need to ensure the important action is triggered. Other things like ensuring a particle system has the particles updated at a constant rate are probably not be important events, and those could be skipped over.  That is all game specific implementation detail.

#5196274 Accurately estimating programming cost?

Posted by frob on 04 December 2014 - 10:38 AM

An alternate way of estimating costs is to compare it to rough costs and to find comparable titles. You say you want to start with FTL - Faster Than Light, plus a lot of features.


FTL started as four people with multiple months in their basements (we'll simplify to 1.5 FTE) followed by $200,000 kickstarter money in Shanghai, China. Combined with everything it took them over a half year, if I'm reading that correctly. In the US you need to estimate 10,000 per man-month.  I'm not sure what that will buy you in China, but Google suggests it is about 20% cheaper.  200000/8000=25 man months. It took four people about six months, so that sounds about right. 


Then you are asking to roughly double the size in new features, so we'll double that to 90 man months. Plus since your project is larger there will be more experimentation and more administrative costs, making it about 120 man months.  


From my own experience in smaller games, that number sounds about right for a FTL style game. You can look up various similarly-sized games and see if that feels about the same scale to you.


The game would have a very simplistic feel to it, and may or may not be fun (that is up to your design and implementation). 



You want it in the USA, so the 120 man months is around 1.2 million dollars for your simple little game, if you are paying for it.


If that means the development team is you and your nine other close friends, all of you willing to work about 2000 hours on it as a full time job, it would take about a year.  

#5196136 First big game. Which engine and how to handle multiplayer?

Posted by frob on 03 December 2014 - 03:24 PM

So you want a game engine that runs on 8 different major platforms with all their variants, plus web play, with screen sizes ranging from 4-inch 640x480 to giant screens having 4k and 5k resolutions, plus has solid network play across all kinds of networks from 3G phones to corporate LANs, and all with minimum installation requirements, all with a single shared source code and asset base.


Is that all? happy.png


Really that means Flash-based engines, Java-based engines, and Unity. If you remove the web requirement you can also chose Unreal. I know that doesn't help much for decision making. Try several, pick whatever best fits your design and programming style.


There are many engines capable of doing what you describe. The harder question is if you are capable of doing what you describe. No matter what engine or tools you pick this will be a big undertaking.  Among other things you'll need an army of QA in order to reasonably cover all the operating system variants and hardware variants on each OS. That will not come cheap.




The multiplayer aspect is more an question of design than engine choice. You'll need a design that functions well with the latency and network propagation time. You'll need a design that packets can play well on many different types of networks, including cell phone networks with their crappy connections.


Just writing "...sandbox[sp],co-op[mp],competitive[mp]..." is really not enough to go from. You will need (in your design) to go in great detail before doing much with code no matter your engine choice. You'll need to figure out your protocol, you'll need to figure out how you will handle servers and matchmaking and connections, you'll need to figure out how to handle latency and delays and stalls and drops, you'll need to figure out how to resolve conflicts and what is authoritative, you'll need to figure out how to correct things when they inevitably go wrong. You'll need to figure out what is significant and gets transferred versus what is unimportant or what is computable and does not get transferred. Those details give each game their own unique feel.


If you go with Unity, the networking aspect means you need to design carefully about what features matter for networking. The simulator does not support a "rewind time and insert this event" that is currently popular in fast-paced games. You can run a mini-simulator within the engine that handles that type of work, but there is a significant development cost. The built-in physics engine and other GameObject state can get a little wonky and slightly different if you let each machine do its own simulation, so your design needs to be flexible enough for that, or you can work hard to overcome that kind of drift inside the implementation details. 


If you go with a Flash or Java engine -- and there are many to choose from -- you're going to have similar design concerns.