Using Symbols

I know in things like Unity you can instantiate, or create an object that’s already predefined and use it on the spot. It’s how you make it so when you push the key to fire a bullet, the bullet is created and set on its path. Usually I could save that bullet to an array, and later “remove it” after a set time or it would remove itself if it collided with anything.

I was wondering if there was a way to do that here with perhaps symbols. Can they be instantiated at a point, and later removed? I was digging around in the documents and I couldn’t quite find my answer. There’s something about .attach() and .detach() but these don’t really say they add or remove them completely, just that they attach to a .scene or remove them from a .scene or group. [Plus I couldn’t figure out how to use them.] There’s also .symbol(…) which apparently instantiates a new symbol but clicking on it in the documents doesn’t give me a lot of information on how that works. Plus I don’t see a way to remove it once it’s made?

Example 1:

I have a garden, and when you open the zap, there’s nothing there. However, over time, weeds begin to sprout. These weeds are a “symbol,” that are added to the scene at random based on a script.

Example 2:

You have a button. When the user pushes the button a symbol is placed on that button and runs its animation. At the end of its animation, the symbol removes itself from the scene.

Subsymbols while cool, don’t seem to work the way I originally thought they might. Guide me in the right direction? I was hoping to use them in a clean way to keep my program organized. My quick questions are:

From the parent state, can you tell a Subsymbol to “activate” a controller state?
From the parent state, can you get a value returned from a script running in the Subsymbol?
From the parent state, what can I do with a Subsymbol? Can I add a “pointerdown” event script? I right click and have no options.

Where am I running into headaches?

I’m trying to create a code game. There are 8 buttons, and you must hit them in the right sequence. I’d like to run a script in the parent that tracks what buttons are pressed and evaluates the result there. However, I wanted buttons to turn green or red depending on if they were correct presses or not.

Do I need to think about Subsymbols in a different manner?

Hi There,

I’ve merged your two topics together as they both tie-in quite nicely under the general heading of symbols/subsymbols.

Before I proceed any further it’s worth mentioning that a lot of what I’ll be mentioning is covered in more detail in the subsymbols documentation so it’s worth checking out.


Symbol construction

You can construct a symbol in ZapWorks Studio in a script by simply dragging the symbol from the symbol definitions panel into the editor with a script node selected. For a reusable object like a bullet you’ll probably want to use a blank symbol.

You can then add this symbol instance to the Hierarchy at runtime using the Z.Group push function, using the remove function to remove it. The root node acts as a group in case you don’t have a specific group in the hierarchy to push your symbol to.

It’s worth noting that once constructed there’s no way at the moment for “deleting” the memory used, even when removing the symbol from the Hierarchy - so we recommend creating a “pool” of objects that you can reuse, like your array method.


Subsymbol access

To answer your questions on accessing functionality of a subsymbol from a parent symbol the first step is to have access to a variable containing the symbol instance. This was mentioned previously with dragging in the symbol to a script node and can also be done with dragging in a symbol instance in the Hierarchy to a script node. once you have that variable the syntax is as follows:

To activate a state or timeline

mySymbol.controllers.symbolController.elements.controllerState.activate();

To access functions and variables from within a script

The below assumes that the function or variable has the export keyword preceding it, for more information on this please see this post - How to change plane 'materials' property (texture) from my script

mySymbol.nodes.symbolScript.myVariable

mySymbol.nodes is the way of accessing the nodes within a symbol, which is also useful.

To access events

At the moment we don’t expose any events from a symbol but you can fire your own custom events from within a subsymbol using the emit function and listen for them within the parent symbol.

For example you could have the following code within a subsymbol, parent being a plane object the pointerdown script was created from:

parent.on("pointerdown", (e) => {
	parent.emit("custom:pointerdown");
});

And then listen for the custom:pointerdown event in the parent symbol to know when subsymbol’s plane has been pressed:

