CREATE YOUR WORLD
Interacting with Objects
Applying Vehicles to ZEPETO Characters
20min
by applying the guide on attaching objects to zepeto characters, you can implement riding vehicles like cars, airplanes, pets, etc , as if the character is riding them 📘 please refer to the following guide \[ attaching objects to zepeto characters docid\ rqti5gxrdenvblefpzzih ] setting up the animator 1\) create an animator controller by going to project > create > animator controller and rename it to vehiclezepetoanimator 2\) in the animator tab, create an empty state by selecting create state > empty 3\) rename it appropriately in the inspector and assign animation clips to motion to use your desired animation clip files, refer to the custom animation guide 📘 please refer to the following guide \[ how to apply custom animation docid\ fgnaprjtltzzp5pj6sn4x ] 4\) drag and drop vehiclezepetoanimator onto zepetoplayers to set it up 👍 tips if the camera height needs to change depending on the size of the vehicle, you can preset the camera lookoffset value in zepetoplayers example code 1\) create a typescript by going to project > create > zepeto > typescript and rename it to ridevehicle 2\) write a sample script as shown below note that the vehicle transform values in this example should be adjusted to match the vehicle prefab when actually applying it import { zepetoscriptbehaviour } from 'zepeto script'; import { zepetocharacter, zepetoplayers } from 'zepeto character controller'; import { transform, animator, gameobject, humanbodybones, object, vector3, quaternion } from 'unityengine'; export default class ridevehicle extends zepetoscriptbehaviour { public vehicleprefab gameobject; public bodybone humanbodybones; private localcharacter zepetocharacter; private vehicle gameobject; start() { zepetoplayers instance onaddedlocalplayer addlistener(() => { // find the local player and set it to localcharacter this localcharacter = zepetoplayers instance localplayer zepetoplayer character; // get the localcharacter's animator component const animator animator = this localcharacter zepetoanimator; // get the position of the bone to attach the object to const bone transform = animator getbonetransform(this bodybone); // create the vehicle prefab this vehicle = object instantiate(this vehicleprefab, bone) as gameobject; // set vehicle transform this vehicle transform localposition = new vector3(0 5, 0,0); this vehicle transform localrotation = quaternion euler(0, 0,90); }); } } 3\) after completing script writing, add the script to the gameobject in the scene 4\) in the inspector, assign the vehicle's prefab resources and the body bone to be attached 5\) click the play button, and you'll see the zepeto character riding on the vehicle 👍 tips you can create various vehicles by simply changing the prefab of the vehicle and the animation clips of the character example of size change when consuming items here is a fun application example implementing content where the character's size changes when consuming items while riding a vehicle 1\) in this example, we prepared two types of prefabs and set the tag of items that increase in size when consumed as "increase" and items that decrease in size as "decrease " 2\) add colliders to each item and make sure to check istrigger 3\) create a typescript by going to project > create > zepeto > typescript and rename it to changeobjectsize 4\) write a sample script as shown below import { collider, gameobject, vector3 } from 'unityengine'; import { zepetoscriptbehaviour } from 'zepeto script'; export default class changeobjectsize extends zepetoscriptbehaviour { public vehicle gameobject; start() { } ontriggerenter(collider collider) { if (collider tag === "increase") { this gameobject transform localscale += new vector3(0 1, 0 1, 0 1); gameobject destroy(collider gameobject); } if (collider tag === "decrease") { const decreaseamount = new vector3(0 1, 0 1, 0 1); const newscale = this gameobject transform localscale decreaseamount; gameobject destroy(collider gameobject); // exception handling ensure that the scale does not become smaller than (1, 1, 1) if (newscale x >= 1 && newscale y >= 1 && newscale z >= 1) { this gameobject transform localscale = newscale; } } } } the key part of the code is modifying the localscale to change the size of the zepeto character when it touches each item feel free to adjust the numbers for size change but make sure to handle exceptions to prevent the scale from becoming smaller than (1,1,1) 5\) this script should be added to the zepeto character created at runtime therefore, modify the ridevehicle script that attaches the vehicle as follows import { zepetoscriptbehaviour } from 'zepeto script'; import { zepetocharacter, zepetoplayers } from 'zepeto character controller'; import { transform, animator, gameobject, humanbodybones, object, vector3, quaternion } from 'unityengine'; import changeobjectsize from ' /changeobjectsize'; export default class ridevehicle extends zepetoscriptbehaviour { public vehicleprefab gameobject; public bodybone humanbodybones; private localcharacter zepetocharacter; private vehicle gameobject; start() { zepetoplayers instance onaddedlocalplayer addlistener(() => { // find the local player and set it to localcharacter this localcharacter = zepetoplayers instance localplayer zepetoplayer character; // get the localcharacter's animator component const animator animator = this localcharacter zepetoanimator; // get the position of the bone to attach the object to const bone transform = animator getbonetransform(this bodybone); // create the vehicle prefab this vehicle = object instantiate(this vehicleprefab, bone) as gameobject; // set vehicle transform this vehicle transform localposition = new vector3(0 5, 0,0); this vehicle transform localrotation = quaternion euler(0, 0,90); // add script to charactercontroller const sizescript = this localcharacter gameobject addcomponent\<changeobjectsize>(); // add the vehicle to the script's inspector sizescript vehicle = this vehicle; }); } } code to add the changeobjectsize script at runtime has been added 6\) click the play button, and you'll see the character's size changing each time it consumes an item interacting with vehicles by applying the interaction guide, it is possible to implement boarding a vehicle at a desired location after interacting with it 📘 please refer to the following guide \[ interacting with an object docid\ emcqhbdmmf0dbwanun7pg ] setting up 1\) set up the dockpoint object and ui prefab on your vehicle prefab in the same way as the interaction guide 2\) in the unity editor, make sure the transform gizmo toggle button at the top is set to local, and rotate it so that the z axis (blue arrow) points outward from the object 3\) add a collider component and check the istrigger option 4\) adjust the size of the collider to the range within which the player can interact with the object 5\) create an empty object as a child of dockpoint by going to hierarchy > create empty object, and rename it to iconpos 6\) set up preficoncanvas in the same way as the object interaction guide, and then make it into a prefab 7\) additional step create a dismount button create a button as a child of the vehicle object by going to hierarchy > ui > button, and rename it to get off button adding boarding animation to the vehicle when a character gets on or off a vehicle, they need a natural animator setup to match the guide below will help you through the animator settings required for getting on or off refer to the guide on applying custom animations to add a sitting animation state to your custom animator 📘 please refer to the following guide \[ how to apply custom animation docid\ fgnaprjtltzzp5pj6sn4x ] 1\) right click on the added animation state, click make transition to create a transition from idle to sitting and back from sitting to idle select the created transition and uncheck the has exit time option 2\) in the custom animator → parameters → \[ + ], add a bool condition and rename it to isriding 3\) for the transition from sitting to idle state, click conditions → \[ + ] and add the isriding condition with the option set to false 4\) for the transition from idle to sitting state, click conditions → \[ + ] and add the isriding condition with the option set to true script write the interactionicon ts script, same as the one in the interaction guide, which displays the interaction ui when entering the trigger area of the vehicle prefab add the written interactionicon zepetoscript to the dockpoint object, and assign pref icon canvas and icon position in the inspector refer to the ridevehicleexample below for sample code on how to board the vehicle after interacting with the ui import { animator, gameobject, humanbodybones, physics, transform, vector3, waitforendofframe } from 'unityengine'; import { zepetoscriptbehaviour } from 'zepeto script'; import { zepetoplayers, zepetocharacter, characterstatemachine } from "zepeto character controller"; import { button } from 'unityengine ui'; import interactionicon from ' /interactionicon'; export default class ridevehicleexample extends zepetoscriptbehaviour { @serializefield() private bodybone humanbodybones; public isriding bool; public getoffbtn button; public vehicleobj gameobject; private interactionicon interactionicon; private localcharacter zepetocharacter; private playersittingposition vector3; private animator animator; private start() { zepetoplayers instance onaddedlocalplayer addlistener(() => { this localcharacter = zepetoplayers instance localplayer zepetoplayer character; this animator = this localcharacter zepetoanimator; }); this interactionicon = this transform getcomponent\<interactionicon>(); this interactionicon onclickevent addlistener(() => { // when the interaction icon is clicked, hide the icon and perform the interaction this interactionicon hideicon(); this dointeraction(); }); // set up the click event for the getoffbtn (button to exit the vehicle) this getoffbtn onclick addlistener(() => { if(this isriding) { this stopinteraction(); this interactionicon showicon(); } }); this getoffbtn gameobject setactive(false); } //method for performing the riding logic private dointeraction() { // set the animator's transition value to switch the current animation state to sitting state this animator setbool("isriding", true); this startcoroutine(this snapbone()); // to fix current animation, deactivate the animator this localcharacter statemachine constraintstateanimation = true; // set the vehicle object's parent to local character this vehicleobj transform parent = this localcharacter transform; // activate the getoffbutton this getoffbtn gameobject setactive(true); this isriding = true; } private stopinteraction() { // set the animator's transition value to switch the animation state to idle this animator setbool("isriding", false); // activate the animator again this localcharacter statemachine constraintstateanimation = false; this isriding = false; // set the vehicle object's parent to null this vehicleobj transform parent = null; // deactivate the getountbutton this getoffbtn gameobject setactive(false); } // coroutine for snapping the bone to the vehicle private snapbone() { const animator animator = this localcharacter zepetoanimator; const bone transform = animator getbonetransform(this bodybone); let idx = 0; while (true) { // calculate the distance between the bone and character position const distance = vector3 op subtraction(bone position, this localcharacter transform position); const newpos vector3 = vector3 op subtraction(this transform position, distance); // update the player sitting position and set the character's position and rotation this playersittingposition = newpos; this localcharacter transform position = this playersittingposition; this localcharacter transform rotation = this transform rotation; yield new waitforendofframe(); idx++; // calibrate position during 5 frames of animation if (idx > 5) { return; } } } } the flow of the script is as follows start() when the icon is clicked, this interactionicon is deactivated, and the dointeraction() function is called dointeraction() set the animator's transition values to play the sitting animation start the snap bone() coroutine to attach the zepeto character's bodybone to the targettransform use the function this localcharacter statemachine constraintstateanimation = true; to disable the current animator's transition, locking in the currently playing animation the parent of the vehicle object changes to the zepeto character the get off button in the top right is activated stopinteraction() set the animator's transition values to play the idle animation re enable the animator transition so that the appropriate animation plays according to the situation set the parent of the vehicle object to null deactivate the get off button this getoffbtn onclick the stopinteraction() function is called this interactionicon is activated add the written ridevehicleexample zepetoscript to dockpoint, and assign the get off button and vehicle prefab in the inspector \[▶︎(play)] press the play button to try boarding the vehicle resulting screen 👍 tips the above sample is an example of content not considered for multiplayer synchronization to implement multiplayer synchronization, you need to synchronize information such as which vehicle each player is riding, and the size and location of the vehicle, as room state