Deleting script component dynamically or increasing max script components amount

Hi! This is me again, with long hard-to-read posts :3
tl;dr: i’d like to be able to do either of this:

  1. increase maximum script components in the project settings
  2. being able to delete the script component from the object, as it only have init() function in itself.
    I can’t really remove these scripts and combine them into one large script, because it will create a lot of ugly and tedious work for level designers and might leave some “hard-to-find” errors in the map.
    I can do dynamic creating/deleting of large collections, but i’m afraid of the lag, so i’d rather avoid this solution for now.

Because our game has “technically-real-3d” view (check screenshot - trees are facing camera, tilemap is flat, we get real parallax and everything), we have to add some logic to map objects on init() function. Basically we have to rotate lots of objects on the map to face the camera angle when they are created. This angle might be changed and we can’t just set it in the editor, so we do it from the script in the init() call. After that, the script is basically not needed and could be deleted.
Obviously, we faced the “Could not create script component” problem quite fast, so we made a hack - not every object has a script on itself, but rather a collection with multiple objects controls them. For example we hawe this forest pack - a collection with collider, multiple trees sprites game objects (1-4 trees in each sprite for optimization) and a controller script, which knows the amount of tree sprites (passing total amount in the inspector, because we can’t have arrays, duh :unamused:). This limits us in creating more “diverse” visuals, but reduces the amount of scripts by a lot and solves it for custom manually created maps.
But then we tried to make a larger, procedurally generated maps and this problem appeared again. The map consists of large (~2 screens wide) manually constructed tiles, with the same collections in it. In addition, there are scripts like monster spawners, might be some more randomizers (put a box or a barrel in the specified spot, etc). Most of this scripts only have init() function and don’t (i hope) really use any CPU after that, so i’m fine with having too many scripts in the scene, but i can’t change scripts maximim amount in project settings.
Of course, i can do dynamic loading, having in memory only zone of 3x3 “large” tiles around the player and destroying other ones, but there is a chance there will be some lag when spawning 3 new tiles, which might be noticable by the player. And well, enabling/disabling looks like a better way to do that.
On the other hand, if i can delete the scripts - i can spread the map loading onto multiple frames, deleting all the init() scripts in the each frame, so i won’t reach the scripts limit, but i can’t do that right now.
Any suggestions for me? :slight_smile:

5 Likes

+1

I do level design on this project and I confirm every word here.

1 Like

Hmm, ok, so you have a ton of manually created and placed game objects, each of them with a script that does something in the init() function? Could you perhaps name them consistently (tree1, tree2, tree3, …, tree2001 etc) and have a single script somewhere that in it’s init() function iterates over all of the game objects and does whatever it was that you did in the individual scripts attached to the game objects? It’s not as dynamic since you need to know how many game objects there are. Maybe you could iterate up to a really high number and pcall() to catch any errors in case you try to operate on game objects that doesn’t exist.

2 Likes

I just want to add whilst we’re on the subject, @britzl: I LOVE the fact that copying “tree” in the collection (on the right hand side of the screen ) creates a new copy called “tree2”. I would love it if the same thing happened in the project explorer.

It would also be great if there was a way of accessing the name of the instance within a script: calling message url and go.get_id both return hashs, if i recall correctly. I need this because I have more than 200 objects called “leveselect1, levelselect2, levelselect3, etc…” and each one has a property called “1, 2, 3 etc…”.

Sorry for threadjacking and good luck with your complicated game!

I need to know about more about what it is you wish to do. I’m sure there’s a good solution to your problem. Would you mind posting it as a separate question? Thanks!

You are right, it is probably possible with manually created levels (and we did it in the lower scale, for a small groups on ~10 objects).
But now we try to procedurally generate the level, creating it from a big “tiles” (making up to 20x20 of this tiles, with ~10-100 objects in each tile. Each tile collection looks like this. There are “trees_pack_*” collections, which have multiple sprite objects and a script, that applies rotation for this objects.
So, overall, the game stucture is something like this:
main collection (with manager scripts etc) - [400 spawned (using collectionfactory) tile collections] - [mutiple “forest” collections, each having its own script for rotating the sprites]. In theory, theremight be some deeper collections aswell.
We can specify the sprite names in some way, like “trees_”, “building_” etc, but there will be multiple objects with the same name (as we can have repeating tiles and repeating “forest packs”), and they all will be nested in different tiles.
It is okay for me to iterate through all the objects, checking if its name starts with “trees_”, but how can i do that from a script, that is located in “main collection”? And how do i compare gameobject name?

Only way i see right now is to restrict “parenting” to a couple of “types”, like:

/collection*/trees_pack_*/trees_*
OR
/collection*/tree_*

And manually loop through every collection number and from 0 to “9999” for “trees_pack” and “trees”, creating url from that. Are there no better way? And if this is the way, then:

  1. How do i use pcall? I should just check “if not pcall(go.set_rotation(go_url)) then …”?
  2. I know the amount of spawned tiles, so i know my max index for “collection*”. There are no way to iterate through every collection inside it, so how do i check if the collection, say, “/collection3/trees_pack_25/” exists? Can i do the same pcall, like that:
tile_collection_name = '/collection3/'  -- Another iterating cyccle outside, lets just assume its '3' there
for i=0,9999 do
  pack_name = tile_collection_name .. "trees_pack_" .. i
  if not pcall(go.get_position(pack_name)) then break end

  -- for "/collection*/trees_pack_*/trees_*"
  for j=0,9999 do
    tree_name = pack_name .. "/trees_" .. j
    if not pcall(go.set_rotation(tree_name, required_rotation)) then break end
  end
end

-- for "/collection*/tree_*"
for j=0,9999 do
  tree_name = tile_collection_name .. "/tree_" .. j
  if not pcall(go.set_rotation(tree_name, required_rotation)) then break end
end

I’m not sure if it is possible because it is a colelction, not a game object?
This is how spawned tile collection might look right now: http://pastebin.com/3HLNLDAu We can restrict “trees_pack_*” to have one naming convention if needed.

One more question in advance - how should i properly enable/disable tile collections, which are too far from the player? I want that to reduce physics and drawing computations (i dont care what happens too far outside of the camera). I know tile collection id’s i need to disable, should i just call msg.post('/collection10', 'disable') for them?

Ok, but if you are procedurally creating the game objects using collection factories then why can’t you use the mappings returned from collectionfactory.create() and iterate over those and apply rotations?

3 Likes

I don’t need to apply rotation to every object in the collection, some should be flat as they were (tilemap, some ground effect sprites, etc), and if i iterate through the mappings (they are in the pastebin in previous post) i have only hashes and can’t really tell which object i need to rotate.
Only way with this approach is to do the same thing - set the naming convention (trees_pack_XX.trees_XX) and iterate through it while the hash with this name exists in returned table. This looks a bit better, because i don’t have to use pcall(), but still requires iterating 0…9999. No real big overhead, as we break from each cycle the moment the object with the required name hasn’t been found in the table, just looks ugly :slight_smile:
Probably will do this way, if there are no better option, thanks!
P.S. But being able to store some info on the object without the script component (like unity’s tag/layer system for example) would be really helpful.

1 Like