Jump to content

[SOLVED] Sharing user classes within Unigine.cpp script


photo

Recommended Posts

Hello !

 

I am currently seeking for a scripting functionality that I can't really find.

 

Problem:

I would like to share a user class across each World scripts. This class could handle and save some attributes for example (it is like some kind of "singleton" pattern).

 

According to the documentation, I have foundb(from https://developer.un...stem.get_string) :

 

variable engine.system.get(string var)
Description
Returns a variable from the system script. Instances of user-defined classes cannot be requested in such a manner.
Arguments
string var - Variable name with a namespace, if needed.
Return value
Requested instance.

 

As you could read :

Instances of user-defined classes cannot be requested in such a manner

 

And it is true, trying to share user class in such a manner lead to Unigine crash.

 

 

Could you please give me some tips on how to achieve that kind of task ? (I believe I could write my own C++ plug-in that will expose my user class to Unigine script and ensure "singleton" pattern but I think it is a bit too "complicated" only for that)

 

Thanks for reading me !

Link to comment

Unigine only runs one world script at a given time so you don't normally need to do any of this.

You might want to send objects between the world,system and editor scripts in which case it is easier to pass messages to the scripts that own the objects rather than pass objects between them. The other senario I could think of is passing data between multiple clients in which case the network libraries are the best way to do this.

Link to comment

Let's say we have 20 levels in our application, where a "player" could have a custom state (items, skills, tasks to do, etc.) (like in scratch project where user have a name and it's shared across each "level" worlds). It will be more convenient (and logic to me) to store all theses attributes in a class at runtime (and share it around each world).

 

Otherwise, it is possible to write a custom file that contains all theses attributes at a level end and then reload it in the next one to get access to needed informations, but I don't really like that ...

 

Do you have any other way to give a class to another script ? I don't see anything else in the documentation :-/

 

Thanks !

Link to comment

Hi,

 

You can save info in system script. Let's say that you have this structure in your world script:

 

class Item {

private:

 string name;
 int price;

public:

 Item(string n,int p) { name = n; price = p; }
 ~Item() { }

 string getName() { return name; }
 int getPrice() { return price; }

};

class Player {

private:
 Item items[0];

public:
 Player() { }
 ~Player() { items.delete(); }

 int getNumItems() { return items.size(); }

 void addItem(Item item) { items.append(item); }
 void clearItems() { items.delete(); }
 Item getItem(int index) { return items[index]; }
};

 

And you want to save player state between worlds. You can rewrite that structure to this:

 

namespace PlayerState {

class Item {

 private:

  string name;
  int price;

 public:

  Item(string n,int p) { name = n; price = p; }
  ~Item() { }

  string getName() { return name; }
  int getPrice() { return price; }

};

Item items[0];

int getNumItems() { return items.size(); }

void addItem(string name,int price) { items.append(new Item(name,price)); }
void clearItems() { items.delete(); }

int getItemPrice(int index) { return items[index].getPrice(); }
string getItemName(int index) { return items[index].getName(); }
}

 

Put this structure to system script and use engine.system.call methods to retrieve player state from system script any world script.

 

Also, if you have complicated Item and Player classes, you can save them to xml file and load in world script init function.

And one more way: you can store simple state in system script (player name, items id, whatever id) and reconstruct complicated player state in world script based on system script state.

Link to comment

Hello,

 

Thank you for this demonstration.

 

So there is not any other way to share user classes :(

 

Do you know what are the costs (in performance) for calling "engine.system.call" each frame instead of directly calling a class member ?

 

Thank you !

Link to comment

engine.system.call performance is similar with engine.world.call, but it's still slowly than direct function call or call by function id. The performance loss depends on where your function is placed in the code. It's better to avoid each frame calls.

 

Also, in Oil Rush we're storing players and game states in system script and creating full copy in world script for runtime purposes. So, the best way for you is to store simplified state in system script and create performance friendly full state in world script. It'll take some time on initialization, of course.

Link to comment

In fact my whole "problem" is like this :

 

I have an external peripheral that I get camera coordinates from. This peripheral must be initialized once in the application run time because it costs time.

 

What I would have wanted to do is : load exported class in Unigine.cpp script via custom plugin and open peripheral and share that class around each worlds to get coordinates from

 

But accordingly to you it is not possible ;)

 

So I will have to do everything directly in the c++ Plugin class and then only export accessors methods.

It is just a different thinking about how to use Unigine Script and develop Plugins :(

Link to comment

Yeah, sure, the basic idea is to export high-level systems to the script and did all hard work in C++ plugins. So, it might be tricky to think this way, but you'll get proper division between C++ part and UnigineScript and this should bring hapiness to the world. ;)

Link to comment
×
×
  • Create New...