Help with many script instances

Started by
3 comments, last by arpeggiodragon 13 years, 7 months ago
Hi, I'm trying to get a basic frame for an object class working the way I need it too. Every instance of these types of objects needs to call a script function every frame, and ideally I would like to have up to a few thousand objects (and scripts) active at any given time.

Here is what basically what I have so far:
class Object{public:	Object()	{		r = 0;		type = engine->GetObjectTypeById( engine->GetModule(0)->GetTypeIdByDecl("MyClass") );		funcId = type->GetMethodIdByDecl("void func()");		obj = (asIScriptObject*)engine->CreateScriptObject( type->GetTypeId() );	}	~Object()	{		engine->ReleaseScriptObject( (void*)obj, type->GetTypeId() );	}	int Update()	{		if( r == asEXECUTION_FINISHED )		{			ctx->Prepare( funcId );		}		ctx->SetObject(obj);		r = ctx->Execute();		return r;	}	int r;	int funcId;	asIObjectType *type;	asIScriptObject *obj;};

So here are my questions:

Can I get rid of the Prepare() call? -I read that this was a very slow call. I always want the function 'prepared' for fast accessing, yet after it returns asEXECUTION_FINISHED it's gone forever. Can I reuse it, or can this be reference counted somehow?


Is is there a better method for achieving the same type of functionality, or general ways to optimize it? I'm new to AngelScript so I'm still fumbling around the documentation. It's a really awesome library, I just wish I knew how to use it better. Any suggestions are welcome.

Thanks.
Advertisement
Prepare() is not so slow. If you reuse the same context for each execution the Prepare() method will save time by reusing memory that has already been allocated. Also, if Prepare() is called for the same script function that was executed before it doesn't have to do almost anything.

Don't worry so much about the Prepare() call. It really has to be called for each new script function that you're going to call, as it is the one that sets up the context for that that execution. Without the Prepare() call, the context wouldn't know what to do when you called Execute.

You already seem to be caching the information that should be cached, like the funcId, type, etc. Apparently the context is also reused, rather than created for each call. This is all you need to do, in terms of getting the most out of the script engine.

What you should think about is if you really need to execute the script function for all of the objects each frame. Most of the objects are probably waiting for some kind of trigger before they act, in these cases you could probably skip the execution completely. Even objects that are not just waiting can probably be executed only in intervals, maybe every 5th frame, without any noticeable difference in the behaviour.

Once you have the application up and running, there are some things that you can do to make AngelScript run faster, e.g. turn off multithread support (unless you need it), compile the scripts without line cues, use memory pooling, etc. But don't worry too much about this in the beginning.



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

Ah thank you very much. It's good to know I'm not doing it wrong. :D I will keep the latter points in mind also.


Quote:Original post by WitchLord
What you should think about is if you really need to execute the script function for all of the objects each frame. Most of the objects are probably waiting for some kind of trigger before they act, in these cases you could probably skip the execution completely. Even objects that are not just waiting can probably be executed only in intervals, maybe every 5th frame, without any noticeable difference in the behaviour.


Yes, you hit this one dead-on. Unfortunately they do need to be called every frame, or more accurately, when the script demands it. The answer in this case I think is to implement a global "void wait(int frames)" script function that will halt script execution of the script for x frames. ..However I ran into a problem.

if( r == asEXECUTION_SUSPENDED && --suspend > 0 )  return;else  //run scriptvoid Object::SuspendThis( int frames ){  suspend = frames;  engine->Suspend();}///script calls this c++ sidevoid Wait( int f ){  //??? vector<Object*>[num]->SuspendThis(f);}


I don't see how to find the correct instance that the function callee is attached to. Is this possible?
If the function is called from the script you can call the global function asGetActiveContext() to obtain the current context. From that you should be able to determine the object instance, either by getting the object pointer from the callstack directly (asIScriptContext::GetThisPointer()), or by using the user data (asIScriptContext::SetUserData()).

You seem to be planning on having the scripts run infinite loops and then run them in parallel. The Context Manager add-on could you help you with that. However, consider that each running script would have to keep its own instance of an asIScriptContext, which would eat a considerable amount of memory (since each holds its own callstack of 4KB by default). Not that this is a problem by itself, but you should be aware of it.

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

Actually I decided against multiple contexts so these all share a single global asIScriptContext. I've also managed to get everything else working simply by adding a "->setActivePtr(this)" for tracking cpp instances calling script objects. Works like a charm!

Thank you for your help.

This topic is closed to new replies.

Advertisement