Sign in to follow this  
coder84

Addiction to soft coding...

Recommended Posts

Hi everybody! The title talks for itself, I'm obsessed with soft coding, I'm always trying to left the actual engine clear and take all the information from external sources. And I'm asking the following questions because a lot of people asked me why don't I just hardcore everything. Which makes me doubt, because I'm not sure. Is soft coding a good practice, or is it useless? Should I leave at least some of the game data inside the engine or should I leave it totally clear to make the code more flexible and versatile? BTW, I'm developing a MMO. I believe it depends a lot of what you are developing, with a Tetris I wouldn't do this, but... With a MMO I think it turns useful. For example, I'm using scripting to handle the creatures AI. Some would say, why don't you inherit from an parent class and add some specific behaviors... And I actually have no point there... I have all my maps, scripts, items descriptions, sprites, configurations as external files; that consumes more processing power and makes the game heavier but I make all that code reusable, don't I?

Share this post


Link to post
Share on other sites
you might want to have 3 layers

at the bottom would be the engine, it would be basically be what you have now, as light as possible and no specific details of the game

in the middle you'd have game specific code that is still in the native language, you could put a lot of ai behaviors function here

at the top would be the scripting level, it could have ai and items but it would just be a few variables and function calls so most of the work would be done by the middle layer

Quote:
Original post by coder84
Is soft coding a good practice, or is it useless?

that dosen't really have a answer, hard coding everything isn't a good idea but soft coding everything defeats the purpose of having a having a separate scripting system, for the time being just do what works for you,

just try to keep in mind what parts of the system will be preformance bottlenecks and what you can cache at startup

Share this post


Link to post
Share on other sites
Hmm, I see your point. I agree in most of it, most of the object behaviors which, won't change should be written in the middle layer.

But doing that I'm not sure about how to handle, exceptional NPCs (for example inside a quest), which have to change its routines. As it written up inside the game, I couldn't change it. Instead, scripting I would. I should make a script (a copy of the original), and change what I want to change. With fixed code, I couldn't.

For example, if I want a Wolf not to attack, when its coded to attack the user, I couldn't change it because is fixed.

Probably I will use default creatures, with the code of the middle layer and make a script if I want to make one different.

Quote:
that dosen't really have a answer, hard coding everything isn't a good idea but soft coding everything defeats the purpose of having a having a separate scripting system, for the time being just do what works for you,


I didn't understand that =/

Equally, there is something I didn't say yet... My scripting language is the same that the language I'm using to program. As C# has a code reader, it can read C# code from any file. Even if its extension is not ".cs". So is pretty easy to me to make the scripts, if thats what you trying to say.

Thanks for replying!!

Share this post


Link to post
Share on other sites
Quote:
Original post by coder84
Quote:
that dosen't really have a answer, hard coding everything isn't a good idea but soft coding everything defeats the purpose of having a having a separate scripting system, for the time being just do what works for you,


I didn't understand that =/

i suppose that could have been clearer
basically i was trying to say that learning to use soft code is definitely a good thing but it doesn't mean soft code is the best solution 100% of the time (like any other technique)

Quote:
Original post by coder84
Equally, there is something I didn't say yet... My scripting language is the same that the language I'm using to program. As C# has a code reader, it can read C# code from any file. Even if its extension is not ".cs".

that makes a bit of a difference, iv never used the C# reflection api but i would assume its performance is almost the same as statically linking C# classes, so it really doesn't matter then since as long as you avoid unnecessary loading and compiling your scripts should run at the same speed as your engine.

Share this post


Link to post
Share on other sites
You are right.

Quote:
i suppose that could have been clearer
basically i was trying to say that learning to use soft code is definitely a good thing but it doesn't mean soft code is the best solution 100% of the time (like any other technique)


Soft coding is useful when dealing with big projects (like MMOs). It keeps the code clearer and it improves versatility and flexibility. But it is totally useless to use it while making a Pacman or Tetris. Is necessary to know when to.

Thanks for helping!

Share this post


Link to post
Share on other sites
For a quick hack, anything will do.

For any project which will need to be maintained, keeping your options open is always a good choice, as long as you stay realistic.

It's easy to get carried away and abstract too much. It's extremly easy to find a shiny new hammer, and then develop tetris toolkit that supports n-dimensional pieces using some numberical recipes library that represents piece topologies.

There's some rules though. One Java guideline states, that only numeric constants that should ever be hard-coded are values of 0 and 1. In Java, that's not such a bad practice, even if all you ever do declare static final (static const equivalent) variables.

