# Unity A new, C++-meant-for scripting language: IonScript

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

## Recommended Posts

Hello dear community,

I would like to present a new lightweight scripting system I've been working on during the last couple of months. It is called IonScript and it has entirely been made in modern C++ for easy embedding in C++ applications.

Some time ago I was looking for an easy to use and straightforward to embed scripting language for my everyday game development. The only real solution I found was LUA of course, but I am somewhat against cumbersome language-to-language API wrappers while I found the native C LUA API requiring a lot of extra code for real embedding in C++ applications. For this and more reasons, I started working on IonScript and I recently reached a pretty usable release. I am actually using it in my new indie game for several scripting environments (from resource loading, to world generation procedures, to AI, to game logics).

You can find a detailed page about the language at the official page.
While the source code can be found on Github.

The language has a trivial syntax, with some sugar, it handles null, numeric, string, boolean, list, dictionary, managed and unmanaged object values and it is extremely lightweight.

Making any of your existent classes internally scriptable or building from ground-up a complete scripting system tied to your needs is only a matter of minutes.

For any question, information, help, request and, especially, critics feel free to post here or write me an email.

Sincerely,
Massimo

[Edited by - Keebus on October 18, 2010 11:53:44 AM]

##### Share on other sites
Hrm, interesting! I'll have to check this out and see how easily I can integrate it with my engine. Since I just started thinking about supporting script languages, this could be a good time for me to try this out. Thanks for the time and effort in providing developers other options!

##### Share on other sites
Good news! Well,I've been working on this for a while, and I'm currently using it, but it would be a pity if others have my same needs and face the same lack of suitable technology. I'd be happy to give you any hint you desire for the testdrive.

##### Share on other sites
Sounds good! I'll send you a PM once I start to add this to my engine. If I have some time later on tonight after work, I'll see if I can add it then.

##### Share on other sites
I'm surprised someone hasn't griped about "LUA" vs Lua lol.

Anyways, I think your C++ embed impl is interesting.

is parsing a vector of byte code really fast? I think that will be your biggest challenge in trying to compete with Lua (along with the whole community support thing).

##### Share on other sites

The point is: is it really necessary? For "scripting" I intend a quick, easy, trivial way for driving your C++ application (which indeed should be fast!) using the (as limited as possible) API you set up for your specific scripting domain. I would like to give you a couple of examples.

Suppose you're writing (as I am) a world generator that simply generates a new whole world (full of details and tweakable parameters). You have a generate() method that properly calls a bunch of submethods for specific stages of the world generation. Each of this private methods take quite a few parameters (map size, number of cities, perlin noise persistence, scale, octaves, etc). During the tuning process, it's normal to change parameters continuously to get to the best result. You definitely know how long a compilation can take.

This is surely a case where you would use IonScript. Take your World class and inherit from script::VirtualMachine. Add one single private static method to your class to handle multiple script-side functions and properly call your own methods. Make the generate() method call your own script placed somewhere. In a matter of minutes (this is what it took me) I have a system that can be tuned at runtime, and can even contain a pretty complex logic.

The second example consists of AI scripting. IonScript makes latent functions simply trivial. This means that script-side functions and host-side functions are decoupled, and a single script-side funciton can "last" a few game cycles. Take a look at the following snippet (it is meant to run within a kind of NPC C++ class).
agent = get("agent") // retrieves the value "agent" from the global values                     // you set from C++enemy = agent.findEnemy()agent.kill(enemy)

Here both findEnemy() and kill() are latent functions. So for example findEnemy() says "agent, go looking for an enemy now and continue when you find it" so that the function actually returns when the enemy is found, which can take seconds, minutes.

So the whole point is: IonScript is not meant for the purposes you were talking about. Parsing an array of bytes, or a bunch of ugly XML would be possilbe ONLY IF you implement needed functions in your C++ program and you provide an interface to the IonScript to call them.

Please let me stress this point one last time. IonScript is made for embedding, more like a "driver" language that drives your C++ objects/functions easily. It is not a general purpose language such as Python, Ruby (or even Lua), but it is strictly related to your own scripting needs (built-in functions are in fact less then ten).

Despite all this, IonScript is yet pretty fast. It compiles really quickly and some benchmarks perform even better than Python in some cases. Anyway, I haven't made too many benchmarks just yet since I'm pretty satisfied by its performance (both in compiling and execution).

