Jump to content

How to add 2 scripts in one prefab?


igg02
 Share

Recommended Posts

It is unfortunately no longer possible to add multiple scripts to 1 gameobject. What you can do is add a pivot to the scene, make it a child of your prefab, and attach the script there. You do no need to make sure that the child references the parent though (depends a little on what you want your script to be doing).

  • Upvote 1
Link to comment
Share on other sites

So although this works, it is not ideal.

 

If you make a script that you want to share you always have to take in to account that you are possibily a child of the object and that the script is not attached to the object itself. It breaks the logic of every script that you can find in the workshop. So be careful.

Link to comment
Share on other sites

Depends on what you do, but you have function FindChild , you could place some pivot as child of player character and at start init some variable with the player entity than be able to use Pivot script to manipulate Player entity and not itself only.

 

One example could be some Input manager : Keyboard, joystick ...

So this pivot that would manage inputs could be a portable script for other characters, they would just need to call some functions of the script's pivot that would give movement to do based on inputs.

 

Or some states manager using a pivot as child also.

This way all scripts : input, states manager would be attached to the player, and would reduce a lot the player script and make it more clear. But perhaps more script is less faster than in player Lua script import some State manager Lua script and just instantiate it and refresh it in update loop ?

Stop toying and make games

Link to comment
Share on other sites

There's a good reason for this. During the development of Darkness Awaits, we got into a lot of extremely ugly script code like this:

for script in entity.scripts do

if script.health>0 then

if script.TakeDamage)~nil then

result = script:TakeDamage()

break

end

end

end

return result

 

When this was all we really wanted:

if entity.script.health>0 then

if entity.script.TakeDamage~=nil then return entity.script:TakeDamage()

end

 

The 1:1 entity to script paradigm reduces a lot of code complexity. As soon as this was implemented, it opened up my creativity since I wasn't stumbling around trying to make code conform to an ideological design that made life harder instead of easier.

 

In theory, having a bunch of different pieces you put together sounds nice and simple, but in practice those things are not so easily separable. We ended up with excess abstract classes like a HealthManager, that baffled experts and beginners alike. Simplicity has proven to be the best approach.

 

Also note that the first case is ambiguous. You can't simply poll a variable from an entity, because multiple scripts can have variables with the same names. So if you want non-ambiguous variables, you now have to come up with a namespace for everything. And if your idea doesn't happen to be the same as everyone else's your scripts aren't going to work together.

 

With a 1:1 design different scripts not written by the same person can work together and create emergent gameplay. For example, pretty much everyone will use 'health' as an indication of how much life an object has. So scripts designed by different people will naturally work together to create new and interesting gameplay mechanics.

  • Upvote 1

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

That kind of illustrates the problem. If another script is looking for an "FPSPlayer" component, it won't work with a third-person player script. I thought about what the Workshop would look like a couple years from now, and realized the namespace requirement would damage a lot of functionality we would otherwise have. It turns the script system into a sets of scripts that all have to be designed to work together, and actually makes the system less modular...which is the opposite of what we want.

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

But swapping out FPSPlayer scripts that function differently and have the same interface works without any changes to the other scripts. I think this is more about separation of duties than anything else. Having all the code that handles what a player is inside 1 entity script gets complex and hard to follow. The FPSPlayer script that comes with LE is pretty messy and not even close to a final game's needs. This means it's only going to grow in complexity and be harder to follow and maintain.

 

The way around that currently is to make our own classes (like AnimationManager) that help separate out some of the functionality and make reusable objects.

 

The point with something like HealthManager is that I don't have to retype or copy/paste (because copy/paste is often a clue of bad design) health managing code into all the potential scripts that need it. My player needs health, enemy type A needs health, enemy type B needs health, a door needs health if you can break it/kill it. By simply adding the HealthManager script, that functionality is given to these entities and no need to code health data/logic into each script yourself.

  • Upvote 1
Link to comment
Share on other sites

My goal is to maximize emergent behavior between arbitrary scripts that were not necessarily written to work together. Leadwerks is particularly strong with communication between objects, with the flowgraph and the dynamic nature of the Lua script language. The approach I have taken provides the best ease of use for programmers, who don't have to deal with the cognitive burden of classes straddling different files, and non-programmers who don't have to remember a complicated series of required scripts to make one object work.

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

The approach I have taken provides the best ease of use for programmers, who don't have to deal with the cognitive burden of classes straddling different files, and non-programmers who don't have to remember a complicated series of required scripts to make one object work.

 

I get where you are coming from but "classes straddling different files" isn't a burden, it's organization for maintainable and reusable code. You did this yourself with the AnimationManager class. You did it because that's the way it's supposed to be done. Nobody is going to copy/paste animation code into all scripts that need it. Programmers know this, and so this isn't for the ease of use for programmers, it's for the ease of use for non programmers. I get that, but the non programmers will graduate into seeing why this is important when their codebase becomes unmanageable.

 