But perhaps the most dangerous aspect that comes with hard-coding is overuse of static variables. They quickly add unwanted interdependancies which can no longer be removed without completely changing the design.

Share this post


Link to post
Share on other sites
Quote:
Original post by Kaze
Quote:
Original post by coder84
Quote:
that dosen't really have a answer, hard coding everything isn't a good idea but soft coding everything defeats the purpose of having a having a separate scripting system, for the time being just do what works for you,


I didn't understand that =/

i suppose that could have been clearer
basically i was trying to say that learning to use soft code is definitely a good thing but it doesn't mean soft code is the best solution 100% of the time (like any other technique)

Quote:
Original post by coder84
Equally, there is something I didn't say yet... My scripting language is the same that the language I'm using to program. As C# has a code reader, it can read C# code from any file. Even if its extension is not ".cs".

that makes a bit of a difference, iv never used the C# reflection api but i would assume its performance is almost the same as statically linking C# classes, so it really doesn't matter then since as long as you avoid unnecessary loading and compiling your scripts should run at the same speed as your engine.


Reflection in C#(Aswell as other language that support reflection) is extremely slow (compared to normal C# code).
In general you should Never use reflection in any area where performance is a concern.

http://msdn.microsoft.com/msdnmag/issues/05/07/Reflection/#S2
(Some good information about whats expensive and what isn't, and how to avoid the worst)

Share this post


Link to post
Share on other sites
Quote:
Original post by SimonForsman
Reflection in C#(Aswell as other language that support reflection) is extremely slow (compared to normal C# code).
In general you should Never use reflection in any area where performance is a concern.

http://msdn.microsoft.com/msdnmag/issues/05/07/Reflection/#S2
(Some good information about whats expensive and what isn't, and how to avoid the worst)

i no expert on reflection but once you have the class JIT'ed and the needed methods cached why would it still be slow?
(sorry if the answers in the link, i didn't really follow it)

Share this post


Link to post
Share on other sites
Quote:
Reflection in C#(Aswell as other language that support reflection) is extremely slow (compared to normal C# code).
In general you should Never use reflection in any area where performance is a concern.

http://msdn.microsoft.com/msdnmag/issues/05/07/Reflection/#S2
(Some good information about whats expensive and what isn't, and how to avoid the worst)


A MMO is an area where performance really concerns. And as C# reflection will be used every time an object appears (I was thinking on script every object), I must find another way.

I could use Lua instead of C# reflection. Or even better, define the classes inside the game, and take all the data of the instances from XML.

EXAMPLE:



class Monster
{
int HP, XP, Attack;
string textureSet;
bool RunsIfWonded;
float Velocity;
}




<Monster type="Wolf">
<HP>120</HP>
<XP>18</XP>
<AttackMin 10/><AttackMax 22/>
<RunsIfWonded>false<RunsIfWonded/>
<Velocity>0.25f</Velocity>
</Monster>

But doing that, I couldn't set its behavior. I would only set its properties.

What you suggest?

Share this post


Link to post
Share on other sites
[quote]Original post by Kaze
Quote:
Original post by SimonForsman
Reflection in C#(Aswell as other language that support reflection) is extremely slow (compared to normal C# code).
In general you should Never use reflection in any area where performance is a concern.

http://msdn.microsoft.com/msdnmag/issues/05/07/Reflection/#S2
(Some good information about whats expensive and what isn't, and how to avoid the worst)

i no expert on reflection but once you have the class JIT'ed and the needed methods cached why would it still be slow?
(sorry if the answers in the link, i didn't really follow it)[/quote


Quote:

source:http://msdn.microsoft.com/msdnmag/issues/05/07/Reflection/
Invocation mechanisms can be divided into three categories: early-bound, late-bound, and a hybrid of early- and late-bound invocation. Early-bound invocation mechanisms result from direct intermediate language (IL)-level instructions (call, callvirt, and calli), interface calls, and delegate calls. These early-bound call mechanisms are typically emitted statically by compilers at compile time, where the compiler is supplied with all of the required information about the target to be invoked. These early-bound cases are significantly faster than their late-bound and hybrid counterparts as they map down to a few x86 instructions emitted by the JIT or native code generation (NGEN) compilers. Aggressive optimizations can also be made by the JIT because the call site and method are unchanging and are well known to the runtime.

The late-bound cases are MethodBase.Invoke, DynamicMethod via Invoke, Type.InvokeMember, and late-bound delegate calls (calls on delegates via Delegate.DynamicInvoke). All of these methods come with significantly more negative performance implications than the early-bound cases. Even in the best case, they're typically an order of magnitude slower than the slowest early-bound case. Type.InvokeMember is the slowest of the late-bound invocation mechanisms because there are two functions that InvokeMember needs to perform to properly invoke a member. First, it must figure out the exact member it's supposed to invoke, as determined by the user's string input, and then perform checks to be sure the invocation is safe. MethodBase.Invoke, on the other hand, doesn't need to figure out which method it must call because the MethodBase already holds the identity of the method.

To further explore how reflection sets up and invokes a member, consider a typical usage of MethodBase.Invoke:
-snip-


Basically the reflection API will be slow unless you only use it to load plugin classes(MSIL) using a known interface. (Comparable to loading DLL:s in C or C++ i guess).

There are methods around this though but none that would allow the use of C# as a proper scripting language without paying the standard performance price.

converting C# code to native at runtime is simply too slow to work, normal C# programs are converted to optimized MSIL before distribution and the JIT compiler goes from optimized MSIL to optimized native. (takes a bit of time but as it can be done before the application starts it doesn't impact performance that much).

Quote:
Original post by coder84
Quote:
Reflection in C#(Aswell as other language that support reflection) is extremely slow (compared to normal C# code).
In general you should Never use reflection in any area where performance is a concern.

http://msdn.microsoft.com/msdnmag/issues/05/07/Reflection/#S2
(Some good information about whats expensive and what isn't, and how to avoid the worst)


A MMO is an area where performance really concerns. And as C# reflection will be used every time an object appears (I was thinking on script every object), I must find another way.

I could use Lua instead of C# reflection. Or even better, define the classes inside the game, and take all the data of the instances from XML.

EXAMPLE:

*** Source Snippet Removed ***

<Monster type="Wolf">
<HP>120</HP>
<XP>18</XP>
<AttackMin 10/><AttackMax 22/>
<RunsIfWonded>false<RunsIfWonded/>
<Velocity>0.25f</Velocity>
</Monster>

But doing that, I couldn't set its behavior. I would only set its properties.

What you suggest?


Lua would be just as slow, or even slower, its not a problem with C# specifically.

The question really is : would it be too slow ?

"Every time an object appears" doesn't sound too bad. (unless you have hundreds of thousands of objects appearing every frame)

Oh, and when i said Areas i meant parts of the code. Even an MMO have some areas of the code that will run thousands of times each second (or maybe even millions of times / second), those are the areas where you want to avoid reflection.

On an entity (Monster, NPC, etc) that is updated a few times / second or less it is hardly a big issue.

For an MMO your main concern will be bandwidth, not CPU time. (You might want to avoid heavy reflection use on the client though as you want the game to run smoothly on as old hardware as possible)

[Edited by - SimonForsman on April 8, 2007 5:42:30 PM]

Share this post


Link to post
Share on other sites
Quote:
Lua would be just as slow, or even slower, its not a problem with C# specifically.

The question really is : would it be too slow ?

"Every time an object appears" doesn't sound too bad. (unless you have hundreds of thousands of objects appearing every frame)

Oh, and when i said Areas i meant parts of the code. Even an MMO have some areas of the code that will run thousands of times each second (or maybe even millions of times / second), those are the areas where you want to avoid reflection.

On an entity (Monster, NPC, etc) that is updated a few times / second or less it is hardly a big issue.

For an MMO your main concern will be bandwidth, not CPU time. (You might want to avoid heavy reflection use on the client though as you want the game to run smoothly on as old hardware as possible)


Well, thats a relief. Talking of hundreds of thousands will only appear while sending and receiving messages from and to the server (where no reflection at all is used). Remember that the creation of objects only happens in the server-side, so joining everyone they may make some thousands... It may need a bit more of processing power, but it worths it.

Share this post


Link to post
Share on other sites
Quote:
Original post by coder84Well, thats a relief. Talking of hundreds of thousands will only appear while sending and receiving messages from and to the server (where no reflection at all is used). Remember that the creation of objects only happens in the server-side, so joining everyone they may make some thousands... It may need a bit more of processing power, but it worths it.


Think one step further.

How often do values change? Do you, in an MMO, update every single creature at every step of game loop?

Most time will be spent serializing the data. This is simply due to exponential increase in number of messages that need to be sent.

In addition, even in active areas, do objects really change frequently?

So even if you use reflection, you can always cache (as blobs) serialized form of an object. And if that object changes, just discard the blob. If you only use this blob 3 times, you've probably saved enough CPU to offset benefits of introspection.

What about world updates?

Which attributes are very likely to change every loop? Location, orientation, health and energy. That's it. Those should be hard-coded. Everything else can be fully introspectable.

You level up once every few hours. You examine 1 object every 5 seconds. Gain an ability every few hours. Acquire a badge every few hours.

Inventory and other containers are handled differently anyway - container is once again fixed, but its contents are dynamic.

The general rule is that IO is the bottleneck. In 3D graphics, in networking, in disk access, even RAM (L1,L2 cache). IO will kill you, never processing power.

So the greatest drawback of using introspection would be losing locality of your data, hence taking cache miss performance decrease. But then again, in an MMO with hundreds of thousands of objects dynamically instantiated and destroyed, that locality will be small to begin with.

And once you consider all the different interactions you need to provide in such game, hardcoding anything is essentially a death sentence.

Just developing a better range search will help you increase the performance by a large factor.

Share this post


Link to post
Share on other sites
Quote:
Original post by coder84
So... Is it OK to use reflection or is it totally bad? ( I didn't understand =/ )

If its bad, what do you suggest without sacrificing versatility and flexibility?


It is not bad, my original reply was to kazes assumption that it would perform almost as well as statically linked classes. (it doesn't unless you only use the basic parts (then it can get quite close but isn't really that flexible))

Versatility and flexibility comes at a price, Reflection is one of the cheapest ways of getting it(it is cheaper than interpreted scripts) but it is still far from free.

My advice is to make things as flexible as you want it first, then profile it to see if it is too expensive and reduce flexibility in the areas where the cost is too great compared to the benefit. (In a large project the benefits are huge)

Share this post


Link to post
Share on other sites
One thing that I don't really get, Coder84, is how much of the AI Behavior are you actually scripting. You should use stuff like variables to control the behavior:

Your example was a wolf that, instead of attacking the player, would just stand there. Then why not add an "agressiveness" variable to your class so you can control whether it does attack or not? You can follow with this line of thought: add a variable to control almost every behavior of your entity, so you script only what is really necessary.

Then, if that is not enough use scripting to "override" the default behavior of your entity. I think the rule of thumb here should be, if you are going to have a certain class/behavior instantied too many times in your game, then have it hardcoded. Specializations or specific stuff that happens only every once in a while can be put aside and cached during the load or even on the fly.

I believe that even goes to textures and models. You can speedup a bit of loading time by hardcoding a model that is used a 1000 times on your application. The tradeoff is that it'll take longer to open your application (since it's executable is fully loaded into memory before execution), and you also lose memory and control over where will your data-structure be (parts of executables can be paged and stored on the pagefile, I think).

And another sugestion: you can use precompiled assemblies and use then as "plugins", the same way that dlls goes on C++. So, that's the same as having scripts in C#, but the difference is that you compile everything before actual run, which speeds loading time and execution performance. Link with then through reflection during run-time so you still gain flexibility.

If you follow my last suggestion, I suggest you think about a 4 layered application (or think that your application 2nd layer have two sub-layers):

1. Engine Core
2. Customization Layer
2.1 Hardcoded Customization (base class to use inside your MMO)
2.2 External Customization (derived classes declared inside assemblies)
3. Scripts

This way you can balance performance and flexibility. If you think a certain NPC or monster have to act in a very specific way, just add a script to it. If that monsters is going to be instantiated 1000 times each 10 minutes, consider moving the script to an assembly. If the monster will be used in future games or can be used as samples, you can move it up to the Hardcoded Customization layer.

Becareful not to overcrowd layer 2.1 or you might endup inflating your executable. Load 2.2 only during runtime.

Share this post


Link to post
Share on other sites
Great ideas! Now I understand a bit more how this works.

You are right about when to use scripting and when to hard code. If I want to make an object to act in a very specific way I'll override that hard code with a script. If I'll use that script a lot of times, I should move it to an assembly.

Quote:
And another sugestion: you can use precompiled assemblies and use then as "plugins", the same way that dlls goes on C++. So, that's the same as having scripts in C#, but the difference is that you compile everything before actual run, which speeds loading time and execution performance. Link with then through reflection during run-time so you still gain flexibility.


When you talk about precompiled assemblies you mean .cs files? It would be a good idea. I load them before the actual game starts and I have both, performance and versatility improved. (Sorry if I misunderstood).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this