Finally, I would like to invite you to try to embed the VirtualMachine in any of your existent classes and add some scripting facilities and see how small and intuitive the API is (in my humble opinion, of course).

It would be simply amazing if anyone of you smart guys gets interested and maybe collaborates for the development of the remaining features. Simple testing is absolutely good too.

p.s.: I'm sorry for eventual english grammar mistakes, I'm not a native speaker.

[Edited by - Keebus on October 18, 2010 7:26:32 PM]

##### Share on other sites
I have a few problems with your statements.
Lua as has been pointed out is the correct name not LUA, this implies to me that you do not know the language or it's "cumbersome" C API, which leads nicely onto my second point why is it cumbersome?

Quote:
 in the real world, it is often strongly suggested to write the glue-code by hand.

Why is this the case? Did you pull this one out of the air?

Quote:
 No need to reinvent the wheel.

I had to laugh because this seems exactly what you have done :)

I had a quick look at your code and one thing stood out to me in "Values.h"
inline bool checkObjectType (const std::type_info & type) const {            return strcmp(mObjectTypeName, type.name()) == 0;         }

Firstly type_info.name is not guaranteed to be unique even in the same executable and secondly type_info is not guaranteed to be the same for the same type in two executables. The fact that you are actually using type_info is also somewhat of a surprise as you seem to be aiming at game developers, which also calls into question using exceptions.

The following is personal opinion but it annoys me every time I see it.
   if (mpProgram)      delete mpProgram;

There is a couple of times when you use a union and read data without knowing what the type is, the result of which is undefined.
   type = child.type;   memcpy(&child.number, &number, sizeof (double));

Then there is the case when you are comparing a double to 0.0, what happens if the double is a calculated value?

The biggest problem I would have with your library maybe is the function handling, seriously is it good design to have a big switch statement for "function groups"?

Overall the library show potential yet without knowing have fast it is, without being able to disable exceptions and runtime information I personally could not recommend it; yet these are all things which can be easily fixed.

##### Share on other sites
Quote:

Quote:
 in the real world, it is often strongly suggested to write the glue-code by hand.

Why is this the case? Did you pull this one out of the air?

This is indeed not always true. If the it are simple functions like IncrementByOne(Value) functions, a glue-code generator will do fine. Only when the functions get real complicated (more then 5 parameters, standard parameters, overloads, etc.) it might be better to do it yourself. But only if you know exactly what you're doing.
I do agree that it is very useful to know how the glue-code works.

Quote:
 The following is personal opinion but it annoys me every time I see it.*** Source Snippet Removed ***

Why? This is just used when you already have started a program.
I see problems with deleting the program right after execution. What if you want to extract values after execution? You would need to add a lot of host functions.

Quote:
 The biggest problem I would have with your library maybe is the function handling, seriously is it good design to have a big switch statement for "function groups"?

It's not a bad idea. You can have a function in the VM to add a single function. But that would also result in long code as well.
- It are simple integer comparisons, those are really fast on a computer
- Divide you functions into multiple groups. Instead of adding all the functions into a single group, put them into multiple ones. One for global stuff, one for geometry stuff, etc.
- Put the functions that 'need' speed at the start of the switch. The function 'exit' doesn't exactly need speed so you can put it at the bottom. It doesn't matter if it has a lag of a 1/100 second.

I do see a lot of potential. But you should also build a standard library for it. Stuff like containers (a equivalent of std::vector for example) and file IO (if you like). Since you will (sooner or later) find out that if your language doesn't support these tings, you have to do A LOT to get longer scripts working properly.

assainator

##### Share on other sites
Quote:
Original post by assainator
Quote:
 The following is personal opinion but it annoys me every time I see it.*** Source Snippet Removed ***

Why? This is just used when you already have started a program.
I see problems with deleting the program right after execution. What if you want to extract values after execution? You would need to add a lot of host functions.

He meant:

http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.8

