[.net] Easy Scripting in .NET

Started by
72 comments, last by ppp_vcf 16 years, 5 months ago
Why not use Lua or Python as your scripting language. It seem much easier to use those and modify your engine variable with less work. I am currently using python in my engine :)
Advertisement
Why would using python or lua from a managed language be easier? As described in this thread, the .net framework provides the means to compile code at runtime very easily, and you can place security restrictions on it. Why go through the hassle of creating python bindings when that exists? Besides, a python script will almost certainly run slower than a c# script.

As for how to interact with the c# script, why not declare some base classes that scripts are required to derive from?

For example, suppose you need a script for an npc. Just create an abstract class or interface that has all the properties and functions that the engine may need to manipulate, then implement them in the script.

So in a library used by your engine, declare an abstract class Npc. I prefer abstract classes here, because then you can define a constructor and some basic characteristics shared by all npcs. This is obviously a very simple case:

public abstract class Npc{    public Npc( int hitPoints )    {        mHitPoints = hitPoints;    }    private int mHitPoints;    public int HitPoints { get { return mHitPoints; }}    public abstract void BattleCry();}


Then in a script that's compiled runtime, and refers to the assembly containing the abstract class:

public class BlackKnight    : Npc{    public BlackKnight()        : base(100)    { }    public override void BattleCry()    {        // Do something suitable here, and specific to the black knight.        // Like display text or play audio saying "Knaves!  Have at thee!"        // If this was a dragon, it could roar here, or a banshee could wail, etc.    }}


After compiling, you can reflect into the script's assembly. If a class isn't derived from a valid base type like Npc, it's rejected.

In the end, all the engine sees is a bunch of npcs, but they all do different things when the engine calls NPC.BattleCry, depending on how it was implemented in the script.

You could expand on this further, by creating more base types in scripts. For example, a Dragon type that's derived from Npc, which also has BlackDragon, BlueDragon, RedDragon, etc derived from it.
I don't find it slow at all, plus binding is easy if you IronPython or Lua.NET which is simple to use. Everything i wrote in it works perfect for me with no speed issue.
Thanks gharen2, that answers my question pretty good. I already have an NPC class defined, the engine contains a set of GUI based development tools and one of the tools generates NPC characters. I guess what I will need to do is generate a C# script for each character created with the editor that use the default NPC methods and fields. The developers can then modify the script as they see fit to. Now, take the following example.

Script file:
public int LocationX = 0;
public int LocationY = 0;
public string world;
public string room;

Now, those values will be changing as the character moves about the world. Can I access those values from within my Engine? As for accessing values within the engine I understand that I can create keywords ([projectPath] as demonstrated by Headkaze) and string.Replace to assign the values to them as needed.

Thanks for any comments or advice!
Quote:Original post by ScionwestCan I access those values from within my Engine?


You can access those values from the engine the same way the engine would access the hitpoints value in my example. The engine is aware of the Npc class, and knows it has a hitpoint property. The value returned by it is determined by the script.

If this doesn't make sense, I have a basic scripting framework of my own, and can crank out a sample quickly enough (assuming I'm not asleep or at work when you reply, of course).

Quote:Original post by rpgmaker
I don't find it slow at all, plus binding is easy if you IronPython or Lua.NET which is simple to use. Everything i wrote in it works perfect for me with no speed issue.


Ah ok, you didn't say you were using IronPython or Lua.Net. Those both compile to the common intermediate language, so would indeed be just as fast as c#, assuming that the IL generated is equally optimized. You just said python and lua, so I was under the impression that you were interoping with the unmanaged versions.

Anyways doing things your way is really no different than the method described in this thread. It's just with a different language, and that's just a matter of personal preference. Personally I'd prefer my scripts in c# so that they'd work on the xbox 360. But if you're not interested in targeting the xbox, then by all means you should use whatever language you prefer. I personally despise pythonic syntax, but to each their own.

(Yes, I know the xbox compact framework doesn't allow runtime compilation of code, but with some ifdefs you could just incorporate the scripts directly into the project for the xbox version. The user won't be able to mod the xbox version, but you aren't supposed to be able to mod console games anyways).
Thanks gharen2, it makes sense now. I need to start workin on a sample project to give this scripting a try!

Thanks again.
Say for instance I am programming a 3d graphics game in c#. Perhaps, my scene class has something called AddEntity( int type, Point location, .... )

Using the c# scripter, would it be possible to have a console window where I can type in c# code from my project such as addentity and do this during runtime?
I doubt you could compile a single line. I'm pretty sure that the script has to be a complete source file.

You could get around this by having most of the script already stored in a string, and insert the line the user entered at the appropriate place.

So have the following string in memory:

using System;// Insert using statements for any other libs that the script may depend on.namespace Scripts{    public class ScriptContainer // A crappy name I know, but it's 1am and I can't think of anything better :P    {        public void Execute()        {            // Insert one liner here.        }    }}


So when the user enters the line of code into the console, the string containing that line of code is inserted into this one. Compile the script, and use reflection to invoke ScriptContainer's Execute method.
This seems to be very useful!
I'm wondering, is it possible to do this from VC++? I believe someone mentioned that using a managed middleman(code) worked quite well- any pointers?
I'm assuming you mean native, regular c++? I know there are ways of calling managed code from native c++, but that's well outside my experience. I do have a strong suspicion that it would be easier for you to just use python. Using python for scripting in a c++ apt is well documented and proven.

This topic is closed to new replies.

Advertisement