Advertisement

Changing the content of global variables from C++

Started by April 05, 2014 09:26 PM
7 comments, last by DevilWithin 10 years, 7 months ago

Hello,

I don't know if I am missing something in the documentation, but I don't seem to find a way to alter a global variable in a script.

Here's my use case:

I have a behavior script attached to an entity. This behavior script has a Update() function called every frame, and has the following global variable: Entity@ entity = null;

Since this behavior is attached to multiple entities, entity must point to the appropriate object every time I call Update().

But I can't seem to be able to make entity reference a valid object from C++, before calling the script function Update(). Any tips on how to do it?

The closest I've been was getting the global var address, which indeed points to null, as initialized. But I can't seem to make it reference the appropriate entity before calling Update()..

Thanks

Using GetAddressOfGlobalVar() I was able to change the variable for both object handles and primitives successfully. I was just wondering now if I am doing it the right way. Thanks

Advertisement

If you wish to change values of global variables in the script from the application side, then using the GetAddressOfGlobalVar() is the way to do it. For object handles you'll need to remember to release the previous object, and add a reference for the new object. For objects stored by value you can use the engine's AssignScriptObject() method to call the assignment operator.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Thanks Andreas! That helps :)

Also, could you refer me to the right API for calling a member function on the script? For example, in script I have:

class CustomBehavior : BaseBehavior

{

void onEvent(){}

}

Can I call onEvent() from the application side directly? Either as a static class method or by calling it on a object previously created, of type CustomBehavior.

Thanks

Manual: Calling a method on a script class

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Advertisement

Thanks Andreas, for the quick help! Two problems solved! I am currently implementing AngelScript for the second iteration of my engine, Nephilim 2. It is coming out as a full blown pre compiled engine, with full scripting support to make any kind of game with it, 2D or 3D :) So far, so good, thanks for the awesome library.

I have one more question, if you don't mind. The documentation is good, but sometimes I fail to find/understand the right tool for the job in there.

I attach behavior scripts to my game world's entities. Then, every game tick, I call Update() on my behavior, so it does something with its parent entity.

To do this, the script has access to an entity variable, an handle to a Entity object. For now, the Entity class is basically a collection of pointers to components. So, entity.transform is either a valid transform or null. The same applies to other components like terrain, camera, light, mesh, collider, sprite etc.

The problem is that the amount of component types is growing fast and its a really bad design decision to list every component type available as a field in the Entity class. For example, a entity with only a Transform, will still have dozens of pointers to components taking space, even if they are all null. Even worse, when I create a component dynamically through scripts. Because of this I need a way to dynamically get the component by a identifier string/integer.

In C++, I would solve it by having a template function, which I'd call as entity.getComponent<BoxCollider>(); It would return null if there was no BoxCollider or the reference to the actual BoxCollider instance. Is this doable with angelscript?

I need to access the entity's components dynamically either with type, integer or string. As simple as possible, if possible, any ideas? :)

There are multiple options.

You can do something similar to what the dictionary add-on does. It has a get method that retrieve the stored component using a name as the key, it will then cast the value to the type that the script is expecting

Or you can register property accessors, where the name of the accessor method tells the application what to return. It would even be possible to use only 1 implementation on the C++ side that dynamically decides what to do to based on what the script calls, then register the same function/method with multiple names for each component type, or you can implement each accessor (possibly with the getComponent<T>) method you already have.

If you decide to do a single implementation, then you'll need to determine the name of the property accessor that is called from the script dynamically with something like this:

void *Entity::getComponent()
{
  asIScriptContext *ctx = asGetActiveContext();
  asIScriptFunction *func = ctx->GetSystemFunction();
 
  // Determine which component the script wants by the name of the function that is called
  string name(func->GetName());
  if( name == "get_transform" )
     // return the transform component
  else if( name == "get_model" )
     // return the model component
 
 
}

If the method is registered as returning the type by handle, i.e. @, the ref count must be incremented unless the return is null.

If the method is registered as returning the type by reference, i.e. &, then the ref count shouldn't be incremented and value types can be used too, but on the other hand you will not be able to return a null pointer. Instead you'll need to raise an exception if the component doesn't exist, or return a reference to a dummy component.

Regards,

Andreas

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Thanks Andreas, again!

All those solutions seem promising, and since there is no ideal solution ( a template function), I will pick one of those, probably the one with the casting to the right type :)

My Regards,

Artur

This topic is closed to new replies.

Advertisement