Jump to content

Multiple scripts and inheritance


Josh
 Share

  

17 members have voted

  1. 1. What do you think the resulting behavior should be?

    • Entity turns +1
      0
    • Entity turns -1
      3
    • Entity turns +1 then -1 (no net change)
      14


Recommended Posts

If we have multiple scripts attached to a single entity, should redundant functions override previously declared ones, or should the functions be executed in sequence?

 

Example of two scripts attached to an entity, in order:

function object:Update()
self.entity:Turn(1,0,0)
end

function object:Update()
self.entity:Turn(-1,0,0)
end

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

+1 -1 (no net change)

 

it's more interesting that way and useful too I would think

 

also it's what I'm used to from blender's logic bricks

Core I5 2.67 / 16GB RAM / GTX 670

Zbrush/ Blender / Photoshop CS6 / Renoise / Genetica / Leadwerks 3

Link to comment
Share on other sites

It should execute both scriptd as they are (+1, then -1). Developers can use the require statement to include other script they want to inherit and override, so the engine should not change and confuse the behaviour of Lua scripts.

Ryzen 9 RX 6800M ■ 16GB XF8 Windows 11 ■
Ultra ■ LE 2.53DWS 5.6  Reaper ■ C/C++ C# ■ Fortran 2008 ■ Story ■
■ Homepage: https://canardia.com ■

Link to comment
Share on other sites

It should overwrite the previous version of the same methods, since else you have no control to overwrite methods which you don't want. But you should be also able to call the overwritten method from the new method, else you have to rewrite all code in the new method. Then it works like C++, and the real developers don't have to learn a new language behaviour.

How would you suggest doing that? Something like this?:

function object:Update()
if self.super~=nil then
	if self.super.Update~=nil then
		self.super:Update()
	end
end
self.entity:Turn(1,0,0)
end

It seems like the "code blocks" paradigm really has nothing to do with C++ inheritance.

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

Best would be to have the choice. In C++, I can override a method but still (if I want to) call the base method.

Agree. I would execute in sequence all the same events except if one of them contains "new function" instead of "function", in that case only the "new function" should be executed, perhaps a bit annoying to implement but that should be a more flexible way.

 

Or let the developer to use a function to add an event handler in an event pool.

?? FRANCESCO CROCETTI ??

http://skaredcreations.com

Link to comment
Share on other sites

yeah I was thinking that you would dynamically activate/deactivate attach/unattach scripts during gameplay, so you could have a status effect script for "this unit is now drunk", and in that script you would have him continue to follow the movement instructions of his normal behavior, but then the "this unit is drunk script" which is dynamically activated at a certain time would then take that initially behavior and just alter it a bit. This way you can have one "Drunken unit" script and just dynamically assign it to whatever entity whenever necessary without having to completely define movement charistics for different entity types. It could work univerally. Then again my knowledge and understanding is admittedly limited.

 

This was my rationalle for +1-1(no net change)

 

you get really interesting dynamic outputs when the scripts interact in that way from my experience, and you can reuse scripts in a more universal non destructive manner because all the behaviors build on top of one another

 

anyone care to put my rationale in its place? Cuz like I said my understanding is limited - I'm probably not a real developer tbh :)

Core I5 2.67 / 16GB RAM / GTX 670

Zbrush/ Blender / Photoshop CS6 / Renoise / Genetica / Leadwerks 3

Link to comment
Share on other sites

If these scripts are intended as different actions to be executed in sequence, I think you should consider a DURATION parameter also. I mean something like (pseudo-code)

 

Entity.AddAction(action_script_1, 1000);

Entity.AddAction(action_script_2, 1500);

Entity.AddAction(action_script_3, 1000);

 

Where action_script_1, action_script_2, action_script_3 are different LUA script (maybe not necessarly related with the entity itself but with the entire scene) and 1000,1500,1000 is the duration of the 'action/script' (a -1 could be used to left to the action_script the duration/execution of itself).

 

Of course I think you need other 'Action commands' to clear the list, rearrange, loop it and so on.

 

Just an idea

Phenom II X4 955 Asus HD5770 4GB Ram WindowsXP Sp2 BlitzMax

www.graphio.net www.graphioware.com