The training I've been giving to a few people I advise them to make classes that hold common functionality so it can be added easily into other scripts. This is required because we don't have multi-script functionality so it's the next best thing. If we had mult-script functionality these classes would be scripts.

 

Need a timer on your object? Attach a timer scripts that does the functionality of a timer and hook up it's logic with the flowgraph. This is easier for a non-programmer and programmer than copy & pasting the timer functionality into each script that needs it because if the player object is the thing that needs said timer, they're out of luck because it has the FPSPlayer script already attached.

 

The multi-script feature worked great because of the flowgraph feature. They compliment each other.

 

I get where you are coming from, I just don't agree with it.

Link to comment
Share on other sites

Having all the code that handles what a player is inside 1 entity script gets complex and hard to follow. The FPSPlayer script that comes with LE is pretty messy and not even close to a final game's needs. This means it's only going to grow in complexity and be harder to follow and maintain.

 

 

I agree a lot, it's lot of code , input, animation, health, and states are all mixed in the code and yes it's really hard to follow.

Well even if we have one script only , it is possible to import in player :

- Health.lua

-StatesAndAnims.lua

-SoundsManager

-InputManager

In player Lua you would instanciate each Lua "Class" , give the good parameters at start then call them each time you need.

 

Not all classes are "portable".

For example StatesManager would be different from Player , NPC1 , NPC2 etc ... because you could have a different ennemy behaving differently from another a,d specific states, so not same states branching in the code of StatesManager.But InputManager for inputs to send to player indeed could be portable for a FPS, TPS , Racing game or whatever ...as it should just send what are the actual inputs from a choosen keys/mouse/joystick mapping.

 

I already tested in the past Flowgraph and keys manager, the script just branched in player inputs and it was a great code separation and clear to modify, maintain or make evolve.

 

To summarize, you can do all you Player management in one Script if your game is not too much complex, once it becomes more complex with lot of stuff to manage, better create managers or classes for each functionnality could it be multiple imports or multi scripts.

 

For multi scripts the other advantage is simply, the drag and drop concept and ready to go i think it's the same good feeling with actual post effects systems, where you add or remove as you want : with multi scripts this was the case, add or remove as you want.

 

For example some state manager script would be coded with self.entity, so you could branch it to players or NPC and just adapt variables and 2D life bar display at screen.

 

Well Agrror, thanks for that tip, Pivot is incredibly usefull one more time in LE3 smile.png

Stop toying and make games

Link to comment
Share on other sites

In player Lua you would instanciate each Lua "Class" , give the good parameters at start then call them each time you need.

 

Yeah, what we have right now is a more traditional approach. What you describe is pretty much how you'd do it in C++ as well. Break out common functionality into it's own class.

 

I feel like we had something very powerful in the multi-script feature combine with flowgraphs for non coders (hell, even for coders). We could have written very generic scripts that are pieced together using the flowgraph by people who don't know how to code (or want to reuse things and get something unique up and running quickly by combining different scripts).

 

 

 

I have experienced the opposite. Separate scripts are nice for a simple example, but quickly break down as your game gets more advanced.

 

I guess one way to test this is to use the pivot method Aggror mentioned above with the FPSPlayer script to see how different it is. Sounds like a fun challenge :)

Link to comment
Share on other sites

Humm ...

 

I would not mix complex states and animations in same code as Player as this would go incredible complex.

If you had to manage several attack types, climbing, crouching ,swimmig, and each states would had to knwo if another is on or off, or some like underwater state could be enabled only if swimming etc ...

I can't imagine how complex states would go, that's why states should be appart as they are the core for player management.

 

You could code just states using input manager that do nothing in a first time (no sound or animation, particles calls or whatever).

Like :

 

T1

state idle

input= walk -> state walk

 

T2

state walk

input= nothing -> state idle

input= run -> state run

 

T3

state run

state idle

input= attack -> state attack

state attacking

 

 

Etc ...

 

This is the core of player management or NPC, the fundamental programming for games.

Other code like animation, sounds, changing other entity states (hurt etc ...) are specific to each state, so once you have states manager or graph ok , than you can fill each state with appropriate code.

 

For example

 

Function state_Walk()
sound walk
anim walk
goto (direction, speed, ...)
end

Function state_Attack()
sound attack
anim attack
end

 

This way this is super clear on how to fill each state , so easy.

 

This is what i done in LE 3.0 and it made my code super clear and easy to read compared to mixing all in player script. That's one rule in some langages programming not go over 1000 lines of code in one Class or script, or split it in another class or script for functionnalities.

 

In Leadwerks 3.1 even with import we can split Player and states manager, and input manager etc ...

Or do it using pivots attachhed to player, each having it's own script working independently.

Stop toying and make games

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...