Did you try luabind (http://www.rasterbar.com/products/luabind.html)? It also does miracles in a matter of minutes.

##### Share on other sites
Quote:
Original post by noe
Quote:
Original post by assainator
Quote:
 The following is personal opinion but it annoys me every time I see it.*** Source Snippet Removed ***

Why? This is just used when you already have started a program.
I see problems with deleting the program right after execution. What if you want to extract values after execution? You would need to add a lot of host functions.

He meant:

http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.8

Oh didn't know that. Sorry.

But now that I'm reading it, I am wondering why I get a runtime error whenever I try to delete a variable that is NULL.

assainator

Thanks

• 11
• 19
• 10
• 11
• 12
• ### Similar Content

• So I am building a turn based rogue-like (think CDDA). The game is going to have a very large map (up to 1000's x 1000's) however to alleviate most of that I obviously can't render everything so there will just be render a certain radius around the player and just load in and out data as the player moves.
The next major system I am prototyping is making interactive tiles destructible and pretty much everything will be destructible besides basic landscape (cars, doors, windows, structures, etc. will be destructible)
While I am only rendering a certain amount of tiles around the player, I want to keep the amount of colliders active at one time to be as small as possible for performance and currently the tilemap tool I use automatically merges colliders together.
So instead of creating a separate colliders for each of these tiles and having the destructible behavior tied to that object (which my tilemap tool would allow me to do) I was thinking that I would store an array of all the X and Y locations for the interactive tilemap layer and let the tilemap manage the colliders.
Then when I hit a collider on the interactive tilemap layer, instead of of getting the behavior for how to deal with the destruction for that tile from that game object, I would pull it from the array I mentioned earlier based on the tile I attempt to interact with which I already have.
Does this sound like a good approach? Any other recommendations would be welcomed.

• Hey guys,
I have a really weird problem. I'm trying to get some data from a REST service. I'm using the following code:

private void GetTheScores() { UnityWebRequest GetCommand = UnityWebRequest.Get(url); UnityWebRequestAsyncOperation operation = GetCommand.SendWebRequest(); if (!operation.webRequest.isNetworkError) { ResultsContainer rez = JsonUtility.FromJson<ResultsContainer>(operation.webRequest.downloadHandler.text); Debug.Log("Text: " + operation.webRequest.downloadHandler.text); } } The problem is that when I'm in Unity's editor, the request doesn't return anything (operation.webRequest.downloadHandler.text is empty, the Debug.Log command just prints "Text: "), but when I enter the debug mode and insert a breakpoint on that line, then it returns the text properly. Does anyone have an idea why is this happening?
The real problem I'm trying to solve is that when I receive the text, I can't get the data from the JSON. The markup is really simple:
[{"id":1,"name":"Player1"},{"id":2,"name":"Player2"}] and I have an object that should accept that data:
[System.Serializable] public class ResultScript { public int id; public string name; } There is also a class that should accept the array of these objects (which the JSON is returning):
[System.Serializable] public class ResultsContainer { public ResultScript[] results; } But when I run the code (in the debug mode, to get any result) I get an error: ArgumentException: JSON must represent an object type. I've googled it but none of the proposed solutions work for me.
Also (regardless if I'm in the debug mode or not) when I try to do some string operations like removing or adding characters to the GET result, the functions return an empty string as a result
Can you help me with any of these problems?
Thank you
• By nihitori
The Emotional Music Vol. I pack focuses on beautiful and esoteric orchestral music, capable of creating truly emotive and intimate moods. It features detailed chamber strings, cello and piano as the main instruments, resulting in a subtle and elegant sound never before heard in video game royalty-free music assets.

The pack includes 5 original tracks, as well as a total of 47 loops based on these tracks (long loops for simple use and short loops for custom / complex music layering).

A 15 seconds preview of each main track is available on Soundcloud:

• Another one of our new UI for #screenshotsaturday. This is the inventory screen for showing what animal fossils you have collected so far. #gamedev #indiedev #sama

• We're looking for programmers for our project.
Our project is being made in Unity
Requirements:
-Skills in Unity
-C#
-Javascript
-Node.js
We're looking for programmers who can perform a variety of functions on our project.
Project is a top-down hack-and-slash pvp dungeon-crawler like game. Game is entirely multiplayer based, using randomized dungeons, and a unique combat system with emphasis on gameplay.
We have a GDD to work off of, and a Lead Programmer you would work under.
Assignments may include:
-Creating new scripts of varying degrees specific to the project (mostly server-side, but sometimes client-side)
-Assembling already created monsters/characters with existing or non-existing code.
-Creating VFX
This project is unpaid, but with royalties.

---