Make Things Change on Tap
FeaturedHey Everyone,
Let’s make something change on tap! In this guide we will go through an example of tapping to change objects, tapping to change sprite textures, and tapping to change material colors.
So in my current project, I have three objects that I want to tap through. In this example each item is an object with a MeshVisual component (3D object), but it can be anything, such as: a sprite, a parent of multiple , a billboard, etc..
First let’s create a box (Add new -> Mesh Visual -> Box) to define where a user’s tap would count and call it TouchCollision. Resize this box to roughly encompass our objects.
Although you can use any MeshVisual, including the actual object you’re displaying, it’s sometimes to have a seperate mesh since it can stay consistent across different objects and allow you to tap on non-MeshVisual object such as a sprite.
Since we don’t actually want to see the TouchCollision, let’s give it an invisible material. In the TouchCollision Inspector panel, under Mesh Visual component, click “Default” to open the material selection window. In this window, we can Add New “Unlit” material. Select the new Unlit material in the Resources panel and uncheck “‘Depth Test”, “Depth Write”, “Color Write”.
To use the TouchCollision, we’ll add a TouchComponent (Inspector Panel -> Add Component -> Touch) and assign the TouchCollision to it.
Next, let’s add a ScriptComponent (Inspector Panel -> Add Component -> Script) on the same object. This script will use theTouchComponent and iterate through our items when we tap. Add a new script to this component on ‘Initialize’.
Then let’s edit the script (double-click on the script in your Resources panel). To get references to our items in this script, we can create an input that takes in an array of SceneObject. Then in the Inspector Panel of TouchCollision, you can add our objects to the array--in this case item1, item2, item3.
// @input SceneObject[] items
Since we only want to see one object at a time, we can loop through our “items” array and disable everything but the first one.
// Arrays are indexed from 0.
// Disable everything but the first (0th) item
for (var i = 1; i < script.items.length; i++) {
script.items[i].enabled = false;
}
Below that, we tell the script that we want to activate the next item in the array when a TouchStartEvent happens.
function activateNextItem () {
// we’ll fill this in a second
}
// Bind the function to the touch event.
var touchEvent = script.createEvent("TapEvent");
touchEvent.bind(activateNextItem)
When activateNextItem gets called by the TapEvent, we want the Lens to disable the current item and enable the next item. To help us do this, we need to keep track of our current item.
// We remember what item is currently visible.
// When we start it’s the 0th item.
var currentItemIndex = 0;
// Define what happens when you tap.
function activateNextItem () {
// Disable the current item.
script.items[currentItemIndex].enabled = false;
// Increment the current item index
currentItemIndex += 1;
// We need the current item index to wrap around
// once it's higher than the number of items we have.
currentItemIndex = currentItemIndex % script.items.length;
// Enable the new item.
script.items[currentItemIndex].enabled = true;
}
And that’s it! In your preview you should be able to do this:
Our final script:
// @input SceneObject[] items
// Arrays are indexed from 0.
// Disable everything but the first (0th) item .
for (var i = 1; i < script.items.length; i++) {
script.items[i].enabled = false;
}
// We remember what item is currently visible.
// When we start it's the 0th item.
var currentItemIndex = 0;
// Define what happens when you tap.
function activateNextItem () {
// Disable the current item.
script.items[currentItemIndex].enabled = false;
// Increment the current item index
currentItemIndex += 1;
// We need the current item index to wrap around
// once it's higher than the number of items we have.
currentItemIndex = currentItemIndex % script.items.length;
// Enable the new item.
script.items[currentItemIndex].enabled = true;
}
// Bind the function to the touch event.
var touchEvent = script.createEvent("TapEvent");
touchEvent.bind(activateNextItem)
Bonus:
You can also use similar scripts to modify existing objects:
Instead of passing an array of objects, you can pass in an array of textures and then iterate through the textures on one sprite.
// @input Component.SpriteVisual sprite
// @input Asset.Texture[] textures
// Our starting texture index
var currentItemIndex = 0;
// Assign the initial texture to our sprite
script.sprite.mainPass.baseTex = script.textures[currentItemIndex]
// Define what happens when you tap.
function changeTexture () {
// Increment the current item index
currentItemIndex += 1;
// We need the current item index to wrap around
// once it's higher than the number of items we have.
currentItemIndex = currentItemIndex % script.textures.length;
// Change the sprite's texture
script.sprite.mainPass.baseTex = script.textures[currentItemIndex];
}
// Bind the function to the touch event.
var touchEvent = script.createEvent("TapEvent");
touchEvent.bind(changeTexture);
Or instead of passing any array, you can use script to get random results on tap!
// -----JS CODE-----
// @input SceneObject object
// Define what happens when you tap.
function changeColor () {
// Get the item's mesh visual
var meshVisual = script.object.getFirstComponent("Component.MeshVisual");
// Change it's baseColor
meshVisual.mainPass.baseColor = new vec4(Math.random(), Math.random(), Math.random(), 1.0);
}
// Bind the function to the touch event.
var touchEvent = script.createEvent("TapEvent");
touchEvent.bind(changeColor);
Happy crafting!
-
Hi Patrick, Glad to hear! Don't forget to show us what you come up with :)
Hi Tai, Can you clarify what you mean by "tap cycle through textures"? Do you mean when you tap once, it will cycle through multiple images (like every second?)
Hi Patrick, Currently Lens Studio does not provide that. We'll add this to our feature request. Thanks!
-
Hi Patrick!
You are able to use a hash table in Javascript. It might make sense when your project becomes more complex to use a central hash table for cleanliness. But it really depends on what you're trying to accomplish.
And finally, I wouldn't say you are pushing the limit. Lens Studio's Javascript is very powerful and I'm really excited to see more and more complex interactive experiences.
Cheers,
Travis
-
Hello everyone! :)I do not understand what's going on with my script.
How can I add my items to the board?
Here's what I see in the console:
22:23:19 Failed to parse scripts. Reason: incorrect value name 'text_english,' at line:
And how do I add my objects in the script:
@input SceneObject [text_english, text_english] elements
// Tables are indexed from 0.
// Disables everything except the first (0) element.
for (var i = 1; i <script.items.length; i ++) {
script.items [i] .enabled = false;
I hope you know where the problem comes from :)
Thank you!
-
Hello Jonathan!
Thanks for the quick answer! I tried to do exactly the same example as you, but when I add my objects in the Inspector panel under the script, I still have this error in the console:
11:04:35 SyntaxError: invalid token (line 2)
at [anon] (Script:2) internaland this is my line 2:
@input SceneObject[] items
So nothing happens when I touch in the preview :(
I can't figure out the issue..
Best,
-
Hi Nathan,
If you're using the script above, it looks like the list of "items" hasn't been set in the Inspector panel and so when the script tries to set "enabled" it fails because there is no object.
Here I add things to the Item list in the Inspector panel of my script:
If this is not the issue, can you post your script so we can take a look at it?
Thanks!
Jon
-
hi Jonathan,
is there a way to change these forehead binding on tap? and if i want to do it for more than one face could it be done?
-
Hi Sweet Ice!
I think you're very close. In the Inspector panel of where you placed your script, make sure that you have your face sprite on the Sprite field:
Then once you add your different hair do as the values in Textures, you should be able to touch the screen to change hair do! (In this example I just add in the default textures that comes with the project).
Let me know if you need any clarification! Excited to see the result :)
Cheers,
Jon
-
Thank you that worked just the way i want it to, i just need to adjust my textures so they all the the same distentions and location so they would fit perfectly.
follow up questions:
i can use the same script for a second face right?
and if i wanted to add a different sprite as well ( lets say a nose ) in addition to the first one would that work?
-
Hi Takinours!
Yes we can use something similar, instead of enabling or disabling objects, we can tell the script to change the audio track on an audio component, then tell it to play:
// Get an audio component
// @input Component.AudioComponent audioComponent
// Get a list of audio files we want to play
// @input Asset.AudioTrack[] items
// We remember what item is currently visible.
// When we start it's the 0th item.
var currentItemIndex = 0;
// Play the first sound on initialize
script.audioComponent.audioTrack = script.items[currentItemIndex];
script.audioComponent.play(1);
// Define what happens when you tap.
function activateNextItem () {
// Increment the current item index
currentItemIndex += 1;
// We need the current item index to wrap around
// once it's higher than the number of items we have.
currentItemIndex = currentItemIndex % script.items.length;
// Set the audio component to play the new audio file
script.audioComponent.audioTrack = script.items[currentItemIndex];
script.audioComponent.play(1);
}
// Bind the function to the touch event.
var touchEvent = script.createEvent("TapEvent");
touchEvent.bind(activateNextItem)Then, you should have something like this:
You can create an Audio component, by clicking "Add New" at the bottom of the Inspector panel, and clicking Audio.
Then select the Audio Component field and choose the newly created audio component. Finally, you can drag your audio from the Resources panel into the different values in the Items field.
Let me know if you need any clarification. Can't wait to see what you come up with!
Cheers,
Jon
-
I thank you again for your help.
When I tap, Is it possible to change element in same time on the front and back camera?
I tap one time, I wear a component , if I switch on the back camera I find a component associated. If I tap another time I wear a new component and if I switch of camera I Have a new component.
I don't if I'm clear ....
Thanks!
-
Hi Takinours!
Yup! All you need to do is call the function when the front and back camera events get called. At the end of your script you can add the following:
// Bind the function to the camera switched to back event
var cameraSwitchToFrontEvent = script.createEvent("CameraBackEvent");
cameraSwitchToFrontEvent.bind(activateNextItem);
// Bind the function to the camera switched to front event.
var cameraSwitchToBackEvent = script.createEvent("CameraFrontEvent");
cameraSwitchToBackEvent.bind(activateNextItem);Let me know how it goes!
Cheers,
Jon
Please sign in to leave a comment.
Comments
30 comments