mySymbol.nodes.Plane0.on("custom:pointerdown", () => {
    // run some code
})

It is highly recommended to prepend custom events with the custom: syntax to avoid potential conflicts with built-in events, including ones that may be added in future.


I hope this has helped explain symbols a little better and how they can be used, any further questions let us know :slight_smile:

Thanks,
Mark

2 Likes

Fantastic and a ton of information I needed with much needed examples. Thanks so much. I do apologize that I might not be finding the information I need in the documents at times. This has certainly opened up a lot of doors though.

It’s a shame there’s no way to remove symbols that are added via scripts. I guess all “unused” symbols could be dropped into a “recycling” group and I could check there for an unused symbol before making a new one XD

No worries, we’re looking to add further articles and tutorials on multi-symbol experiences in the future :slight_smile:

Mark

Hi, evrything works when i have the symbol from a variable Ex dragg and drop , but when i instance the symbol pushing it to a node using (push) , how i get access to the function from that instance that i just pushed into the node ? have been trying with the variable that i asign to create the z.symbol but dosent work can you hel p me thank you

Hi,

<your_variable>.nodes.
let you access the complete hierarchy of your symbol’s instance .

So, to access your function:
<your_variable>.nodes.<your_script>.<your_function>

Hope, it helps. Cheers.

1 Like

jvouillon thanks for the reply , yes i had tried that before but when i intanciate the symbol from the script using Push , the instanciated object dosent start any function using the script neither wiht ponterdown or calling it from the main script , but when i dragg it to the herarchy manually the same symbol it works with this code any other advice thanks ,

actually an ex is this

  1. instance a symbol
    instance = Z.Symbol(“XXXX”).rotation([0, 0, 0]).scale([1, 1, 1]);

  2. push it to node “tags”
    symbol.nodes.tags.push(instance);

  3. allready is in herarchy

  4. try to trigger a function from the instanced symbol ( any method event , form script etc…)

intance.nodes.script.openbox();

  1. nothing happens

but if i drag the symbol manually to the herarchy it works without problem

any advice is welcome

what we have done thats kind of works is

  1. in the symbol herarchy we add an object with a pointer down event triggering a function lets called function 1; (emit didnt work in this case)
    1.create a Z.object type plane and add a tag via script
  2. then made the intanced symbol parent of the z.object that we just created
  3. then via ponterdown call a function2 from main script dependeing of the tag
    the problem is that we need to tab twice to trigger the two functions one for each , becouse one function depends from the main script and the other one depends of the instanciated symbol.
    it works but is not the best practice,
    any help will be helpfull
    thank you

I got this code from the support guys some time ago. I wanted a way to track when an event happened from a pushed symbol. I haven’t used it yet but maybe it can help you.

Steve

function applyEvents(node: Z.Type.Symbol, index, array) {
node.tags().push(index); // Add index into tag.
node.on(“Block:Clicked”, () => {
console.log(Clicked: ${node.tags()[0]})
});
}

symbol.nodes.screen.children().forEach(applyEvents);

thanks steve , im trying to use it but i cant make it work , do not know if im doing something wrong here

Here is my email I sent them it may help you out more…


Ok so I’m pushing a lot of the same subsymbol to a group. I want to use the emit from the subsymbol to know when things happen. This would work normally but because they have been pushed I’m having problems. If I use this code it works but that’s not what I want.

symbol.nodes.screen.child(1).on(“Block:Clicked”, () => {
// Runs when the Block:Clicked event occurs
console.log(“Block:Clicked!”);
});

Is there away to make any or all child?

EX…

symbol.nodes.screen.child(any).on(“Block:Clicked”, () => {

// Runs when the Block:Clicked event occurs
console.log(“Block:Clicked!”);
});

I was thinking of making a loop but don’t know if it would miss the emit.
I will need to know the child’s ID that did the emitting for use elsewhere.


Also remember to change “” if you copy the code from the form.

Steve