Link to comment
Share on other sites

Best would be to have the choice. In C++, I can override a method but still (if I want to) call the base method.

 

This isn't really an option in this situation. He's talking about 2 completely different scripts (classes) attached to an object. In each script you are already overriding the Update() method. It just so happens that you have 2 scripts that both override the Update() method. Both scripts Update() method are going to be called by the engine. Josh just wants to know in the case that multiple scripts are trying to affect the same thing, what should happen. So there is no base method you can call. Both scripts are at the same level.

 

No net change seems to be the more logical and less confusing way to handle this. Both scripts Update() will be called. It's up to the programmers to know the scripts attached to their objects and what it's doing.

 

 

 

It should overwrite the previous version of the same methods, since else you have no control to overwrite methods which you don't want. But you should be also able to call the overwritten method from the new method, else you have to rewrite all code in the new method. Then it works like C++, and the real developers don't have to learn a new language behaviour.

 

You wouldn't have to learn a new language behaviour. You just have to think about how this works differently. Netting the rotation value would give the same behaviour in C++. What's happening is the following:

 

There is a base class, let's call this LEScript. It has a public virtual function called Update(). Each script you create derives from LEScript and allows you to overwrite the Update() method in which the engine will call automatically each cycle. If you have 2 separate scripts and you attach both to an object, then naturally the engine will call both scripts Update() function for that object. This would be how C++ would do it also. The scripts are just classes derived from another class. If in your object you stored both of your subclasses, the engine would cycle through all these subclasses stored with that model and call their Update() method.

Link to comment
Share on other sites

Guest Red Ocktober
This isn't really an option in this situation. He's talking about 2 completely different scripts (classes) attached to an object.

 

i'm sorry... i don't understand the above statement, or, for that matter, the entire topic...

 

an object in c++ is an instance of a class... right... so, in what context can you have multiple classes attached to an object...

 

 

scripts are not class definitions... thinking of them in the same way that you would think of c++ classes is wrong...

 

scripts are not attached to objects... they are attached to what i've seen referred to as entities, which are mostly meshes in the Leadwerks context...

 

scripts merely invoke behaviors... as such, they should all be called in response to whatever event or callback they are responding to...

 

can ya see where overriding one script with another is gonna become a debugging nightmare...

 

i'm gonna have to agree with what the communist coder above so boldly said above... treat em all equally... :)

 

 

--Mike

Link to comment
Share on other sites

an object in c++ is an instance of a class... right... so, in what context can you have multiple classes attached to an object...

 

By storing a list of base class pointers to an object. In C++ terms it would look like:

 

class GameObject
{
public:
  list<LEScript*> scripts;
};

class LEScript
{
public:
  virtual void Update(){}
};

class Script1 : LEScript
{
public:
  virtual void Update(){ // script 1 logic }
};

class Script2 : LEScript
{
public:
  virtual void Update() { // script 2 logic }
};

GameObject obj1;

obj1.scripts.push_back(new Script1());
obj1.scripts.push_back(new Script2());

// now you look through all the scripts attached to obj1 and call the Update() method. This will call Script1 class and Script2 class Update() method.

 

Script1 & Script2 would be defined by us in Lua files.

 

scripts are not class definitions

 

Object/Entity scripts contain class definitions. That's how the current LUA implementation works. Although currently you can only have 1 Lua script per object (entity). What Josh is saying is that you can attach any number of Lua scripts to objects.

 

 

scripts are not attached to objects... they are attached to what i've seen referred to as entities, which are mostly meshes in the Leadwerks context...

 

You are correct in how it's implemented today. Josh is asking about how it'll be implemented tomorrow.

Link to comment
Share on other sites

Guest Red Ocktober
By storing a list of base class pointers to an object. In C++ terms it would look like:

 

that's not a class definition... i repeat, since an object is an instance of a class, in what context can an instance of a class be represented by bymultiple class definitions...

 

linking class pointers to an exisitng object is not the same thing as instantiating an object... me thinks you are a bit confused here...

 

 

Object/Entity scripts contain class definitions.

you've said nothing here... all you've managed to point out is the obvious... that scripts can contain class definitions, just like any other source code...

 

You are correct in how it's implemented today. Josh is asking about how it'll be implemented tomorrow.

well... that's what i was answering... since they are scripts... let em all be executed as scripts... why add some confusing overrding mechanism to the mix...

 

c++ object oriented thinking doesn't apply here... well, not directly... when you drag an object from the LW editor pallette onto the workspace, you are, in effect, instantiating a class... now if you want to override a previously declared method, then hey... why not... for each instance of the class, you can have different update methods...

 

i don't understand the problem...

 

--Mike

Link to comment
Share on other sites

linking class pointers to an exisitng object is not the same thing as instantiating an object... me thinks you are a bit confused here...

 

Think of the existing object as a model in your scene. That object gets instantiated and along with it, the scripts that you attached to it also get instantiated. Now when the main engine loops through all objects in a scene, it also loops through all the instances of all the classes attached to it. Generally 1 script contains 1 class definition (in the Lua implementation today), so I'm using the term script/class in this case interchangeably.

 

 

well... that's what i was answering... since they are scripts... let em all be executed as scripts... why add some confusing overrding mechanism to the mix...

 

Well we are overriding script functions in todays Lua implementation when it comes to entities. That's probably the key thing to point out with this discussion. This would be scripts attached to entities instead of the stand alone scripts.

Link to comment
Share on other sites

c++ object oriented thinking doesn't apply here... well, not directly... when you drag an object from the LW editor pallette onto the workspace, you are, in effect, instantiating a class... now if you want to override a previously declared method, then hey... why not... for each instance of the class, you can have different update methods...

 

You are sort of there. When dragging an object to the editor pallette you wouldn't want that to have it's own standalone class/script where you override methods. The reason is you generally will have multiple objects in your scene that are similar/same and should provide similar functionality. So if each was it's own standalone class/script you would be copying and pasting code to each objects class/script. So that's why you allow attaching scripts to the objects. Because you can attach the same script to all these objects so they can share the functionality. The ability to do this gives the functionality you talk about above, but it also allows for different functionality to be implemented as well.

 

When a script (which is just a class definition) is attached, the engine will create an instance of the class inside the script and start calling the functions. So the user is defining the class and how it works, and the engine takes care of creating instances of that class.

Link to comment
Share on other sites

Guest Red Ocktober

no... i'm not there Rick... you are thinking of these things as objects... i'm thinking of them as what they actually are... models, with attached scripted behaviors...

 

 

ok... maybe i'm missing something here... lemme put it to you as a question...

 

say i have a boat "object" on the editor pallete... but i want a submersible boat in my game... a submarine...

 

how would i leverage the existing boat "class" in your vision, to make a submersible boat...

 

 

--Mike

Link to comment
Share on other sites

no... i'm not there Rick... you are thinking of these things as objects... i'm thinking of them as what they actually are... models, with attached scripted behaviors...

 

Exactly. Now just think about being able to attach more than 1 script to a model, and each script has an Update() method in it, and the engine is going to call one or both of these Update() methods for this model. That's the issue Josh is asking. Should it call both, or just 1 of them? My argument is both.

 

 

say i have a boat "object" on the editor pallete... but i want a submersible boat in my game... a submarine...

 

how would i leverage the existing boat "class" in your vision, to make a submersible boat...

 

Just to clear this up, today (and I know this is what you are saying) we put models into the editor palette. I get that this is how it works today. But take that out of your head for a second. Let's imagine you don't have access to any sort of int main(). Instead you just have what we'll call Game Objects. In Leadwerks terms these are basically just TPivots. They just have pos/rot/scale and that's basically it. Now you can attach multiple things to these Game Objects like models, sounds, scripts, particles, etc. So in your example here is what you would do.

 

1. Create a submarine model.

2. Create a script that acts on a game object that has submarine behavior to it.

3. Drag an empty game object into the editor palette.

4. Attach the submarine model to it.

5. Attach the submarine script you wrong to it.

 

This would be the long way to do it. The more common way would be to just drag the model into the palette and a game object would be created for you automatically and the model attached to it. Then you attach your submarine script to that game object.

 

It's important to separate out the idea of a game object vs a model and other assets, because a game object doesn't always have to be a model. It can just be logic. These are the basics around the "Thingoids". Logical entities instead of model based. Triggers, rotators, movers, etc. Things that don't have an in game visual aspect but run code instead. For example I've created Spawner objects. I attach a spawner to a trigger. When the trigger is hit it fires an output message to the spawner object. The spawner object receives this as input and runs code to dynamically instantiate some other game object, like a zombie or something.

Link to comment
Share on other sites

Guest Red Ocktober

so... your saying that i could add an additional script to the game object (pivot) to override the existing class script ?

 

 

in other words... if there was a bouyancy "game object"... and i added to a scene... then i could replace the model with my sub model... and attach an additional script that i could write to override any exisitng function and also to add new functions in order to make a floating object a powered submersible object... is that the idea ?

 

--Mike

Link to comment
Share on other sites

At that point, I would probably assume you are a competent programmer, and are able to copy and paste code. :)

 

The whole point of multiple scripts is for people who aren't able to understand what a block of code is doing, and copy and paste it without causing a problem. To you and me this may seem completely trivial, but if you think about the last time you looked at a wall of incomprehensible code, it makes sense. Not saying Rick is in this boat. I think he has seen systems like this in action, and they probably are fun and nice to work with.

 

So basically this moves the burden of using copy and paste from the novice to the expert. I don't really see this script system working with class hierarchies, and I think that is okay. AI is probably the only real use of hierarchical classes I would use, and how hard is to make some basic AI functions and call them from another script? Traditional object-oriented programming is great for a game engine, but I think it breaks down in higher game logic design, and becomes more trouble than it's worth. You can get the same benefits without making derived classes.

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

so... your saying that i could add an additional script to the game object (pivot) to override the existing class script ?

 

Not override, complement. You would have 2 class scripts attached to the same game object. They could be doing completely different things. That is where you have to be careful though. In Josh's example in the first thread, that would be an example of something that would be an issue. He knows that so he's asking in a situation like this, what do we think would be the best action. If I attach 1 script that Joe Blow created and it moves the controller, and I attach another script that Mike Chang created and it also moves the controller, what should happen? Who wins that fight? Should 1 script win over the other, or should they both just run their Update() function and let whatever happens happen. My vote was to let them both run, and leave it up to the person making this object to realize what both scripts are doing.

Link to comment
Share on other sites

Guest Red Ocktober
I don't really see this script system working with class hierarchies,

i agree wholeheartedly... and this is what i was trying to get across above...

 

Traditional object-oriented programming is great for a game engine, but I think it breaks down in higher game logic design, and becomes more trouble than it's worth.

i don't agree 100% here... but i think i can see where you're coming from with this...

 

in my opinion, if you had've ignored lua completely, by now we would've had a feature complete version of Leadwerks, and the availability of game objects that would've come from the various developers would've been more than enough to provide even the most non coder artist type with a rich library of functionality from which he/she could've chosen from...

 

all you would've needed to do with the old 2.3 was to make a reliable loadscene() available that included processscene functionality... that, and providing a guide for developers on how to create a c++, bmax, (or whatever) game object (code class and model) that the editor could 'see'... and Leeadwerks would've been ready for prime time...

 

there would've been whole collection of Leadwerks ready boats, planes, trains, and autos... all the non coding types would've had to do was to drop em into the proper folders and start up the editor... add em to the mix, call loadscene() in their trivial c++ or bmax program... and the game objects would've come to life...

 

we would've been there by now... your goal of making Leadwerks available to everyone would've been accomplished...

 

 

oh well... could've... should've... it's all past history... lets move ahead... but on a purposefull course... lets get 2.3x solid and working... it's almost there...

 

My vote was to let them both run, and leave it up to the person making this object to realize what both scripts are doing.

 

my vote is to not pursue this lua scripting thing any farther... leave it as it is... don't abandon framewerk, produce a general purpose loascene() function (with process scene functionality), and give us a programmers guide for making editor friendly objects we can make in c++, bmax, c# whatever...

 

don't waste time recreating what has already been done... don't waste time implementing programming logic rules into a scripting system that will only serve to implement rules that already exist in other class capable languages that LW can exploit with a lot less work...

 

 

 

 

--Mike

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...