<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://graalonline.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=JimmyAkl</id>
	<title>Graal Bible - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://graalonline.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=JimmyAkl"/>
	<link rel="alternate" type="text/html" href="https://graalonline.net/Special:Contributions/JimmyAkl"/>
	<updated>2026-04-09T16:49:16Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.4</generator>
	<entry>
		<id>https://graalonline.net/index.php?title=Bomberman_MiniGame&amp;diff=20967</id>
		<title>Bomberman MiniGame</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Bomberman_MiniGame&amp;diff=20967"/>
		<updated>2021-11-22T14:17:02Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the Bomberman Minigame Tutorial!&lt;br /&gt;
&lt;br /&gt;
= BomberMan =&lt;br /&gt;
&lt;br /&gt;
==== Intro ====&lt;br /&gt;
BomberMan is a multiplayer game (usually 4 players). Each player can drop bombs that, upon explosion,  destroy the grey pillars making a path to other players. The objective of the game is to eliminate other players with the exploding bombs. Power ups are also sometimes dropped when pillars are destroyed (increase of speed, explosion power and number of bombs allowed to place at a time).&lt;br /&gt;
[[File:Bomberman cover.png|none|thumb|675x675px]]&lt;br /&gt;
Assets Bundle : &amp;lt;nowiki&amp;gt;https://www.graalonline.com/playerworlds/downloads/file?name=bombermanMinigame.unitypackage&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''bombermanprefabs'''&lt;br /&gt;
&lt;br /&gt;
[[File:Bomberman prefabs.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
and '''bombermanlevel1'''&lt;br /&gt;
&lt;br /&gt;
[[File:Bomberman level prefab.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
Since this game is meant to be multiplayer, we will be placing the GameObjects in NPCs for them to be visible to all the players and triggerring the server every time we want to place them. (more info on that here: [[Placing GameObjects in NPC]])&lt;br /&gt;
&lt;br /&gt;
First, we have the weapon that launches the game and places the NPCs (''found under '''weapon: 3D/Samples/BomberMan/Game''''')&lt;br /&gt;
&lt;br /&gt;
We've implemented a graalscript UI (which is not covered in this section, considering you know graalscript) that allows us to launch the game;&lt;br /&gt;
 function onActionServerside(cmd, x, y) {&lt;br /&gt;
   if (cmd == &amp;quot;bomb&amp;quot;) {&lt;br /&gt;
     temp.pnpc = putnpc2(x, y, &amp;quot;&amp;quot;);&lt;br /&gt;
     temp.pnpc.join(&amp;quot;merlin_bomberman_bomb&amp;quot;);&lt;br /&gt;
     //temp.pnpc.DropBomb(explvl);&lt;br /&gt;
   }&lt;br /&gt;
   if (cmd == &amp;quot;level&amp;quot;) {&lt;br /&gt;
      temp.bombernpc = putnpc2(x, y, &amp;quot;&amp;quot;);&lt;br /&gt;
      temp.bombernpc.join(&amp;quot;merlin_bomberman_level&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   echo(this.name @ &amp;quot; OnCreated&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function Load() {&lt;br /&gt;
   level.explosionpower = 3; //for powerups with explosion&lt;br /&gt;
   level.numberofbombs = 2; //number of bombs allowed to place at a time&lt;br /&gt;
   level.speed = 7; //player default speed&lt;br /&gt;
   &lt;br /&gt;
   echo(this.name @ &amp;quot; LOAD&amp;quot;);&lt;br /&gt;
   Object::destroy(this.bomberManParentNode);&lt;br /&gt;
   if (isObject(&amp;quot;bomberman_Quit&amp;quot;)) {&lt;br /&gt;
     &amp;quot;bomberman_Quit&amp;quot;.destroy();&lt;br /&gt;
   }&lt;br /&gt;
   new GuiButtonCtrl(&amp;quot;bomberman_Quit&amp;quot;) {&lt;br /&gt;
     profile = GuiBlueButtonProfile;&lt;br /&gt;
     x = 600;&lt;br /&gt;
     y = 200;&lt;br /&gt;
     width = 150;&lt;br /&gt;
     height = 30;&lt;br /&gt;
     text = &amp;quot;bombermanQuit&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   temp.warpLevel = &amp;quot;only_ground.nw&amp;quot;;&lt;br /&gt;
   temp.warpX = 4.65; &lt;br /&gt;
   temp.warpY = 21.33; &lt;br /&gt;
   temp.warpZ = 0.7; &lt;br /&gt;
   WARPMANAGER.Warp(temp.warpX, temp.warpY ,temp.warpZ ,temp.warpLevel);&lt;br /&gt;
   sleep(0.5);&lt;br /&gt;
   start(); &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function bomberman_Quit.onAction() {&lt;br /&gt;
   BomberManQuit();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function BomberManQuit() {&lt;br /&gt;
   if (isObject(&amp;quot;bomberman_Quit&amp;quot;)) {&lt;br /&gt;
     &amp;quot;bomberman_Quit&amp;quot;.destroy();&lt;br /&gt;
   }&lt;br /&gt;
   PLAYERMOVEMENT.UnFreeze();&lt;br /&gt;
   PLAYERMOVEMENT.canJump = true;&lt;br /&gt;
   this.GAMEON = false;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function start() {&lt;br /&gt;
   PLAYERMOVEMENT.canJump = false;&lt;br /&gt;
   this.GAMEON = true;&lt;br /&gt;
   triggerserver(&amp;quot;gui&amp;quot;, this.name, &amp;quot;level&amp;quot;, -60 , 14);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onKeyPressed(keycode, keychar) {&lt;br /&gt;
   if (this.GAMEON == true) {&lt;br /&gt;
     if (keycode == &amp;quot;32, ,57&amp;quot;) {&lt;br /&gt;
       DropBomb();&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function DropBomb() {&lt;br /&gt;
   this.hit = RaycastHit::create();&lt;br /&gt;
   done = Physics::Raycast(player.gameobject.transform.position, Vector3::Down, this.hit, 100);&lt;br /&gt;
   //sleep(0.05);&lt;br /&gt;
   triggerserver(&amp;quot;gui&amp;quot;, this.name, &amp;quot;bomb&amp;quot;, this.hit.transform.gameobject.transform.position.x, this.hit.transform.gameobject.transform.position.z);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
the '''''Load()''''' function is called when the minigame is launched (Devtools -&amp;gt; Minigames -&amp;gt; BomberMan). &lt;br /&gt;
&lt;br /&gt;
'''level.explosionpower = 3;''' is how much tiles the explosion is going to cover. (at the beginning it's 3)&lt;br /&gt;
&lt;br /&gt;
'''level.numberofbombs = 2;''' is the number of bombs a player is allowed to place at a time. (at the beginning it's 2) &lt;br /&gt;
&lt;br /&gt;
In the function '''''start()''''', we trigger the server with the command &amp;quot;'''level'''&amp;quot; to load the bomberman map by placing an NPC and joining it with the class &amp;quot;'''3d_samples_bomberman_level'''&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Once we start the game, the player is not allowed to Jump: '''PLAYERMOVEMENT.canJump = false;''' &lt;br /&gt;
&lt;br /&gt;
And pressing space will be used to drop a bomb, '''''function onKeyPressed()''''' checks if space is pressed and calls '''''DropBomb()'''.''&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: RayCast:&amp;lt;/u&amp;gt; ====&lt;br /&gt;
Think of RayCast as '''''triggeraction()''''' that triggers NPCs at a given (x,y). Similarly, '''''RayCast''''' casts a ray given a position (origin), a direction and a length, detecting colliders.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Raycast(Vector3 origin, Vector3 direction, float maxDistance = Mathf.Infinity, int layerMask = DefaultRaycastLayers, QueryTriggerInteraction queryTriggerInteraction = QueryTriggerInteraction.UseGlobal);&lt;br /&gt;
|}&lt;br /&gt;
'''Returns:''' Boolean indicating if the RayCast hit a Collider.&lt;br /&gt;
&lt;br /&gt;
''(More info here: https://docs.unity3d.com/ScriptReference/Physics.Raycast.html&amp;lt;nowiki/&amp;gt;)''&lt;br /&gt;
&lt;br /&gt;
Here, since the bomberman level is a grid and the floor is made of squares. We want the player to drop the bomb exactly in one square and not in between two. Therefore, when space is pressed, we RayCast with the PlayerGameObject as '''origin''', with a Vector3::Down '''direction''', '''''this.hit''''' as the '''output''' and 100 for '''length'''. The other parameters are kept as default.&lt;br /&gt;
&lt;br /&gt;
This will return the collider of the GameObject underneath the player, which is one square tile.&lt;br /&gt;
&lt;br /&gt;
We extract the tile's position from '''''this.hit''''':&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.hit.transform.gameobject.transform.position.x / y&lt;br /&gt;
|}&lt;br /&gt;
And we trigger the server, with the command &amp;quot;bomb&amp;quot; and the coordinates, to place a bomb NPC;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!triggerserver(&amp;quot;gui&amp;quot;, this.name, &amp;quot;bomb&amp;quot;, this.hit.transform.gameobject.transform.position.x, this.hit.transform.gameobject.transform.position.z);&lt;br /&gt;
|}&lt;br /&gt;
 function onActionServerside(cmd, x, y) {&lt;br /&gt;
   if (cmd == &amp;quot;bomb&amp;quot;) {&lt;br /&gt;
     temp.pnpc = putnpc2(x, y, &amp;quot;&amp;quot;);&lt;br /&gt;
     temp.pnpc.join(&amp;quot;merlin_bomberman_bomb&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
   if (cmd == &amp;quot;level&amp;quot;) {&lt;br /&gt;
      temp.bombernpc = putnpc2(x, y, &amp;quot;&amp;quot;);&lt;br /&gt;
      temp.bombernpc.join(&amp;quot;merlin_bomberman_level&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
Now, on to the classes!&lt;br /&gt;
&lt;br /&gt;
'''&amp;quot;3d_samples_bomberman_level&amp;quot; Class:'''&lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   //Set a 10 minute timer to automatically destroy the levelprefab&lt;br /&gt;
   scheduleEvent(120, &amp;quot;DestLvl&amp;quot;);  &lt;br /&gt;
 }&lt;br /&gt;
 //Destroy if the server restarts&lt;br /&gt;
 &lt;br /&gt;
 function onInitialized() {&lt;br /&gt;
   this.destroy();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;dest&amp;quot;) onDestLvl();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onDestLvl() {&lt;br /&gt;
   this.destroy();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;bombermanlevel1&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onAssetBundleDownloaded(bundlename){&lt;br /&gt;
   if (bundlename == &amp;quot;bombermanlevel1&amp;quot;) {&lt;br /&gt;
     player.chat = &amp;quot;bombermanlevel loaded&amp;quot;;&lt;br /&gt;
     temp.prefab = GameObject::fromassetbundle(&amp;quot;bombermanlevel1&amp;quot;, &amp;quot;assets/bombermantest/big level 2.prefab&amp;quot;);&lt;br /&gt;
     this.bomberlevel = Object::Instantiate(Type::GameObject, temp.prefab, this.gameobject.transform, false);&lt;br /&gt;
     this.bomberlevel.transform.parent = this.gameobject.transform;&lt;br /&gt;
     this.bomberlevel.transform.localposition = v3(-15,0,0);&lt;br /&gt;
     this.bomberlevel.transform.localscale = v3(1,1,1);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;dest&amp;quot;) Object::Destroy(this.gameobject);&lt;br /&gt;
 }&lt;br /&gt;
Here we place the level GameObject in an NPC ([[Placing GameObjects in NPC]]) and we only load and instantiate the level the usual way ([[Uploading and Loading AssetBundles]]).&lt;br /&gt;
&lt;br /&gt;
'''&amp;quot;3d_samples_bomberman_bomb&amp;quot; Class:'''&lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   //echo(&amp;quot;merlin_testbomb&amp;quot;);&lt;br /&gt;
   scheduleEvent(3600, &amp;quot;RemoveBomb&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //Destroy if the server restarts&lt;br /&gt;
 function onInitialized() {&lt;br /&gt;
   this.destroy();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;/destroy&amp;quot;) {&lt;br /&gt;
     onRemoveBomb();&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onRemoveBomb() {&lt;br /&gt;
   this.destroy();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   this.dropped = false;&lt;br /&gt;
   this.powerup = randomstring({&amp;quot;bomb&amp;quot;, &amp;quot;explosion&amp;quot;, &amp;quot;speed&amp;quot;});&lt;br /&gt;
   &lt;br /&gt;
   DropBomb();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function DropBomb() {&lt;br /&gt;
   if (level.numberofbombs == 0) return;&lt;br /&gt;
   --level.numberofbombs;&lt;br /&gt;
   &lt;br /&gt;
   (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;bombermanprefabs&amp;quot;);&lt;br /&gt;
   (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;staffstick&amp;quot;);&lt;br /&gt;
   this.speedprefab = GameObject::fromassetbundle(&amp;quot;staffstick&amp;quot;,&amp;quot;assets/johntest/staffstick_era.prefab&amp;quot;);&lt;br /&gt;
   this.explosionprefab = GameObject::fromassetbundle(&amp;quot;bombermanprefabs&amp;quot;, &amp;quot;assets/bomberman/prefabs/explosion.prefab&amp;quot;);&lt;br /&gt;
   this.prefab = GameObject::fromassetbundle(&amp;quot;bombermanprefabs&amp;quot;, &amp;quot;assets/bomberman/prefabs/bomb.prefab&amp;quot;);&lt;br /&gt;
   this.bomb = Object::instantiate(Type::GameObject, this.prefab, this.gameobject.transform, false);&lt;br /&gt;
   this.bomb.transform.parent = this.gameobject.transform;&lt;br /&gt;
   this.bomb.transform.localeulerangles = v3(0, 0, 0);&lt;br /&gt;
   this.bomb.transform.localposition = v3(0, 0.5, 0);&lt;br /&gt;
 &lt;br /&gt;
   scheduleEvent(3, &amp;quot;Explode&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onExplode() {&lt;br /&gt;
   echo(&amp;quot;onexplode&amp;quot;);&lt;br /&gt;
   &lt;br /&gt;
   echo (&amp;quot;prefab type=&amp;quot; @ this.explosionprefab.objecttype());&lt;br /&gt;
   this.explosion = Object::instantiate(Type::GameObject, this.explosionprefab, this.gameobject.transform, false);&lt;br /&gt;
   echo (&amp;quot;explosion type=&amp;quot; @ this.explosion.objecttype());&lt;br /&gt;
   this.explosion.transform.parent = this.gameobject.transform;&lt;br /&gt;
   this.explosion.transform.localposition = v3(0, 0, 0);&lt;br /&gt;
   this.explosion.transform.localscale = v3(1,1,1);&lt;br /&gt;
   &lt;br /&gt;
   Object::Destroy(this.bomb, .3f);&lt;br /&gt;
   &lt;br /&gt;
   this.exploded = true;&lt;br /&gt;
 &lt;br /&gt;
   CreateExplosion(Vector3::forward);&lt;br /&gt;
   CreateExplosion(Vector3::right);&lt;br /&gt;
   CreateExplosion(Vector3::back);&lt;br /&gt;
   CreateExplosion(Vector3::left);&lt;br /&gt;
   &lt;br /&gt;
   ++level.numberofbombs;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function CreateExplosion(direction) {&lt;br /&gt;
   for (temp.i = 1; temp.i &amp;lt; level.explosionpower; temp.i++) {&lt;br /&gt;
     this.hit = RaycastHit::create();&lt;br /&gt;
     done = Physics::Raycast(this.bomb.transform.position.Add(v3(0,0.5,0)), direction, this.hit, temp.i);&lt;br /&gt;
      &lt;br /&gt;
     if (!done || this.hit.transform.gameobject.name.starts(&amp;quot;assets/bomberman/prefabs/explosion.prefab&amp;quot;) || this.hit.transform.gameobject.name.starts(&amp;quot;TPlayer&amp;quot;)){&lt;br /&gt;
       temp.explosion = Object::instantiate(Type::GameObject, this.explosionprefab, this.gameobject.transform, false);&lt;br /&gt;
       temp.explosion.transform.localposition = v3(0,0,0).Add(direction.Mult(temp.i));&lt;br /&gt;
       Object::Destroy(temp.explosion, 0.7);&lt;br /&gt;
     }&lt;br /&gt;
     if (this.hit.transform.gameobject.name.starts(&amp;quot;E_Bomber_Pilar_01_&amp;quot;)|| this.hit.transform.gameobject.transform.parent.gameobject.name.starts(&amp;quot;E_Bomber_Pilar_01_&amp;quot;)) {&lt;br /&gt;
       if (!this.dropped) {&lt;br /&gt;
         if (rand(0,1) &amp;lt; 0.2) {&lt;br /&gt;
           this.dropped = true;&lt;br /&gt;
           //drop power up&lt;br /&gt;
           droppowerup(this.hit.transform.gameobject.transform.position.x, this.hit.transform.gameobject.transform.position.z);&lt;br /&gt;
         }&lt;br /&gt;
       }&lt;br /&gt;
       Object::Destroy(this.hit.transform.gameobject.transform.parent.gameobject);&lt;br /&gt;
       Object::Destroy(this.hit.transform.gameobject);&lt;br /&gt;
       Object::Destroy(temp.explosion, 0.7);&lt;br /&gt;
       temp.explosion = Object::instantiate(Type::GameObject, this.explosionprefab, this.gameobject.transform, false);&lt;br /&gt;
       temp.explosion.transform.position = this.hit.transform.position;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function droppowerup(x,z) {&lt;br /&gt;
   if (this.powerup == &amp;quot;bomb&amp;quot;) {&lt;br /&gt;
     this.powerupGO = Object::instantiate(Type::GameObject, this.prefab, this.gameobject.transform, false);&lt;br /&gt;
   }&lt;br /&gt;
   if (this.powerup == &amp;quot;explosion&amp;quot;) {&lt;br /&gt;
     this.powerupGO = Object::instantiate(Type::GameObject, this.explosionprefab, this.gameobject.transform, false);&lt;br /&gt;
   }&lt;br /&gt;
   if (this.powerup == &amp;quot;speed&amp;quot;) {&lt;br /&gt;
     this.powerupGO = Object::instantiate(Type::GameObject, this.speedprefab, this.gameobject.transform, false);&lt;br /&gt;
   }&lt;br /&gt;
   this.powerupGO.transform.position = v3(x, 0.5, z);&lt;br /&gt;
   this.powerupGO.transform.scale = v3(0.5,0.5,0.5);&lt;br /&gt;
 &lt;br /&gt;
   sphereCollider = this.powerupGO.AddComponent(Type::SphereCollider);&lt;br /&gt;
   sphereCollider.size = v3(1, 10, 1);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function onActionGrab() {&lt;br /&gt;
   player.chat = this.powerup;&lt;br /&gt;
   Object::Destroy(this.gameobject);&lt;br /&gt;
   if (this.powerup == &amp;quot;bomb&amp;quot;) {&lt;br /&gt;
     ++level.numberofbombs;&lt;br /&gt;
   }&lt;br /&gt;
   if (this.powerup == &amp;quot;explosion&amp;quot;) {&lt;br /&gt;
     ++level.explosionpower;&lt;br /&gt;
   }&lt;br /&gt;
   if (this.powerup == &amp;quot;speed&amp;quot;) {&lt;br /&gt;
     PLAYERMOVEMENT.setSpeed(7);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
Again, we are loading and instantiating the prefabs in an NPC.&lt;br /&gt;
&lt;br /&gt;
In '''''function onCreated()''''': &lt;br /&gt;
&lt;br /&gt;
* '''''this.dropped''''' variable is used to allow every bomb to drop only one powerup.&lt;br /&gt;
* '''''this.powerup''''' variable is the name of the powerup, chosen randomly each time a bomb is dropped.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''''DropBomb()''''' is responsible for loading, instantiating and placing the bomb. The player can drop 2 bombs at a time at the start of the game. Therefore, we begin by checking if the player can drop bombs. We decrease the variable '''''level.numberofbombs''''' when a bomb is dropped and decrease it when the bomb explodes.&lt;br /&gt;
&lt;br /&gt;
After positioning the bomb, we schedule event to create the explosion after 3 seconds of placing the bomb;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!scheduleEvent(3, &amp;quot;Explode&amp;quot;);&lt;br /&gt;
|}&lt;br /&gt;
'''''onExplode()''''' function instantiates an explosion under the bomb; &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.explosion.transform.localposition = v3(0, 0, 0);&lt;br /&gt;
|}&lt;br /&gt;
and calls '''''CreateExplosion(direction);''''' in all the four directions (forward, right, left, back) to instantiate explosions in a cross shape around the bomb.&lt;br /&gt;
&lt;br /&gt;
'''''CreateExplosion(direction)''''' casts a Ray in all the four directions with the given length ('''level.explosionpower'''; the number of tiles it covers) and the bomb as the origin. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.bomb.transform.position.Add(v3(0,0.5,0));&lt;br /&gt;
|}we add a '''''Vector3 (0, 0.5, 0)''''' to increase the Y of the '''RayCast''' for it to hit the  grey pillars and not the ground.&lt;br /&gt;
&lt;br /&gt;
The two conditional blocks after are used to check if the collider hit by the raycast is a pillar or not. &lt;br /&gt;
&lt;br /&gt;
if it's a Grey Pillar, we destroy it. If not then it's empty space and we instantiate an explosion.&lt;br /&gt;
&lt;br /&gt;
When a Pillar is destroyed, there's a 20% chance it will drop a powerup, by calling the function '''''droppowerup(x,z)''''' with (x,z) the coordinates of the Pillar. &lt;br /&gt;
&lt;br /&gt;
'''''droppowerup(x,z)''''' will check '''''this.powerup''''' and create and place the appropriate GameObject. It also adds a collider Component to be triggered onActionGrab;  &lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: onActionGrab for NPCs:&amp;lt;/u&amp;gt; ====&lt;br /&gt;
For this to work, the GameObject is required to have a collider.&lt;br /&gt;
&lt;br /&gt;
And '''''public function onActionGrab()''''' needs to be implemented.&lt;br /&gt;
&lt;br /&gt;
Here, we destroy the powerup GameObject and give the player the powerup.&lt;br /&gt;
&lt;br /&gt;
(''weapon: '''3D/Player/Grab''''' for more info)&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Plane_MiniGame&amp;diff=20966</id>
		<title>Plane MiniGame</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Plane_MiniGame&amp;diff=20966"/>
		<updated>2021-11-22T14:15:06Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This minigame is similar to the Car driving minigame. However, we move a plane through obstacles.&lt;br /&gt;
&lt;br /&gt;
'''AssetBundles:''' &amp;lt;nowiki&amp;gt;https://www.graalonline.com/playerworlds/downloads/file?name=cars_planes_minigame.unitypackage&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using the bundle explorer (F10):&lt;br /&gt;
&lt;br /&gt;
'''minigameplane:'''&lt;br /&gt;
&lt;br /&gt;
[[File:Plane.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
[[File:Obstacles.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
'''env:'''&lt;br /&gt;
&lt;br /&gt;
[[File:Environment.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
Weapon: '''''3D/Samples/Planeminigame'''''&lt;br /&gt;
 findplayer(&amp;quot;GraalID&amp;quot;).addweapon(this.name);&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 &lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   this.keepAlive = true;//SetTimer(9999);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;plane&amp;quot;) start();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function start() {&lt;br /&gt;
   WARPMANAGER.Warp(19, 14 ,0.7 ,&amp;quot;only_ground.nw&amp;quot;);&lt;br /&gt;
   new GuiWindowCtrl(&amp;quot;PlaneMinigame&amp;quot;) {&lt;br /&gt;
     profile = GuiBlueWindowProfile;&lt;br /&gt;
     x = 120;&lt;br /&gt;
     y = 0;&lt;br /&gt;
     width = 670;&lt;br /&gt;
     height = 340;&lt;br /&gt;
     text = &amp;quot;Plane Minigame&amp;quot;;&lt;br /&gt;
     &lt;br /&gt;
     new GuiButtonCtrl(&amp;quot;Plane&amp;quot;) {&lt;br /&gt;
       profile = GuiBlueButtonProfile;&lt;br /&gt;
       x = 150;&lt;br /&gt;
       y = 90;&lt;br /&gt;
       width = 150;&lt;br /&gt;
       height = 30;&lt;br /&gt;
       text = &amp;quot;Spawnplane&amp;quot;;&lt;br /&gt;
     }&lt;br /&gt;
       new GuiButtonCtrl(&amp;quot;Exit&amp;quot;) {&lt;br /&gt;
       profile = GuiBlueButtonProfile;&lt;br /&gt;
       x = 150;&lt;br /&gt;
       y = 120;&lt;br /&gt;
       width = 150;&lt;br /&gt;
       height = 30;&lt;br /&gt;
       text = &amp;quot;Exit&amp;quot;;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function Plane.onAction() {&lt;br /&gt;
   exit();&lt;br /&gt;
   PLAYERMOVEMENT.Freeze();&lt;br /&gt;
   //Quattro3D::PlayerCamera::Instance.FreeCam = true;&lt;br /&gt;
   CAMERAMANGER.freecam = true;&lt;br /&gt;
   this.empty = GameObject::Create(&amp;quot;empty&amp;quot;);&lt;br /&gt;
   Quattro3D::PlayerCamera::Instance.transform.rotation = Quaternion::euler(0, -90, 0);&lt;br /&gt;
   (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;minigameplane&amp;quot;);&lt;br /&gt;
   (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;env&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onAssetBundleDownloaded(bundlename) {&lt;br /&gt;
   if (bundlename == &amp;quot;minigameplane&amp;quot;) {&lt;br /&gt;
     this.planeprefab = GameObject::fromassetbundle(&amp;quot;minigameplane&amp;quot;, &amp;quot;assets/drivingplane/vehicles/planes/small_plane02.prefab&amp;quot;);&lt;br /&gt;
     this.plane = Object::Instantiate(Type::GameObject, this.planeprefab);&lt;br /&gt;
     this.plane.transform.position = v3(player.x, player.z, player.y);&lt;br /&gt;
     this.plane.transform.localscale = v3(0.3, 0.3, 0.3);&lt;br /&gt;
     this.plane.transform.parent = this.empty.transform;&lt;br /&gt;
     &lt;br /&gt;
     this.RB = this.plane.AddComponent(Type::RigidBody);&lt;br /&gt;
     this.RB.useGravity = false;&lt;br /&gt;
     &lt;br /&gt;
     boxCollider = this.plane.AddComponent(Type::BoxCollider);&lt;br /&gt;
     boxCollider.size = v3(4,4,4);&lt;br /&gt;
 &lt;br /&gt;
     Quattro::EventManager::AddOnCollisionHandlerTo(this.plane, this.plane.layer);&lt;br /&gt;
     this.catcheventobject(this.plane, &amp;quot;onCollisionEnter&amp;quot;, &amp;quot;onPlaneCollisionEnter&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     this.obstacleprefab = GameObject::fromassetbundle(&amp;quot;minigameplane&amp;quot;, &amp;quot;assets/drivingplane/vehicles/planes/obstacles 1.prefab&amp;quot;);&lt;br /&gt;
     this.obstacle = Object::Instantiate(Type::GameObject, this.obstacleprefab);&lt;br /&gt;
     this.obstacle.transform.position = v3(player.x, player.z + 10, player.y + 20);&lt;br /&gt;
     this.obstacle.transform.localscale = v3(0.3, 0.3, 0.3);&lt;br /&gt;
     this.obstacle.transform.parent = this.empty.transform;&lt;br /&gt;
   }&lt;br /&gt;
   if (bundlename == &amp;quot;env&amp;quot;) {&lt;br /&gt;
     this.envprefab = GameObject::fromassetbundle(&amp;quot;env&amp;quot;, &amp;quot;assets/jimmyenv2/environment.prefab&amp;quot;);&lt;br /&gt;
     this.env = Object::Instantiate(Type::GameObject, this.envprefab);&lt;br /&gt;
     this.env.transform.position = v3(player.x, player.z + 1.5, player.y);&lt;br /&gt;
     this.env.transform.parent = this.empty.transform; &lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onUpdate() {&lt;br /&gt;
   temp.campos = this.plane.transform.position.Add(v3(20,0,0));&lt;br /&gt;
   Quattro3D::PlayerCamera::Instance.transform.position = temp.campos;&lt;br /&gt;
   &lt;br /&gt;
   this.verticalInput = Input::GetAxis(&amp;quot;Vertical&amp;quot;);&lt;br /&gt;
   this.horizontalInput = Input::GetAxis(&amp;quot;Horizontal&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
   this.plane.transform.translate(Vector3::forward.Mult(Time::deltaTime * 5));&lt;br /&gt;
 &lt;br /&gt;
   this.plane.transform.rotate(Vector3::Right.Mult(700 * Time::deltaTime * this.verticalInput));&lt;br /&gt;
 &lt;br /&gt;
   this.plane.transform.rotate(Vector3::Forward.Mult(700 * Time::deltaTime * this.horizontalInput * -1));&lt;br /&gt;
 &lt;br /&gt;
   this.propellor = this.plane.transform.Find(&amp;quot;Propellor&amp;quot;);&lt;br /&gt;
   this.propellor.transform.rotate(Vector3::Forward.Mult(1700 * Time::deltaTime)); &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function onPlaneCollisionEnter(gameobject, collision) {&lt;br /&gt;
   player.chat = &amp;quot;BOOM YOU LOST!&amp;quot;;&lt;br /&gt;
   exit();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function Exit.onAction() {&lt;br /&gt;
   exit(); &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function exit() {&lt;br /&gt;
   findweapon(&amp;quot;3D/Dev/ToolBar/Camera&amp;quot;).cam1();&lt;br /&gt;
   PLAYERMOVEMENT.unfreeze();&lt;br /&gt;
   Object::Destroy(this.empty);&lt;br /&gt;
   Input::ResetInputAxes();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The function '''''start()''''' creates a UI with two buttons (Spawn Plane and Exit) allowing us to start and end the game.&lt;br /&gt;
&lt;br /&gt;
'''Plane.onAction()''' ''(when the Spawn button is pressed) :'' &lt;br /&gt;
&lt;br /&gt;
Calls the '''''exit()''''' function first to destroy GameObjects instantiated before, freezes the player using '''PLAYERMOVEMENT.Freeze();''' ,frees the camera with '''Quattro3D::PlayerCamera::Instance.FreeCam = true;''' and loads all the assets we'll need to use.&lt;br /&gt;
&lt;br /&gt;
In function '''''onAssetBundleDownloaded(bundlename)''''' we catch all the loaded assetbundles, we instantiate the plane, obstacles and environment. And we position them, modify their scales, add components to them and make them a child of an empty GameObject.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.empty = GameObject::Create(&amp;quot;empty&amp;quot;);&lt;br /&gt;
|}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.obstacle.transform.parent = this.empty.transform;&lt;br /&gt;
|}&lt;br /&gt;
This will help delete all the GameObjects upon deleting the empty GameObject. ('''Object::Destroy(this.empty);''')&lt;br /&gt;
&lt;br /&gt;
Now, the '''''onUpdate()''''' function checks for updates on every frame. '''''SetTimer(9999)''''' needs to be added for it to work.&lt;br /&gt;
&lt;br /&gt;
This function will be responsible for moving the plane, moving the camera following the plane and turning the propeller of the plane.&lt;br /&gt;
&lt;br /&gt;
First for the Camera, we want it to be looking side ways at the plane. We take the plane's position and add to the X axis:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!temp.campos = this.plane.transform.position.Add(v3(20,0,0));&lt;br /&gt;
|}&lt;br /&gt;
then we change the camera position to '''''temp.campos;'''''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Quattro3D::PlayerCamera::Instance.transform.position = temp.campos;&lt;br /&gt;
|}&lt;br /&gt;
We'll also need to change the rotation of the camera since it's initially facing forward and we want it to face the plane;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Quattro3D::PlayerCamera::Instance.transform.rotation = Quaternion::euler(0, -90, 0);&lt;br /&gt;
|}&lt;br /&gt;
Now, for the movement of the plane. It will be moving forward at a constant speed; '''''this.plane.transform.translate(Vector3::forward.Mult(Time::deltaTime * 5));'''''&lt;br /&gt;
&lt;br /&gt;
And the '''''Input::GetAxis()''''' will help us move it up/down and sideways.&lt;br /&gt;
&lt;br /&gt;
We also find the propellor of the plane and move it at a constant rotation speed;&lt;br /&gt;
&lt;br /&gt;
'''''this.propellor = this.plane.transform.Find(&amp;quot;Propellor&amp;quot;);'''''&lt;br /&gt;
&lt;br /&gt;
'''''this.propellor.transform.rotate(Vector3::Forward.Mult(1700 * Time::deltaTime));''''' &lt;br /&gt;
&lt;br /&gt;
Finally, the function '''''exit()''''' switches back to the default camera: '''''findweapon(&amp;quot;3D/Dev/ToolBar/Camera&amp;quot;).cam1();'''''&lt;br /&gt;
&lt;br /&gt;
unfreezes the Player, destroys the GameObjects and resets the Input Axes using: '''''Input::ResetInputAxes();'''''&lt;br /&gt;
[[File:Planeminigame gameplay.png|center|thumb|1108x1108px]]You can also add collision detection to the plane to turn it into an actual game.&lt;br /&gt;
 Quattro::EventManager::AddOnCollisionHandlerTo(this.plane, this.plane.layer);&lt;br /&gt;
 this.catcheventobject(this.plane, &amp;quot;onCollisionEnter&amp;quot;, &amp;quot;onPlaneCollisionEnter&amp;quot;);&lt;br /&gt;
and implement the function:&lt;br /&gt;
 public function onPlaneCollisionEnter(gameobject, collision) {&lt;br /&gt;
   player.chat = &amp;quot;BOOM YOU LOST!&amp;quot;;&lt;br /&gt;
   exit();&lt;br /&gt;
 }&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Driving_MiniGame&amp;diff=20965</id>
		<title>Driving MiniGame</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Driving_MiniGame&amp;diff=20965"/>
		<updated>2021-11-22T14:14:32Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the Driving MiniGame tutorial.&lt;br /&gt;
&lt;br /&gt;
= Intro =&lt;br /&gt;
&lt;br /&gt;
==== DrivingMiniGame ====&lt;br /&gt;
This is a simple and easy car driving example. In the assetbundle, there's an environment that we load and instantiate and multiple cars that we can spawn. This game is not focused on the actual driving experience itself, but more on introducing new Unity functionalities.&lt;br /&gt;
&lt;br /&gt;
'''Asset Bundles:''' &amp;lt;nowiki&amp;gt;https://www.graalonline.com/playerworlds/downloads/file?name=cars_planes_minigame.unitypackage&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
using the bundle explorer (F10):&lt;br /&gt;
&lt;br /&gt;
'''minigame2:'''&lt;br /&gt;
&lt;br /&gt;
[[File:Minigame2.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
'''env:'''&lt;br /&gt;
&lt;br /&gt;
[[File:Minigame2 env.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
Weapon: '''''3D/Samples/Drivingminigame'''''&lt;br /&gt;
 findplayer(&amp;quot;GraalID&amp;quot;).addweapon(this.name);&lt;br /&gt;
 this.join(&amp;quot;3d_merlin_camera&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;dest&amp;quot;) dest();&lt;br /&gt;
   if (player.chat == &amp;quot;drive&amp;quot;) drive();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function drive() {&lt;br /&gt;
   destLevelName = &amp;quot;only_ground.nw&amp;quot;;&lt;br /&gt;
   x = 19;&lt;br /&gt;
   y = 10;&lt;br /&gt;
   z = 0.7;//0.7;&lt;br /&gt;
   WARPMANAGER.Warp(x, y ,z ,destLevelName);&lt;br /&gt;
 &lt;br /&gt;
   sleep(1);&lt;br /&gt;
  &lt;br /&gt;
   new GuiWindowCtrl(&amp;quot;MyGUI_Minigame_Window1&amp;quot;) {&lt;br /&gt;
     profile = GuiBlueWindowProfile;&lt;br /&gt;
     style = $pref::Video::defaultguistyle;&lt;br /&gt;
     clientrelative = true;&lt;br /&gt;
     clientextent = &amp;quot;320,240&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
     canmove = true;&lt;br /&gt;
     canresize = true;&lt;br /&gt;
     closequery = false;&lt;br /&gt;
     destroyonhide = false;&lt;br /&gt;
     text = &amp;quot;Window 1&amp;quot;;&lt;br /&gt;
     x = 490;&lt;br /&gt;
     y = 242;&lt;br /&gt;
 &lt;br /&gt;
     new GuiButtonCtrl(&amp;quot;MyGUI_Minigame_Button1&amp;quot;) {&lt;br /&gt;
       profile = GuiBlueButtonProfile;&lt;br /&gt;
       text = &amp;quot;Car&amp;quot;;&lt;br /&gt;
       width = 80;&lt;br /&gt;
       x = 77;&lt;br /&gt;
       y = 31;&lt;br /&gt;
     }&lt;br /&gt;
     new GuiButtonCtrl(&amp;quot;MyGUI_Minigame_Button2&amp;quot;) {&lt;br /&gt;
       profile = GuiBlueButtonProfile;&lt;br /&gt;
       height = 31;&lt;br /&gt;
       text = &amp;quot;Bus&amp;quot;;&lt;br /&gt;
       width = 80;&lt;br /&gt;
       x = 77;&lt;br /&gt;
       y = 69;&lt;br /&gt;
     }&lt;br /&gt;
     new GuiButtonCtrl(&amp;quot;MyGUI_Minigame_Button3&amp;quot;) {&lt;br /&gt;
       profile = GuiBlueButtonProfile;&lt;br /&gt;
       height = 31;&lt;br /&gt;
       text = &amp;quot;Quit&amp;quot;;&lt;br /&gt;
       width = 80;&lt;br /&gt;
       x = 78;&lt;br /&gt;
       y = 109;&lt;br /&gt;
     }&lt;br /&gt;
     new GuiTextCtrl(&amp;quot;MyGUI_Minigame_Text1&amp;quot;) {&lt;br /&gt;
       profile = GuiBlueTextProfile;&lt;br /&gt;
       height = 20;&lt;br /&gt;
       text = &amp;quot;Select Type:&amp;quot;;&lt;br /&gt;
       width = 71;&lt;br /&gt;
       x = 11;&lt;br /&gt;
       y = 5;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function MyGUI_Minigame_Button1.onAction() {&lt;br /&gt;
   // Button &amp;quot;Car&amp;quot; has been pressed&lt;br /&gt;
   (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;minigame2&amp;quot;);&lt;br /&gt;
   (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;env&amp;quot;);&lt;br /&gt;
   this.vehicle = &amp;quot;car&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function MyGUI_Minigame_Button2.onAction() {&lt;br /&gt;
   // Button &amp;quot;Bus&amp;quot; has been pressed&lt;br /&gt;
   (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;minigame2&amp;quot;);&lt;br /&gt;
   (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;env&amp;quot;);&lt;br /&gt;
   this.vehicle = &amp;quot;bus&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function MyGUI_Minigame_Button3.onAction() {&lt;br /&gt;
   dest();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onAssetBundleDownloaded(bundlename) {&lt;br /&gt;
   if (bundlename == &amp;quot;env&amp;quot;) {&lt;br /&gt;
     this.env = GameObject::fromassetbundle(&amp;quot;env&amp;quot;, &amp;quot;assets/jimmyenv2/Environment.prefab&amp;quot;);&lt;br /&gt;
     this.env = Object::Instantiate(Type::GameObject, this.env);&lt;br /&gt;
     this.env.transform.position = v3(player.x, player.z, player.y);&lt;br /&gt;
   }&lt;br /&gt;
   if (bundlename == &amp;quot;minigame2&amp;quot;) {&lt;br /&gt;
     if (this.vehicle == &amp;quot;bus&amp;quot;) {&lt;br /&gt;
       dest();&lt;br /&gt;
       this.vh = GameObject::fromassetbundle(&amp;quot;minigame2&amp;quot;, &amp;quot;assets/jimmyminigame2/Veh_Bus_Blue_Z.prefab&amp;quot;);&lt;br /&gt;
     }&lt;br /&gt;
     &lt;br /&gt;
     if (this.vehicle == &amp;quot;car&amp;quot;) {&lt;br /&gt;
       dest();&lt;br /&gt;
       this.vh = GameObject::fromassetbundle(&amp;quot;minigame2&amp;quot;, &amp;quot;assets/jimmyminigame2/Veh_Car_Blue_Z.prefab&amp;quot;);&lt;br /&gt;
     }&lt;br /&gt;
     &lt;br /&gt;
     this.vh = Object::Instantiate(Type::GameObject, this.vh);&lt;br /&gt;
     this.vh.transform.position = v3(player.x - 2, player.z, player.y - 5);&lt;br /&gt;
     this.vh.AddComponent(Type::RigidBody);&lt;br /&gt;
 &lt;br /&gt;
     PLAYERMOVEMENT.Freeze();&lt;br /&gt;
     //Quattro3D::PlayerCamera::Instance.FreeCam = true;&lt;br /&gt;
     CAMERAMANAGER.freecam = true;&lt;br /&gt;
     handleMovement();&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function handleMovement() {&lt;br /&gt;
   this.on = true;&lt;br /&gt;
   SetTimer(0.05);&lt;br /&gt;
   this.speed = 20;&lt;br /&gt;
   this.rotation = 400;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onFixedUpdate() {&lt;br /&gt;
   this.vInput = Input::GetAxis(&amp;quot;Vertical&amp;quot;);&lt;br /&gt;
   this.vh.transform.Translate(Vector3::forward.Mult(Time::deltaTime * this.speed * this.vInput));&lt;br /&gt;
     &lt;br /&gt;
   this.hInput = Input::GetAxis(&amp;quot;Horizontal&amp;quot;);&lt;br /&gt;
   this.vh.transform.Rotate(Vector3::up.Mult(Time::deltaTime * this.rotation * this.hInput * this.vInput));&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onTimeOut() {&lt;br /&gt;
   if(this.on) {&lt;br /&gt;
     temp.campos = this.vh.transform.position.Add(v3(0,10,-7));&lt;br /&gt;
     Quattro3D::PlayerCamera::Instance.transform.position = temp.campos;&lt;br /&gt;
     &lt;br /&gt;
     //this.vInput = Input::GetAxis(&amp;quot;Vertical&amp;quot;);&lt;br /&gt;
     &lt;br /&gt;
     //this.hInput = Input::GetAxis(&amp;quot;Horizontal&amp;quot;);&lt;br /&gt;
     //if (this.vInput &amp;lt; 0) this.hInput = - Input::GetAxis(&amp;quot;Horizontal&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     //this.vh.transform.Translate(Vector3::forward.Mult(Time::deltaTime * this.speed * this.vInput));&lt;br /&gt;
     &lt;br /&gt;
     SetTimer(0.05);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function dest() {&lt;br /&gt;
   this.on = false;&lt;br /&gt;
   findweapon(&amp;quot;3D/Dev/ToolBar/Camera&amp;quot;).cam1();&lt;br /&gt;
   PLAYERMOVEMENT.unfreeze();&lt;br /&gt;
   Object::Destroy(this.vh);&lt;br /&gt;
   Object::Destroy(this.env);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Here we create a UI for the player to choose what vehicle to choose, and we load and instantiate the prefab based on the choice.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Camera&amp;lt;/u&amp;gt; ====&lt;br /&gt;
The Camera is the point of view. Here we want the Camera to follow the car while driving and not the player.&lt;br /&gt;
&lt;br /&gt;
In '''''function onAssetBundleDownloaded(bundlename)''''' We use:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Quattro3D::PlayerCamera::Instance.FreeCam = true;&lt;br /&gt;
|}&lt;br /&gt;
To free the camera. This will free it from following the player GameObject.&lt;br /&gt;
&lt;br /&gt;
Then in '''''function onTimeOut()''''' we want the camera position to be updated with the vehicle's position.&lt;br /&gt;
&lt;br /&gt;
'''''temp.campos''''' is the variable we store the camera's position in. We want it to be behind and above the vehicle for a good view. This is why we get the vehicle's position and add a Vector3 to it:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!temp.campos = this.vh.transform.position.Add(v3(0,10,-7));&lt;br /&gt;
|}&lt;br /&gt;
now:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Quattro3D::PlayerCamera::Instance.transform.position&lt;br /&gt;
|}&lt;br /&gt;
allows us to the get the Camera GameObject and to access its transform component and change its position.&lt;br /&gt;
&lt;br /&gt;
We have implemented default cameras found in Weapon: '''''3D/Dev/ToolBar/Camera'''''&lt;br /&gt;
&lt;br /&gt;
We access them through the Weapon &amp;quot;'''''3D/Dev/ToolBar/Camera'''''&amp;quot; using:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!''findweapon(&amp;quot;3D/Dev/ToolBar/Camera&amp;quot;).cam1();''&lt;br /&gt;
|}and we call the function '''''cam1();''''' in '''''function dest()''''' to go back to the default cam.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Unity Input&amp;lt;/u&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Input::GetAxis(&amp;quot;Vertical&amp;quot;);&lt;br /&gt;
|}&lt;br /&gt;
&amp;quot;Vertical&amp;quot; / &amp;quot;Horizontal&amp;quot;&lt;br /&gt;
&lt;br /&gt;
It checks the arrows pressed and gives a value in the range of (-1 to 1) -1 indicating &amp;quot;down&amp;quot;, 1 &amp;quot;up&amp;quot; and 0 &amp;quot;neutral&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
We use it here to translate and rotate the vehicle.&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Turret_MiniGame&amp;diff=20964</id>
		<title>Turret MiniGame</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Turret_MiniGame&amp;diff=20964"/>
		<updated>2021-11-22T14:13:38Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the Turret Minigame!&lt;br /&gt;
&lt;br /&gt;
In this Tutorial, we will build a turret that rotates and shoots targets around it.  &lt;br /&gt;
&lt;br /&gt;
Asset Bundles are available here : &amp;lt;nowiki&amp;gt;https://www.graalonline.com/playerworlds/downloads/file?name=Turretminigame.unitypackage&amp;lt;/nowiki&amp;gt; &lt;br /&gt;
&lt;br /&gt;
==== TurretMiniGame GameObjects ====&lt;br /&gt;
All the prefabs are under the asset bundle: '''minigame''' (you can view them in the bundle explorer &amp;quot;F10&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Turret that shoots the projectiles:&lt;br /&gt;
&lt;br /&gt;
[[File:Turret.png|frameless|407x407px]]&lt;br /&gt;
&lt;br /&gt;
Robot that will serve as a target:&lt;br /&gt;
&lt;br /&gt;
[[File:Robot Obstacle Minigame.png|frameless|407x407px]]&lt;br /&gt;
&lt;br /&gt;
Cubes Instantiated in different position also for targets:&lt;br /&gt;
&lt;br /&gt;
[[File:Turret Minigame targets.png|frameless|405x405px]]&lt;br /&gt;
&lt;br /&gt;
 findplayer(&amp;quot;GraalID&amp;quot;).addweapon(this.name);&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;start&amp;quot;) {&lt;br /&gt;
     destroy();&lt;br /&gt;
     start();&lt;br /&gt;
   }&lt;br /&gt;
   if (player.chat == &amp;quot;dest&amp;quot;) destroy();&lt;br /&gt;
 }&lt;br /&gt;
The way I start the minigame is '''onPlayerChats'''; when the player says &amp;quot;start&amp;quot;. We'll also see how to '''destroy the GameObjects''' when the player says &amp;quot;dest&amp;quot;.&lt;br /&gt;
 function start() {&lt;br /&gt;
   this.start = true;&lt;br /&gt;
   //PLAYERMOVEMENT.Freeze();&lt;br /&gt;
   &lt;br /&gt;
   //for turret control&lt;br /&gt;
   this.rotateangle = 0; //Rotation angle of the turret&lt;br /&gt;
   this.rotateangleB = 270; //Rotation angle of the barrel&lt;br /&gt;
   this.speed = 15;&lt;br /&gt;
   &lt;br /&gt;
   this.currentX = player.x;&lt;br /&gt;
   this.currentY = player.y;&lt;br /&gt;
   this.currentZ = player.z;&lt;br /&gt;
   echo (&amp;quot;TurretMiniGame warp from=&amp;quot; @ this.currentLevel @ &amp;quot; x=&amp;quot; @ this.currentX @ &amp;quot; y=&amp;quot; @ this.currentY @ &amp;quot; z=&amp;quot; @ this.currentZ);&lt;br /&gt;
   WARPMANAGER.Warp(19, 14 ,0.7 ,&amp;quot;only_ground.nw&amp;quot;);&lt;br /&gt;
   sleep(1.5);&lt;br /&gt;
 &lt;br /&gt;
   (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;minigame&amp;quot;); //loading the assetbundle&lt;br /&gt;
 }&lt;br /&gt;
'''''this.start = true;''''' will be used to indicate that the game has started.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Using PLAYERMOVEMENT and WARPMANAGER&amp;lt;/u&amp;gt; ====&lt;br /&gt;
'''PLAYERMOVEMENT.Freeze()''' is a method that freezes the player (weapon: '''3D/Player/Core/Movement)''' &lt;br /&gt;
&lt;br /&gt;
'''WARPMANAGER.Warp(x,y,z,level)''' (weapon: '''3D/Player/Core/Warp/Manager''')&lt;br /&gt;
&lt;br /&gt;
Having uploaded the Asset bundle called &amp;quot;'''minigame'''&amp;quot; that contains the prefabs to the server, I start off by loading them, creating the prefabs, instantiating them and giving them a position in the '''start function'''  ([[Uploading and Loading AssetBundles|&amp;lt;u&amp;gt;Uploading and Loading AssetBundles&amp;lt;/u&amp;gt;]] for info on how to upload assets).&lt;br /&gt;
 function onAssetBundleDownloaded(bundlename) {&lt;br /&gt;
   if (bundlename == &amp;quot;minigame&amp;quot;) { &lt;br /&gt;
     SetTimer(9999);&lt;br /&gt;
     this.empty = GameObject::Create(&amp;quot;empty&amp;quot;); // for parenting and deleting&lt;br /&gt;
 &lt;br /&gt;
     this.turret = GameObject::fromassetbundle(&amp;quot;minigame&amp;quot;, &amp;quot;assets/jimmyminigame/turret.prefab&amp;quot;);&lt;br /&gt;
     this.robot1 = GameObject::fromassetbundle(&amp;quot;minigame&amp;quot;, &amp;quot;assets/jimmyminigame/robot.prefab&amp;quot;);&lt;br /&gt;
     this.robot2 = GameObject::fromassetbundle(&amp;quot;minigame&amp;quot;, &amp;quot;assets/jimmyminigame/robot.prefab&amp;quot;);&lt;br /&gt;
     this.wreckedrobotprefab = GameObject::fromassetbundle(&amp;quot;minigame&amp;quot;, &amp;quot;assets/jimmyminigame/robot wrecked.prefab&amp;quot;);&lt;br /&gt;
     this.projectileprefab = GameObject::fromassetbundle(&amp;quot;minigame&amp;quot;, &amp;quot;assets/jimmyminigame/projectile.prefab&amp;quot;);&lt;br /&gt;
     this.explosion = GameObject::fromassetbundle(&amp;quot;minigame&amp;quot;, &amp;quot;assets/jimmyminigame/explosion.prefab&amp;quot;);&lt;br /&gt;
     &lt;br /&gt;
     this.turret = Object::Instantiate(Type::GameObject, this.turret);&lt;br /&gt;
     this.robot1 = Object::Instantiate(Type::GameObject, this.robot1);&lt;br /&gt;
     this.robot2 = Object::Instantiate(Type::GameObject, this.robot2);&lt;br /&gt;
     &lt;br /&gt;
     this.turret.transform.position = v3(player.x, player.z, player.y);&lt;br /&gt;
     this.robot1.transform.position = v3(player.x - 5, player.z - 1, player.y + 10);&lt;br /&gt;
     this.robot2.transform.position = v3(player.x + 5, player.z - 1, player.y + 10);&lt;br /&gt;
     &lt;br /&gt;
     this.turret.transform.localscale = v3(1,1,1);&lt;br /&gt;
     this.robot1.transform.localscale = v3(1,1,1);&lt;br /&gt;
     this.robot2.transform.localscale = v3(1,1,1);&lt;br /&gt;
     &lt;br /&gt;
     loadCubes();&lt;br /&gt;
     &lt;br /&gt;
     player.charactercontroller.enabled = false;&lt;br /&gt;
     player.gameobject.transform.position = v3(player.x, player.z+5, player.y);&lt;br /&gt;
 &lt;br /&gt;
     this.launcher = GameObject::Find(&amp;quot;Launcher&amp;quot;);&lt;br /&gt;
     this.barrel = GameObject::Find(&amp;quot;Barrel&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function loadCubes() {&lt;br /&gt;
   temp.width = 10;&lt;br /&gt;
   temp.height = 4;&lt;br /&gt;
 &lt;br /&gt;
   for (temp.y = 0; temp.y &amp;lt; temp.height; ++temp.y) {&lt;br /&gt;
     for (temp.x = 0; temp.x &amp;lt; temp.width; ++temp.x) {&lt;br /&gt;
       temp.block = GameObject::CreatePrimitive(PrimitiveType::Cube);&lt;br /&gt;
       temp.block.Name = &amp;quot;myblock&amp;quot;;&lt;br /&gt;
       temp.block.transform.parent = this.empty.transform; // for deleting&lt;br /&gt;
       temp.block.transform.position = v3(player.x - 5 + temp.x, player.z + temp.y, player.y + 15);&lt;br /&gt;
       temp.block.AddComponent(Type::RigidBody);&lt;br /&gt;
       temp.block.layer = this.projectile.layer; &lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   temp.nbofobjects = 20;&lt;br /&gt;
   temp.radius = 7f;&lt;br /&gt;
 &lt;br /&gt;
   for (temp.i = 0; temp.i &amp;lt; temp.nbofobjects; ++temp.i) {&lt;br /&gt;
     temp.angle = temp.i * Mathf::PI * 2 / temp.nbofobjects;&lt;br /&gt;
     temp.x1 = cos(temp.angle) * temp.radius;&lt;br /&gt;
     temp.y1 = sin(temp.angle) * temp.radius;&lt;br /&gt;
     this.cube = GameObject::CreatePrimitive(PrimitiveType::Cube);&lt;br /&gt;
     this.cube.transform.parent = this.empty.transform;&lt;br /&gt;
     this.cube.transform.position = v3(player.x + temp.x1, player.z, player.y + temp.y1);&lt;br /&gt;
     this.cube.AddComponent(Type::RigidBody);&lt;br /&gt;
     temp.angleDegrees = -temp.angle * Mathf::Rad2Deg;&lt;br /&gt;
     this.cube.transform.rotation = Quaternion::euler(0, temp.angleDegrees, 0); &lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
In the '''''loadCubes()''''' function we instantiate primitive type cubes and position them to build a wall and a circular formation around the turret.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Moving the Player GameObject&amp;lt;/u&amp;gt; ====&lt;br /&gt;
The player is a GameObject, and its accessed by:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!player.gameobject&lt;br /&gt;
|}&lt;br /&gt;
Before changing the player's transform, the '''''player.charactercontroller''''' must be disabled:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!player.charactercontroller.enabled = false;&lt;br /&gt;
|}&lt;br /&gt;
Then we can change the position accessing the transform component of the GameObject:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!player.gameobject.transform.position = Vector3::Create(player.x, player.z+5, player.y);&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Parenting&amp;lt;/u&amp;gt; ====&lt;br /&gt;
In Unity, parenting is when a GameObject becomes a parent of another GameObject. The child GameObject will perform all it's transform changes in respect to the parent GameObject and not the Camera. Additionally, deleting the parent GameObject will delete all its children.&lt;br /&gt;
&lt;br /&gt;
We use it for the latter. We create the '''Empty GameObject''', which will serve as a parent for the Cubes ''(children)'' in order to delete them all, since we don't have a reference to each and every cube.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Finding GameObjects by Name&amp;lt;/u&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!GameObject::Find(&amp;quot;name&amp;quot;)&lt;br /&gt;
|}&lt;br /&gt;
We use it to find the barrel that we'll move up and down and the launcher that shoots the projectiles.&lt;br /&gt;
&lt;br /&gt;
Now to move the Turret;&lt;br /&gt;
 function onKeyPressed(keycode) {&lt;br /&gt;
   if (keycode == &amp;quot;90&amp;quot;) { // Z&lt;br /&gt;
     this.rotateangle -= 4;&lt;br /&gt;
     this.turret.transform.rotation = Quaternion::euler(0, this.rotateangle, 0); &lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   if (keycode == &amp;quot;67&amp;quot;) { // C&lt;br /&gt;
     this.rotateangle += 4;&lt;br /&gt;
     this.turret.transform.rotation = Quaternion::euler(0, this.rotateangle, 0);&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   if (keycode == &amp;quot;87&amp;quot;) { // W&lt;br /&gt;
     this.rotateangleB = this.rotateangleB &amp;lt; 300? this.rotateangleB + 4: 300;&lt;br /&gt;
     this.barrel.transform.LocalRotation = Quaternion::euler(this.rotateangleB, 0, 0);&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   if (keycode == &amp;quot;83&amp;quot;) { // S&lt;br /&gt;
     this.rotateangleB = this.rotateangleB &amp;gt; 258? this.rotateangleB - 4: 258;&lt;br /&gt;
     this.barrel.transform.LocalRotation = Quaternion::euler(this.rotateangleB, 0, 0);&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   if (keycode == &amp;quot;32, ,57&amp;quot;) { // Space&lt;br /&gt;
     if (this.start) {&lt;br /&gt;
       shoot();&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
We rotate the barrel around the X axis for it to go up and down;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Quaternion::euler(this.rotateangleB, 0, 0);&lt;br /&gt;
|}&lt;br /&gt;
And rotate the turret around the Y axis (Vertical axis);&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Quaternion::euler(0, this.rotateangle, 0);&lt;br /&gt;
|}&lt;br /&gt;
this.rotateangle for both cases starts at the initial rotation of the GameObjects and is incremented/decremented based on the direction of the rotation.&lt;br /&gt;
&lt;br /&gt;
In the last conditional block, if space is pressed and if the Game is on ('''''this.start == true'''''), the projectile is shot. Here's how it's done;&lt;br /&gt;
 function shoot() {&lt;br /&gt;
     SetTimer(9999);&lt;br /&gt;
     this.projectile = Object::Instantiate(Type::GameObject, this.projectileprefab);&lt;br /&gt;
     this.projectile.transform.parent = this.empty.transform;&lt;br /&gt;
     this.projectile.transform.position = this.launcher.transform.position;&lt;br /&gt;
     this.projectile.transform.scale = v3(1,1,1);&lt;br /&gt;
 &lt;br /&gt;
     temp.rigidBody = this.projectile.GetComponent(Type::RigidBody); &lt;br /&gt;
     temp.rigidBody.velocity = this.launcher.transform.forward.Mult(this.speed);&lt;br /&gt;
 &lt;br /&gt;
     Quattro::EventManager::AddOnCollisionHandlerTo(this.projectile, this.projectile.layer);&lt;br /&gt;
     this.catcheventobject(this.projectile, &amp;quot;onCollisionEnter&amp;quot;, &amp;quot;onProjectileCollisionEnter&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
The projectile is initialized and positioned on the launcher.&lt;br /&gt;
&lt;br /&gt;
We'll need to use physics to shoot the projectile, this is why we get the RigidBody component of the GameObject;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!temp.rigidBody = this.projectile.GetComponent(Type::RigidBody);&lt;br /&gt;
|}&lt;br /&gt;
(if the GameObject doesn't have a RigidBody by default, you'll need to add it using:  '''''gameobject.AddComponent(Type::RigidBody);''''')&lt;br /&gt;
&lt;br /&gt;
We then add velocity (which is a vector that represents speed in a certain direction). The direction is the Launcher's forward direction, it is multiplied by the desired speed;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!temp.rigidBody.velocity = this.launcher.transform.forward.Mult(this.speed);&lt;br /&gt;
|}&lt;br /&gt;
Now to detect collision, we make sure we '''''SetTimer(9999)''''' for the script to stay up and looking for events, we add the Collision Handler to the projectile;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Quattro::EventManager::AddOnCollisionHandlerTo(this.projectile, this.projectile.layer);&lt;br /&gt;
|}&lt;br /&gt;
and we wait for collisions;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.catcheventobject(this.projectile, &amp;quot;onCollisionEnter&amp;quot;, &amp;quot;onProjectileCollisionEnter&amp;quot;);&lt;br /&gt;
|}&lt;br /&gt;
 public function onProjectileCollisionEnter(gameobject, collision) {&lt;br /&gt;
   temp.radius = 4;&lt;br /&gt;
   temp.force = 5;&lt;br /&gt;
   &lt;br /&gt;
   player.chat = &amp;quot;boom=&amp;quot; @ collision.Gameobject.name;&lt;br /&gt;
   echo (&amp;quot;collision.Gameobject.name=&amp;quot; @ collision.Gameobject.name);&lt;br /&gt;
   &lt;br /&gt;
   temp.explosion = Object::Instantiate(Type::GameObject, this.explosion);&lt;br /&gt;
   temp.explosion.transform.parent = this.empty.transform;&lt;br /&gt;
   temp.explosion.transform.position = collision.Gameobject.transform.position;&lt;br /&gt;
   temp.explosion.transform.scale = v3(1,1,1);&lt;br /&gt;
   &lt;br /&gt;
   temp.affected = Physics::OverlapSphere(temp.explosion.transform.position, 5);&lt;br /&gt;
   for (temp.col: temp.affected) {&lt;br /&gt;
     if (temp.col.GetComponent(Type::RigidBody)!= NULL) {&lt;br /&gt;
       temp.col.GetComponent(Type::RigidBody).AddExplosionForce(temp.force, temp.explosion.transform.position, temp.radius, temp.force * 0.5f, ForceMode::Impulse);&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   if (collision.Gameobject.name == &amp;quot;assets/jimmyminigame/robot.prefab(CLONE)&amp;quot;) {&lt;br /&gt;
     this.wreckedrobot = Object::Instantiate(Type::GameObject, this.wreckedrobotprefab);&lt;br /&gt;
     this.wreckedrobot.transform.parent = this.empty.transform;&lt;br /&gt;
     this.wreckedrobot.transform.position = collision.Gameobject.transform.position;;&lt;br /&gt;
     Object::Destroy(collision.Gameobject);&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   if (collision.Gameobject.name.starts(&amp;quot;assets/jimmyminigame/projectile.prefab&amp;quot;)) return;&lt;br /&gt;
   &lt;br /&gt;
   Object::Destroy(gameobject);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Adding Explosion Force&amp;lt;/u&amp;gt; ====&lt;br /&gt;
Upon Collision, we instantiate and place the explosion. To make it seem more realistic we add an explosion force. &lt;br /&gt;
&lt;br /&gt;
We first gather the Colliders around the area of explosion with a radius of 5;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!temp.affected = Physics::OverlapSphere(temp.explosion.transform.position, 5);&lt;br /&gt;
|}&lt;br /&gt;
this will return a list of colliders in the sphere area around the explosion.&lt;br /&gt;
&lt;br /&gt;
We then make sure they have a Rigid Body component and apply explosion force to them;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!temp.col.GetComponent(Type::RigidBody).AddExplosionForce(temp.force, temp.explosion.transform.position, temp.radius, temp.force * 0.5f, ForceMode::Impulse);&lt;br /&gt;
|}&lt;br /&gt;
In this conditional block we ignore the collision if it is between two projectiles;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!if (collision.Gameobject.name.starts(&amp;quot;assets/jimmyminigame/projectile.prefab&amp;quot;)) return;&lt;br /&gt;
|}&lt;br /&gt;
 function destroy() {&lt;br /&gt;
   this.start = false;&lt;br /&gt;
   echo(&amp;quot;destroy&amp;quot;); &lt;br /&gt;
   Object::Destroy(this.turret);&lt;br /&gt;
   Object::Destroy(this.launcher);&lt;br /&gt;
   Object::Destroy(this.robot1);&lt;br /&gt;
   Object::Destroy(this.robot2);&lt;br /&gt;
   Object::Destroy(this.empty);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New : Destroying GameObjects&amp;lt;/u&amp;gt; ====&lt;br /&gt;
Here when the player says &amp;quot;dest&amp;quot;; this function is called and&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Object::Destroy(gameobject);&lt;br /&gt;
|}&lt;br /&gt;
is used to destroy the GameObject.&lt;br /&gt;
&lt;br /&gt;
We can use this function with an added parameter that indicates the time in seconds to wait before destroying the GameObject;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Object::Destroy(gameobject, seconds);&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Unity_UI&amp;diff=20963</id>
		<title>Unity UI</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Unity_UI&amp;diff=20963"/>
		<updated>2021-11-22T14:12:24Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:UnityUI.png|thumb|889x889px|none]]In this section we will go over an example of making a UI on unity and uploading and coding it on Client3D in graalscript.&lt;br /&gt;
&lt;br /&gt;
Asset Bundles can be found here : &amp;lt;nowiki&amp;gt;https://www.graalonline.com/playerworlds/downloads/file?name=MenuUI.unitypackage&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Unity Part:'''&lt;br /&gt;
&lt;br /&gt;
Open the “Quattro3D- Unity Project for bundle asset creation” folder using unity hub.&lt;br /&gt;
&lt;br /&gt;
To the assets folder, add we add a folder that will hold all the prefabs of the assetbundle.&lt;br /&gt;
&lt;br /&gt;
To the scene, add a Canvas (in the Hierarchy, right click -&amp;gt; UI -&amp;gt; Canvas). The Canvas will hold all the elements of our UI (buttons, text, scrollbar, images…).&lt;br /&gt;
&lt;br /&gt;
Select the Canvas and in the Inspector go to '''Canvas Scaler''' and select '''Scale With Screen''' for '''UI Scale Mode'''. This will allow the canvas Canvas to expand to full screen on all screens.&lt;br /&gt;
&lt;br /&gt;
Now to build the UI you see above (devtools). Start by adding Text elements (right click on Canvas -&amp;gt; UI -&amp;gt; Text).&lt;br /&gt;
&lt;br /&gt;
For each element, change the name and the text according to its function, change the color to white, add a button component and add a animation component. In the '''Rect Transform''' component, in the Anchor Presets, hold Alt and select top left to position your element.&lt;br /&gt;
&lt;br /&gt;
Add all the Text elements and position them (Inspector, Bundle Explorer, Console, Camera, Rendering).&lt;br /&gt;
&lt;br /&gt;
Now, to add the back button. Add an Image element to the UI, change its name to “back”, and in the image component add the source of the image (drop down in our case). Rotate it -90 deg on the Z axis for it to face left. Add a button component to turn it to a back button that closes the devtools.&lt;br /&gt;
&lt;br /&gt;
For the grey background you see, add and image just like before, change its color to black and change the A field in RGBA to 48 to make it transparent. Add an '''Outline''' component and change the '''Effect Color''' to white to add an outline to the image.&lt;br /&gt;
[[File:Unity UI.png|none|thumb|1006x1006px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now that we’ve added all our elements to the Canvas, it’s time to create our animations.&lt;br /&gt;
&lt;br /&gt;
To create an animation, in the top menu (next to Files, Edit, Assets…) go to Window -&amp;gt; Animation -&amp;gt; Animation.&lt;br /&gt;
&lt;br /&gt;
The animation tab should open in the bottom. Select the component you want to create an animation for and create and name the animation.&lt;br /&gt;
&lt;br /&gt;
We will be doing the sliding background image example for the animation. &lt;br /&gt;
&lt;br /&gt;
To record the animation, press on the record button. We want the image to slide in. So put the cursor on time 0s, and change the Pos X to -65 (outside of the screen) then move the cursor to 4s and change the Pos X back to 65. Press the record button again to save the recording. &lt;br /&gt;
[[File:Unity UI anim.png|none|thumb|1032x1032px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can press play to view your animation in action. To add the animation to the element; simply add an animation component and add the source of the animation you just created.&lt;br /&gt;
&lt;br /&gt;
Same thing goes for all the other animations.&lt;br /&gt;
&lt;br /&gt;
'''Graal Script Part:'''&lt;br /&gt;
&lt;br /&gt;
Now that we’ve created our prefabs and added the animations, our canvas is ready to be uploaded on the server and scripted. Save the AssetBundle and upload it to the server ([[Uploading and Loading AssetBundles]] for more info).&lt;br /&gt;
  findplayer(&amp;quot;Graal5918039&amp;quot;).addweapon(this.name);&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 &lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;dev&amp;quot;) toggle();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function toggle() {&lt;br /&gt;
   (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;devtoolsui&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onAssetBundleDownloaded(bundlename) {&lt;br /&gt;
   if (bundlename == &amp;quot;devtoolsui&amp;quot;) {&lt;br /&gt;
     this.keepAlive = true;&lt;br /&gt;
     this.btns = {&amp;quot;inscpector&amp;quot;, &amp;quot;bundleexpl&amp;quot;, &amp;quot;console&amp;quot;, &amp;quot;camera&amp;quot;, &amp;quot;rendering&amp;quot;, &amp;quot;back&amp;quot;};&lt;br /&gt;
     this.devuiprefab = GameObject::fromassetbundle(&amp;quot;devtoolsui&amp;quot;, &amp;quot;assets/menuui/canvasdevtools.prefab&amp;quot;);&lt;br /&gt;
     this.devui = Object::Instantiate(Type::GameObject, this.devuiprefab);&lt;br /&gt;
 &lt;br /&gt;
     for (btnb: this.btns) {&lt;br /&gt;
       temp.btn = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, btn);&lt;br /&gt;
       Quattro::EventManager::AddEventHandlerTo(temp.btn.gameobject.GetComponent(Type::UI::Button));&lt;br /&gt;
       this.catcheventobject(temp.btn.gameobject, &amp;quot;onClick&amp;quot;, &amp;quot;onDevToolClick&amp;quot;);&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     Object::Destroy(this.devui, 4);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function onDevToolClick(go) {&lt;br /&gt;
   if (go.name == &amp;quot;inscpector&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;bundleexpl&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;console&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;camera&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;rendering&amp;quot;) player.chat = go.name;&lt;br /&gt;
   &lt;br /&gt;
   if (go.name == &amp;quot;back&amp;quot;) close();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function close() {&lt;br /&gt;
   for (btn: this.btns) {&lt;br /&gt;
     temp.btn = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, btn);&lt;br /&gt;
     Object::Destroy(temp.btn.gameobject);&lt;br /&gt;
   } &lt;br /&gt;
   &lt;br /&gt;
   temp.img = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, &amp;quot;Image&amp;quot;);&lt;br /&gt;
   temp.anim = temp.img.gameobject.GetComponent(Type::Animation);&lt;br /&gt;
   temp.anim.play(&amp;quot;devtools2&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
We load the assetbundle the usual way: &lt;br /&gt;
 (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;devtoolsui&amp;quot;);&lt;br /&gt;
 function onAssetBundleDownloaded(bundlename) {&lt;br /&gt;
   if (bundlename == &amp;quot;devtoolsui&amp;quot;) {&lt;br /&gt;
'''''this.keepAlive = true;''''' is necessary for the weapon to keep checking for button clicks.&lt;br /&gt;
&lt;br /&gt;
We create and instantiate the canvas prefab.&lt;br /&gt;
 this.devuiprefab = GameObject::fromassetbundle(&amp;quot;devtoolsui&amp;quot;, &amp;quot;assets/menuui/canvasdevtools.prefab&amp;quot;);&lt;br /&gt;
 this.devui = Object::Instantiate(Type::GameObject, this.devuiprefab);&lt;br /&gt;
this will display the canvas on the client screen.&lt;br /&gt;
&lt;br /&gt;
To detect button clicks;&lt;br /&gt;
 temp.btn = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, btn);&lt;br /&gt;
 Quattro::EventManager::AddEventHandlerTo(temp.btn.gameobject.GetComponent(Type::UI::Button));&lt;br /&gt;
 this.catcheventobject(temp.btn.gameobject, &amp;quot;onClick&amp;quot;, &amp;quot;onDevToolClick&amp;quot;);&lt;br /&gt;
we first find the button GameObject by name ('''this.devui.transform''' being the transform component of the canvas, and '''btn''' is the button name we want to find).&lt;br /&gt;
&lt;br /&gt;
Next, we add an EventManager to the button component of the GameObject we just found ('''temp.btn.gameobject.GetComponent(Type::UI::Button)''').&lt;br /&gt;
&lt;br /&gt;
And '''this.catcheventobject(temp.btn.gameobject, &amp;quot;onClick&amp;quot;, &amp;quot;onDevToolClick&amp;quot;)''' to catch all the onClick events.&lt;br /&gt;
&lt;br /&gt;
Finally, we implement '''public function onDevToolClick(go)''' to add functionalities after button is pressed (with '''go''' the GameObject being pressed).&lt;br /&gt;
&lt;br /&gt;
For animations, to add or play an animation, you will need to get the animation component of the GameObject first. (using: '''temp.img.gameobject.GetComponent(Type::Animation)''')&lt;br /&gt;
 temp.img = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, &amp;quot;Image&amp;quot;);&lt;br /&gt;
 temp.anim = temp.img.gameobject.GetComponent(Type::Animation);&lt;br /&gt;
 temp.anim.play(&amp;quot;devtools2&amp;quot;);&lt;br /&gt;
(more script functionalities for animations available here: https://docs.unity3d.com/ScriptReference/Animation.html).&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Graal3D_Scripting_Manual&amp;diff=20962</id>
		<title>Graal3D Scripting Manual</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Graal3D_Scripting_Manual&amp;diff=20962"/>
		<updated>2021-11-18T14:17:37Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Intro ==&lt;br /&gt;
[[File:Graal kart start.jpg|center|frame]]&lt;br /&gt;
Welcome to the Graal3D Scripting Manual!&lt;br /&gt;
&lt;br /&gt;
This Manual comes in handy for beginners wanting to learn Graal3D Scripting, and advanced developers looking to expand their knowledge, as it  contains documentation, examples, tutorials and much more...&lt;br /&gt;
&lt;br /&gt;
What we will focus on in this Manual is programming our gameplay (scripting the behavior of our GameObjects, their interactions, the components attached to them...)&lt;br /&gt;
&lt;br /&gt;
==== How things work in Unity: ====&lt;br /&gt;
Unity is the leading platform for building 2D, 3D, VR and augmented reality games. It offers a scripting API in C#, allowing us to interact with the unity editor and the games we want to build.&lt;br /&gt;
&lt;br /&gt;
In the Unity editor, we create and add GameObjects to our scene, we then attach C# scripts to each that will all run upon starting the scene. Unity sort of runs everything for you, it reads through all the lights, cameras, meshes, behaviors… and processes it for you.&lt;br /&gt;
&lt;br /&gt;
==== How things work in Graal3D: ====&lt;br /&gt;
Since we will be using the Graal Unity Binding, things will be a bit different.&lt;br /&gt;
&lt;br /&gt;
The Graal Unity Binding is a binding between GraalScript and Unity, it is actually still in alpha, but most functionalities needed are present. The goal of this binding is to mimic the Unity C# scripting system (functions and classes). So if you are familiar with Unity and C#, everything should be easy. If not, then do not worry, I will go over everything step by step and include examples done in C# and compare them to GraalScript for each topic.&lt;br /&gt;
&lt;br /&gt;
The Worlds Client (which you will have to download) will serve as the Unity base scene where you instantiate your GameObjects and manipulate them with your GraalScripts.&lt;br /&gt;
&lt;br /&gt;
==== Required Downloads: ====&lt;br /&gt;
'''Unity 2020.2.2f1:''' &amp;lt;nowiki&amp;gt;https://unity3d.com/get-unity/download/archive&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''The Worlds Client:''' &amp;lt;nowiki&amp;gt;https://www.graalonline.com/playerworlds/downloads/file?name=WorldsSetup64-518.exe&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''RC:''' http://fp4.ca/windows_rc3_beta.zip&lt;br /&gt;
&lt;br /&gt;
==== Tools ====&lt;br /&gt;
In-game Unity Tools (''mimic the Unity Editor)'' &amp;amp; Game Functionality Tools ''(warping, fixing graphics, starting minigames...):'' &amp;lt;u&amp;gt;[[Tools]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
&lt;br /&gt;
==== Unity ====&lt;br /&gt;
&lt;br /&gt;
* [[Overview On Unity Basics]]&lt;br /&gt;
&lt;br /&gt;
==== AssetBundles ====&lt;br /&gt;
&lt;br /&gt;
* [[Uploading and Loading AssetBundles]]&lt;br /&gt;
*[[Placing GameObjects in NPC]]&lt;br /&gt;
&lt;br /&gt;
==== Examples and Tutorials ====&lt;br /&gt;
*[[Getting Started Examples]]&lt;br /&gt;
*[[3DTutorials|Tutorials]]&lt;br /&gt;
*[[Unity UI]]&lt;br /&gt;
&lt;br /&gt;
==== Classes, Functions and Variables ====&lt;br /&gt;
&lt;br /&gt;
* [https://quattro3d.graalonline.com/Documentation/ Quattro3D Scripting]&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Graal3D_Scripting_Manual&amp;diff=20961</id>
		<title>Graal3D Scripting Manual</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Graal3D_Scripting_Manual&amp;diff=20961"/>
		<updated>2021-11-18T13:21:53Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Intro ==&lt;br /&gt;
[[File:Graal kart start.jpg|center|frame]]&lt;br /&gt;
Welcome to the Graal3D Scripting Manual!&lt;br /&gt;
&lt;br /&gt;
This Manual comes in handy for beginners wanting to learn Graal3D Scripting, and advanced developers looking to expand their knowledge, as it  contains documentation, examples, tutorials and much more...&lt;br /&gt;
&lt;br /&gt;
What we will focus on in this Manual is programming our gameplay (scripting the behavior of our GameObjects, their interactions, the components attached to them...)&lt;br /&gt;
&lt;br /&gt;
==== How things work in Unity: ====&lt;br /&gt;
Unity is the leading platform for building 2D, 3D, VR and augmented reality games. It offers a scripting API in C#, allowing us to interact with the unity editor and the games we want to build.&lt;br /&gt;
&lt;br /&gt;
In the Unity editor, we create and add GameObjects to our scene, we then attach C# scripts to each that will all run upon starting the scene. Unity sort of runs everything for you, it reads through all the lights, cameras, meshes, behaviors… and processes it for you.&lt;br /&gt;
&lt;br /&gt;
==== How things work in Graal3D: ====&lt;br /&gt;
Since we will be using the Graal Unity Binding, things will be a bit different.&lt;br /&gt;
&lt;br /&gt;
The Graal Unity Binding is a binding between GraalScript and Unity, it is actually still in alpha, but most functionalities needed are present. The goal of this binding is to mimic the Unity C# scripting system (functions and classes). So if you are familiar with Unity and C#, everything should be easy. If not, then do not worry, I will go over everything step by step and include examples done in C# and compare them to GraalScript for each topic.&lt;br /&gt;
&lt;br /&gt;
The Worlds Client (which you will have to download) will serve as the Unity base scene where you instantiate your GameObjects and manipulate them with your GraalScripts.&lt;br /&gt;
&lt;br /&gt;
==== Required Downloads: ====&lt;br /&gt;
'''Unity 2020.2.2f1:''' &amp;lt;nowiki&amp;gt;https://unity3d.com/get-unity/download/archive&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''The Worlds Client:''' https://www.graalonline.com/playerworlds/downloads/file?name=WorldsSetup64-516.exe&lt;br /&gt;
&lt;br /&gt;
'''RC:''' http://fp4.ca/windows_rc3_beta.zip&lt;br /&gt;
&lt;br /&gt;
==== Tools ====&lt;br /&gt;
In-game Unity Tools (''mimic the Unity Editor)'' &amp;amp; Game Functionality Tools ''(warping, fixing graphics, starting minigames...):'' &amp;lt;u&amp;gt;[[Tools]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
&lt;br /&gt;
==== Unity ====&lt;br /&gt;
&lt;br /&gt;
* [[Overview On Unity Basics]]&lt;br /&gt;
&lt;br /&gt;
==== AssetBundles ====&lt;br /&gt;
&lt;br /&gt;
* [[Uploading and Loading AssetBundles]]&lt;br /&gt;
*[[Placing GameObjects in NPC]]&lt;br /&gt;
&lt;br /&gt;
==== Examples and Tutorials ====&lt;br /&gt;
*[[Getting Started Examples]]&lt;br /&gt;
*[[3DTutorials|Tutorials]]&lt;br /&gt;
*[[Unity UI]]&lt;br /&gt;
&lt;br /&gt;
==== Classes, Functions and Variables ====&lt;br /&gt;
&lt;br /&gt;
* [https://quattro3d.graalonline.com/Documentation/ Quattro3D Scripting]&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=3DTutorials&amp;diff=20960</id>
		<title>3DTutorials</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=3DTutorials&amp;diff=20960"/>
		<updated>2021-11-18T13:20:33Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This section contains Graal3D Tutorials/Minigames/Projects that have been done on the server.&lt;br /&gt;
&lt;br /&gt;
Make sure you went over and reviewed the Documentation if you are new before starting the tutorials. ([[Getting Started Examples]])&lt;br /&gt;
&lt;br /&gt;
More Unity functionalities and advanced topics will be covered here. Following these tutorials will definitely improve your understanding of the Graal Unity Binding and make you an overall better Graal3D developer.&lt;br /&gt;
&lt;br /&gt;
===== MiniGames: =====&lt;br /&gt;
&lt;br /&gt;
* [[Turret MiniGame]]&lt;br /&gt;
* [[Driving MiniGame]]&lt;br /&gt;
*[[Plane MiniGame]]&lt;br /&gt;
* [[Bomberman MiniGame]][[File:Camera05.jpg|thumb|749x749px|center]]&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Graal3D_Scripting_Manual&amp;diff=20959</id>
		<title>Graal3D Scripting Manual</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Graal3D_Scripting_Manual&amp;diff=20959"/>
		<updated>2021-11-18T13:14:34Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Intro ==&lt;br /&gt;
[[File:Graal kart start.jpg|center|frame]]&lt;br /&gt;
Welcome to the Graal3D Scripting Manual!&lt;br /&gt;
&lt;br /&gt;
This Manual comes in handy for beginners wanting to learn Graal3D Scripting, and advanced developers looking to expand their knowledge, as it  contains documentation, examples, tutorials and much more...&lt;br /&gt;
&lt;br /&gt;
What we will focus on in this Manual is programming our gameplay (scripting the behavior of our GameObjects, their interactions, the components attached to them...)&lt;br /&gt;
&lt;br /&gt;
==== How things work in Unity: ====&lt;br /&gt;
Unity is the leading platform for building 2D, 3D, VR and augmented reality games. It offers a scripting API in C#, allowing us to interact with the unity editor and the games we want to build.&lt;br /&gt;
&lt;br /&gt;
In the Unity editor, we create and add GameObjects to our scene, we then attach C# scripts to each that will all run upon starting the scene. Unity sort of runs everything for you, it reads through all the lights, cameras, meshes, behaviors… and processes it for you.&lt;br /&gt;
&lt;br /&gt;
==== How things work in Graal3D: ====&lt;br /&gt;
Since we will be using the Graal Unity Binding, things will be a bit different.&lt;br /&gt;
&lt;br /&gt;
The Graal Unity Binding is a binding between GraalScript and Unity, it is actually still in alpha, but most functionalities needed are present. The goal of this binding is to mimic the Unity C# scripting system (functions and classes). So if you are familiar with Unity and C#, everything should be easy. If not, then do not worry, I will go over everything step by step and include examples done in C# and compare them to GraalScript for each topic.&lt;br /&gt;
&lt;br /&gt;
The Worlds Client (which you will have to download) will serve as the Unity base scene where you instantiate your GameObjects and manipulate them with your GraalScripts.&lt;br /&gt;
&lt;br /&gt;
==== Required Downloads: ====&lt;br /&gt;
'''Unity 2020.2.2f1:''' &amp;lt;nowiki&amp;gt;https://unity3d.com/get-unity/download/archive&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''The Worlds Client:''' https://www.graalonline.com/playerworlds/downloads/file?name=WorldsSetup64-516.exe&lt;br /&gt;
&lt;br /&gt;
'''RC:''' http://fp4.ca/windows_rc3_beta.zip&lt;br /&gt;
&lt;br /&gt;
==== Tools ====&lt;br /&gt;
In-game Unity Tools (''mimic the Unity Editor)'' &amp;amp; Game Functionality Tools ''(warping, fixing graphics, starting minigames...):'' &amp;lt;u&amp;gt;[[Tools]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
&lt;br /&gt;
==== Unity ====&lt;br /&gt;
&lt;br /&gt;
* [[Overview On Unity Basics]]&lt;br /&gt;
&lt;br /&gt;
==== AssetBundles ====&lt;br /&gt;
&lt;br /&gt;
* [[Uploading and Loading AssetBundles]]&lt;br /&gt;
*[[Placing GameObjects in NPC]]&lt;br /&gt;
&lt;br /&gt;
==== Examples and Tutorials ====&lt;br /&gt;
*[[Getting Started Examples]]&lt;br /&gt;
*[[3DTutorials|Tutorials]]&lt;br /&gt;
*[[Unity UI]]&lt;br /&gt;
*[[Item Manager]]&lt;br /&gt;
&lt;br /&gt;
==== Classes, Functions and Variables ====&lt;br /&gt;
&lt;br /&gt;
* [https://quattro3d.graalonline.com/Documentation/ Quattro3D Scripting]&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Unity_UI&amp;diff=20958</id>
		<title>Unity UI</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Unity_UI&amp;diff=20958"/>
		<updated>2021-11-18T13:07:30Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:UnityUI.png|thumb|889x889px|none]]In this section we will go over an example of making a UI on unity and uploading and coding it on Client3D in graalscript.&lt;br /&gt;
&lt;br /&gt;
'''Unity Part:'''&lt;br /&gt;
&lt;br /&gt;
Open the “Quattro3D- Unity Project for bundle asset creation” folder using unity hub.&lt;br /&gt;
&lt;br /&gt;
To the assets folder, add we add a folder that will hold all the prefabs of the assetbundle.&lt;br /&gt;
&lt;br /&gt;
To the scene, add a Canvas (in the Hierarchy, right click -&amp;gt; UI -&amp;gt; Canvas). The Canvas will hold all the elements of our UI (buttons, text, scrollbar, images…).&lt;br /&gt;
&lt;br /&gt;
Select the Canvas and in the Inspector go to '''Canvas Scaler''' and select '''Scale With Screen''' for '''UI Scale Mode'''. This will allow the canvas Canvas to expand to full screen on all screens.&lt;br /&gt;
&lt;br /&gt;
Now to build the UI you see above (devtools). Start by adding Text elements (right click on Canvas -&amp;gt; UI -&amp;gt; Text).&lt;br /&gt;
&lt;br /&gt;
For each element, change the name and the text according to its function, change the color to white, add a button component and add a animation component. In the '''Rect Transform''' component, in the Anchor Presets, hold Alt and select top left to position your element.&lt;br /&gt;
&lt;br /&gt;
Add all the Text elements and position them (Inspector, Bundle Explorer, Console, Camera, Rendering).&lt;br /&gt;
&lt;br /&gt;
Now, to add the back button. Add an Image element to the UI, change its name to “back”, and in the image component add the source of the image (drop down in our case). Rotate it -90 deg on the Z axis for it to face left. Add a button component to turn it to a back button that closes the devtools.&lt;br /&gt;
&lt;br /&gt;
For the grey background you see, add and image just like before, change its color to black and change the A field in RGBA to 48 to make it transparent. Add an '''Outline''' component and change the '''Effect Color''' to white to add an outline to the image.&lt;br /&gt;
[[File:Unity UI.png|none|thumb|1006x1006px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now that we’ve added all our elements to the Canvas, it’s time to create our animations.&lt;br /&gt;
&lt;br /&gt;
To create an animation, in the top menu (next to Files, Edit, Assets…) go to Window -&amp;gt; Animation -&amp;gt; Animation.&lt;br /&gt;
&lt;br /&gt;
The animation tab should open in the bottom. Select the component you want to create an animation for and create and name the animation.&lt;br /&gt;
&lt;br /&gt;
We will be doing the sliding background image example for the animation. &lt;br /&gt;
&lt;br /&gt;
To record the animation, press on the record button. We want the image to slide in. So put the cursor on time 0s, and change the Pos X to -65 (outside of the screen) then move the cursor to 4s and change the Pos X back to 65. Press the record button again to save the recording. &lt;br /&gt;
[[File:Unity UI anim.png|none|thumb|1032x1032px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can press play to view your animation in action. To add the animation to the element; simply add an animation component and add the source of the animation you just created.&lt;br /&gt;
&lt;br /&gt;
Same thing goes for all the other animations.&lt;br /&gt;
&lt;br /&gt;
'''Graal Script Part:'''&lt;br /&gt;
&lt;br /&gt;
Now that we’ve created our prefabs and added the animations, our canvas is ready to be uploaded on the server and scripted. Save the AssetBundle and upload it to the server ([[Uploading and Loading AssetBundles]] for more info).&lt;br /&gt;
  findplayer(&amp;quot;Graal5918039&amp;quot;).addweapon(this.name);&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 &lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;dev&amp;quot;) toggle();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function toggle() {&lt;br /&gt;
   (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;devtoolsui&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onAssetBundleDownloaded(bundlename) {&lt;br /&gt;
   if (bundlename == &amp;quot;devtoolsui&amp;quot;) {&lt;br /&gt;
     this.keepAlive = true;&lt;br /&gt;
     this.btns = {&amp;quot;inscpector&amp;quot;, &amp;quot;bundleexpl&amp;quot;, &amp;quot;console&amp;quot;, &amp;quot;camera&amp;quot;, &amp;quot;rendering&amp;quot;, &amp;quot;back&amp;quot;};&lt;br /&gt;
     this.devuiprefab = GameObject::fromassetbundle(&amp;quot;devtoolsui&amp;quot;, &amp;quot;assets/menuui/canvasdevtools.prefab&amp;quot;);&lt;br /&gt;
     this.devui = Object::Instantiate(Type::GameObject, this.devuiprefab);&lt;br /&gt;
 &lt;br /&gt;
     for (btnb: this.btns) {&lt;br /&gt;
       temp.btn = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, btn);&lt;br /&gt;
       Quattro::EventManager::AddEventHandlerTo(temp.btn.gameobject.GetComponent(Type::UI::Button));&lt;br /&gt;
       this.catcheventobject(temp.btn.gameobject, &amp;quot;onClick&amp;quot;, &amp;quot;onDevToolClick&amp;quot;);&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     Object::Destroy(this.devui, 4);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function onDevToolClick(go) {&lt;br /&gt;
   if (go.name == &amp;quot;inscpector&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;bundleexpl&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;console&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;camera&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;rendering&amp;quot;) player.chat = go.name;&lt;br /&gt;
   &lt;br /&gt;
   if (go.name == &amp;quot;back&amp;quot;) close();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function close() {&lt;br /&gt;
   for (btn: this.btns) {&lt;br /&gt;
     temp.btn = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, btn);&lt;br /&gt;
     Object::Destroy(temp.btn.gameobject);&lt;br /&gt;
   } &lt;br /&gt;
   &lt;br /&gt;
   temp.img = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, &amp;quot;Image&amp;quot;);&lt;br /&gt;
   temp.anim = temp.img.gameobject.GetComponent(Type::Animation);&lt;br /&gt;
   temp.anim.play(&amp;quot;devtools2&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
We load the assetbundle the usual way: &lt;br /&gt;
 (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;devtoolsui&amp;quot;);&lt;br /&gt;
 function onAssetBundleDownloaded(bundlename) {&lt;br /&gt;
   if (bundlename == &amp;quot;devtoolsui&amp;quot;) {&lt;br /&gt;
'''''this.keepAlive = true;''''' is necessary for the weapon to keep checking for button clicks.&lt;br /&gt;
&lt;br /&gt;
We create and instantiate the canvas prefab.&lt;br /&gt;
 this.devuiprefab = GameObject::fromassetbundle(&amp;quot;devtoolsui&amp;quot;, &amp;quot;assets/menuui/canvasdevtools.prefab&amp;quot;);&lt;br /&gt;
 this.devui = Object::Instantiate(Type::GameObject, this.devuiprefab);&lt;br /&gt;
this will display the canvas on the client screen.&lt;br /&gt;
&lt;br /&gt;
To detect button clicks;&lt;br /&gt;
 temp.btn = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, btn);&lt;br /&gt;
 Quattro::EventManager::AddEventHandlerTo(temp.btn.gameobject.GetComponent(Type::UI::Button));&lt;br /&gt;
 this.catcheventobject(temp.btn.gameobject, &amp;quot;onClick&amp;quot;, &amp;quot;onDevToolClick&amp;quot;);&lt;br /&gt;
we first find the button GameObject by name ('''this.devui.transform''' being the transform component of the canvas, and '''btn''' is the button name we want to find).&lt;br /&gt;
&lt;br /&gt;
Next, we add an EventManager to the button component of the GameObject we just found ('''temp.btn.gameobject.GetComponent(Type::UI::Button)''').&lt;br /&gt;
&lt;br /&gt;
And '''this.catcheventobject(temp.btn.gameobject, &amp;quot;onClick&amp;quot;, &amp;quot;onDevToolClick&amp;quot;)''' to catch all the onClick events.&lt;br /&gt;
&lt;br /&gt;
Finally, we implement '''public function onDevToolClick(go)''' to add functionalities after button is pressed (with '''go''' the GameObject being pressed).&lt;br /&gt;
&lt;br /&gt;
For animations, to add or play an animation, you will need to get the animation component of the GameObject first. (using: '''temp.img.gameobject.GetComponent(Type::Animation)''')&lt;br /&gt;
 temp.img = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, &amp;quot;Image&amp;quot;);&lt;br /&gt;
 temp.anim = temp.img.gameobject.GetComponent(Type::Animation);&lt;br /&gt;
 temp.anim.play(&amp;quot;devtools2&amp;quot;);&lt;br /&gt;
(more script functionalities for animations available here: https://docs.unity3d.com/ScriptReference/Animation.html).&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Turret_MiniGame&amp;diff=20957</id>
		<title>Turret MiniGame</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Turret_MiniGame&amp;diff=20957"/>
		<updated>2021-11-18T13:03:03Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the Turret Minigame!&lt;br /&gt;
&lt;br /&gt;
In this Tutorial, we will build a turret that rotates and shoots targets around it.  &lt;br /&gt;
&lt;br /&gt;
The Assets are available on the server. &lt;br /&gt;
&lt;br /&gt;
==== TurretMiniGame GameObjects ====&lt;br /&gt;
All the prefabs are under the asset bundle: '''minigame''' (you can view them in the bundle explorer &amp;quot;F10&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Turret that shoots the projectiles:&lt;br /&gt;
&lt;br /&gt;
[[File:Turret.png|frameless|407x407px]]&lt;br /&gt;
&lt;br /&gt;
Robot that will serve as a target:&lt;br /&gt;
&lt;br /&gt;
[[File:Robot Obstacle Minigame.png|frameless|407x407px]]&lt;br /&gt;
&lt;br /&gt;
Cubes Instantiated in different position also for targets:&lt;br /&gt;
&lt;br /&gt;
[[File:Turret Minigame targets.png|frameless|405x405px]]&lt;br /&gt;
&lt;br /&gt;
 findplayer(&amp;quot;GraalID&amp;quot;).addweapon(this.name);&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;start&amp;quot;) {&lt;br /&gt;
     destroy();&lt;br /&gt;
     start();&lt;br /&gt;
   }&lt;br /&gt;
   if (player.chat == &amp;quot;dest&amp;quot;) destroy();&lt;br /&gt;
 }&lt;br /&gt;
The way I start the minigame is '''onPlayerChats'''; when the player says &amp;quot;start&amp;quot;. We'll also see how to '''destroy the GameObjects''' when the player says &amp;quot;dest&amp;quot;.&lt;br /&gt;
 function start() {&lt;br /&gt;
   this.start = true;&lt;br /&gt;
   //PLAYERMOVEMENT.Freeze();&lt;br /&gt;
   &lt;br /&gt;
   //for turret control&lt;br /&gt;
   this.rotateangle = 0; //Rotation angle of the turret&lt;br /&gt;
   this.rotateangleB = 270; //Rotation angle of the barrel&lt;br /&gt;
   this.speed = 15;&lt;br /&gt;
   &lt;br /&gt;
   this.currentX = player.x;&lt;br /&gt;
   this.currentY = player.y;&lt;br /&gt;
   this.currentZ = player.z;&lt;br /&gt;
   echo (&amp;quot;TurretMiniGame warp from=&amp;quot; @ this.currentLevel @ &amp;quot; x=&amp;quot; @ this.currentX @ &amp;quot; y=&amp;quot; @ this.currentY @ &amp;quot; z=&amp;quot; @ this.currentZ);&lt;br /&gt;
   WARPMANAGER.Warp(19, 14 ,0.7 ,&amp;quot;only_ground.nw&amp;quot;);&lt;br /&gt;
   sleep(1.5);&lt;br /&gt;
 &lt;br /&gt;
   (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;minigame&amp;quot;); //loading the assetbundle&lt;br /&gt;
 }&lt;br /&gt;
'''''this.start = true;''''' will be used to indicate that the game has started.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Using PLAYERMOVEMENT and WARPMANAGER&amp;lt;/u&amp;gt; ====&lt;br /&gt;
'''PLAYERMOVEMENT.Freeze()''' is a method that freezes the player (weapon: '''3D/Player/Core/Movement)''' &lt;br /&gt;
&lt;br /&gt;
'''WARPMANAGER.Warp(x,y,z,level)''' (weapon: '''3D/Player/Core/Warp/Manager''')&lt;br /&gt;
&lt;br /&gt;
Having uploaded the Asset bundle called &amp;quot;'''minigame'''&amp;quot; that contains the prefabs to the server, I start off by loading them, creating the prefabs, instantiating them and giving them a position in the '''start function'''  ([[Uploading and Loading AssetBundles|&amp;lt;u&amp;gt;Uploading and Loading AssetBundles&amp;lt;/u&amp;gt;]] for info on how to upload assets).&lt;br /&gt;
 function onAssetBundleDownloaded(bundlename) {&lt;br /&gt;
   if (bundlename == &amp;quot;minigame&amp;quot;) { &lt;br /&gt;
     SetTimer(9999);&lt;br /&gt;
     this.empty = GameObject::Create(&amp;quot;empty&amp;quot;); // for parenting and deleting&lt;br /&gt;
 &lt;br /&gt;
     this.turret = GameObject::fromassetbundle(&amp;quot;minigame&amp;quot;, &amp;quot;assets/jimmyminigame/turret.prefab&amp;quot;);&lt;br /&gt;
     this.robot1 = GameObject::fromassetbundle(&amp;quot;minigame&amp;quot;, &amp;quot;assets/jimmyminigame/robot.prefab&amp;quot;);&lt;br /&gt;
     this.robot2 = GameObject::fromassetbundle(&amp;quot;minigame&amp;quot;, &amp;quot;assets/jimmyminigame/robot.prefab&amp;quot;);&lt;br /&gt;
     this.wreckedrobotprefab = GameObject::fromassetbundle(&amp;quot;minigame&amp;quot;, &amp;quot;assets/jimmyminigame/robot wrecked.prefab&amp;quot;);&lt;br /&gt;
     this.projectileprefab = GameObject::fromassetbundle(&amp;quot;minigame&amp;quot;, &amp;quot;assets/jimmyminigame/projectile.prefab&amp;quot;);&lt;br /&gt;
     this.explosion = GameObject::fromassetbundle(&amp;quot;minigame&amp;quot;, &amp;quot;assets/jimmyminigame/explosion.prefab&amp;quot;);&lt;br /&gt;
     &lt;br /&gt;
     this.turret = Object::Instantiate(Type::GameObject, this.turret);&lt;br /&gt;
     this.robot1 = Object::Instantiate(Type::GameObject, this.robot1);&lt;br /&gt;
     this.robot2 = Object::Instantiate(Type::GameObject, this.robot2);&lt;br /&gt;
     &lt;br /&gt;
     this.turret.transform.position = v3(player.x, player.z, player.y);&lt;br /&gt;
     this.robot1.transform.position = v3(player.x - 5, player.z - 1, player.y + 10);&lt;br /&gt;
     this.robot2.transform.position = v3(player.x + 5, player.z - 1, player.y + 10);&lt;br /&gt;
     &lt;br /&gt;
     this.turret.transform.localscale = v3(1,1,1);&lt;br /&gt;
     this.robot1.transform.localscale = v3(1,1,1);&lt;br /&gt;
     this.robot2.transform.localscale = v3(1,1,1);&lt;br /&gt;
     &lt;br /&gt;
     loadCubes();&lt;br /&gt;
     &lt;br /&gt;
     player.charactercontroller.enabled = false;&lt;br /&gt;
     player.gameobject.transform.position = v3(player.x, player.z+5, player.y);&lt;br /&gt;
 &lt;br /&gt;
     this.launcher = GameObject::Find(&amp;quot;Launcher&amp;quot;);&lt;br /&gt;
     this.barrel = GameObject::Find(&amp;quot;Barrel&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function loadCubes() {&lt;br /&gt;
   temp.width = 10;&lt;br /&gt;
   temp.height = 4;&lt;br /&gt;
 &lt;br /&gt;
   for (temp.y = 0; temp.y &amp;lt; temp.height; ++temp.y) {&lt;br /&gt;
     for (temp.x = 0; temp.x &amp;lt; temp.width; ++temp.x) {&lt;br /&gt;
       temp.block = GameObject::CreatePrimitive(PrimitiveType::Cube);&lt;br /&gt;
       temp.block.Name = &amp;quot;myblock&amp;quot;;&lt;br /&gt;
       temp.block.transform.parent = this.empty.transform; // for deleting&lt;br /&gt;
       temp.block.transform.position = v3(player.x - 5 + temp.x, player.z + temp.y, player.y + 15);&lt;br /&gt;
       temp.block.AddComponent(Type::RigidBody);&lt;br /&gt;
       temp.block.layer = this.projectile.layer; &lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   temp.nbofobjects = 20;&lt;br /&gt;
   temp.radius = 7f;&lt;br /&gt;
 &lt;br /&gt;
   for (temp.i = 0; temp.i &amp;lt; temp.nbofobjects; ++temp.i) {&lt;br /&gt;
     temp.angle = temp.i * Mathf::PI * 2 / temp.nbofobjects;&lt;br /&gt;
     temp.x1 = cos(temp.angle) * temp.radius;&lt;br /&gt;
     temp.y1 = sin(temp.angle) * temp.radius;&lt;br /&gt;
     this.cube = GameObject::CreatePrimitive(PrimitiveType::Cube);&lt;br /&gt;
     this.cube.transform.parent = this.empty.transform;&lt;br /&gt;
     this.cube.transform.position = v3(player.x + temp.x1, player.z, player.y + temp.y1);&lt;br /&gt;
     this.cube.AddComponent(Type::RigidBody);&lt;br /&gt;
     temp.angleDegrees = -temp.angle * Mathf::Rad2Deg;&lt;br /&gt;
     this.cube.transform.rotation = Quaternion::euler(0, temp.angleDegrees, 0); &lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
In the '''''loadCubes()''''' function we instantiate primitive type cubes and position them to build a wall and a circular formation around the turret.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Moving the Player GameObject&amp;lt;/u&amp;gt; ====&lt;br /&gt;
The player is a GameObject, and its accessed by:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!player.gameobject&lt;br /&gt;
|}&lt;br /&gt;
Before changing the player's transform, the '''''player.charactercontroller''''' must be disabled:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!player.charactercontroller.enabled = false;&lt;br /&gt;
|}&lt;br /&gt;
Then we can change the position accessing the transform component of the GameObject:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!player.gameobject.transform.position = Vector3::Create(player.x, player.z+5, player.y);&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Parenting&amp;lt;/u&amp;gt; ====&lt;br /&gt;
In Unity, parenting is when a GameObject becomes a parent of another GameObject. The child GameObject will perform all it's transform changes in respect to the parent GameObject and not the Camera. Additionally, deleting the parent GameObject will delete all its children.&lt;br /&gt;
&lt;br /&gt;
We use it for the latter. We create the '''Empty GameObject''', which will serve as a parent for the Cubes ''(children)'' in order to delete them all, since we don't have a reference to each and every cube.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Finding GameObjects by Name&amp;lt;/u&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!GameObject::Find(&amp;quot;name&amp;quot;)&lt;br /&gt;
|}&lt;br /&gt;
We use it to find the barrel that we'll move up and down and the launcher that shoots the projectiles.&lt;br /&gt;
&lt;br /&gt;
Now to move the Turret;&lt;br /&gt;
 function onKeyPressed(keycode) {&lt;br /&gt;
   if (keycode == &amp;quot;90&amp;quot;) { // Z&lt;br /&gt;
     this.rotateangle -= 4;&lt;br /&gt;
     this.turret.transform.rotation = Quaternion::euler(0, this.rotateangle, 0); &lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   if (keycode == &amp;quot;67&amp;quot;) { // C&lt;br /&gt;
     this.rotateangle += 4;&lt;br /&gt;
     this.turret.transform.rotation = Quaternion::euler(0, this.rotateangle, 0);&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   if (keycode == &amp;quot;87&amp;quot;) { // W&lt;br /&gt;
     this.rotateangleB = this.rotateangleB &amp;lt; 300? this.rotateangleB + 4: 300;&lt;br /&gt;
     this.barrel.transform.LocalRotation = Quaternion::euler(this.rotateangleB, 0, 0);&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   if (keycode == &amp;quot;83&amp;quot;) { // S&lt;br /&gt;
     this.rotateangleB = this.rotateangleB &amp;gt; 258? this.rotateangleB - 4: 258;&lt;br /&gt;
     this.barrel.transform.LocalRotation = Quaternion::euler(this.rotateangleB, 0, 0);&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   if (keycode == &amp;quot;32, ,57&amp;quot;) { // Space&lt;br /&gt;
     if (this.start) {&lt;br /&gt;
       shoot();&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
We rotate the barrel around the X axis for it to go up and down;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Quaternion::euler(this.rotateangleB, 0, 0);&lt;br /&gt;
|}&lt;br /&gt;
And rotate the turret around the Y axis (Vertical axis);&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Quaternion::euler(0, this.rotateangle, 0);&lt;br /&gt;
|}&lt;br /&gt;
this.rotateangle for both cases starts at the initial rotation of the GameObjects and is incremented/decremented based on the direction of the rotation.&lt;br /&gt;
&lt;br /&gt;
In the last conditional block, if space is pressed and if the Game is on ('''''this.start == true'''''), the projectile is shot. Here's how it's done;&lt;br /&gt;
 function shoot() {&lt;br /&gt;
     SetTimer(9999);&lt;br /&gt;
     this.projectile = Object::Instantiate(Type::GameObject, this.projectileprefab);&lt;br /&gt;
     this.projectile.transform.parent = this.empty.transform;&lt;br /&gt;
     this.projectile.transform.position = this.launcher.transform.position;&lt;br /&gt;
     this.projectile.transform.scale = v3(1,1,1);&lt;br /&gt;
 &lt;br /&gt;
     temp.rigidBody = this.projectile.GetComponent(Type::RigidBody); &lt;br /&gt;
     temp.rigidBody.velocity = this.launcher.transform.forward.Mult(this.speed);&lt;br /&gt;
 &lt;br /&gt;
     Quattro::EventManager::AddOnCollisionHandlerTo(this.projectile, this.projectile.layer);&lt;br /&gt;
     this.catcheventobject(this.projectile, &amp;quot;onCollisionEnter&amp;quot;, &amp;quot;onProjectileCollisionEnter&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
The projectile is initialized and positioned on the launcher.&lt;br /&gt;
&lt;br /&gt;
We'll need to use physics to shoot the projectile, this is why we get the RigidBody component of the GameObject;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!temp.rigidBody = this.projectile.GetComponent(Type::RigidBody);&lt;br /&gt;
|}&lt;br /&gt;
(if the GameObject doesn't have a RigidBody by default, you'll need to add it using:  '''''gameobject.AddComponent(Type::RigidBody);''''')&lt;br /&gt;
&lt;br /&gt;
We then add velocity (which is a vector that represents speed in a certain direction). The direction is the Launcher's forward direction, it is multiplied by the desired speed;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!temp.rigidBody.velocity = this.launcher.transform.forward.Mult(this.speed);&lt;br /&gt;
|}&lt;br /&gt;
Now to detect collision, we make sure we '''''SetTimer(9999)''''' for the script to stay up and looking for events, we add the Collision Handler to the projectile;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Quattro::EventManager::AddOnCollisionHandlerTo(this.projectile, this.projectile.layer);&lt;br /&gt;
|}&lt;br /&gt;
and we wait for collisions;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.catcheventobject(this.projectile, &amp;quot;onCollisionEnter&amp;quot;, &amp;quot;onProjectileCollisionEnter&amp;quot;);&lt;br /&gt;
|}&lt;br /&gt;
 public function onProjectileCollisionEnter(gameobject, collision) {&lt;br /&gt;
   temp.radius = 4;&lt;br /&gt;
   temp.force = 5;&lt;br /&gt;
   &lt;br /&gt;
   player.chat = &amp;quot;boom=&amp;quot; @ collision.Gameobject.name;&lt;br /&gt;
   echo (&amp;quot;collision.Gameobject.name=&amp;quot; @ collision.Gameobject.name);&lt;br /&gt;
   &lt;br /&gt;
   temp.explosion = Object::Instantiate(Type::GameObject, this.explosion);&lt;br /&gt;
   temp.explosion.transform.parent = this.empty.transform;&lt;br /&gt;
   temp.explosion.transform.position = collision.Gameobject.transform.position;&lt;br /&gt;
   temp.explosion.transform.scale = v3(1,1,1);&lt;br /&gt;
   &lt;br /&gt;
   temp.affected = Physics::OverlapSphere(temp.explosion.transform.position, 5);&lt;br /&gt;
   for (temp.col: temp.affected) {&lt;br /&gt;
     if (temp.col.GetComponent(Type::RigidBody)!= NULL) {&lt;br /&gt;
       temp.col.GetComponent(Type::RigidBody).AddExplosionForce(temp.force, temp.explosion.transform.position, temp.radius, temp.force * 0.5f, ForceMode::Impulse);&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   if (collision.Gameobject.name == &amp;quot;assets/jimmyminigame/robot.prefab(CLONE)&amp;quot;) {&lt;br /&gt;
     this.wreckedrobot = Object::Instantiate(Type::GameObject, this.wreckedrobotprefab);&lt;br /&gt;
     this.wreckedrobot.transform.parent = this.empty.transform;&lt;br /&gt;
     this.wreckedrobot.transform.position = collision.Gameobject.transform.position;;&lt;br /&gt;
     Object::Destroy(collision.Gameobject);&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   if (collision.Gameobject.name.starts(&amp;quot;assets/jimmyminigame/projectile.prefab&amp;quot;)) return;&lt;br /&gt;
   &lt;br /&gt;
   Object::Destroy(gameobject);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Adding Explosion Force&amp;lt;/u&amp;gt; ====&lt;br /&gt;
Upon Collision, we instantiate and place the explosion. To make it seem more realistic we add an explosion force. &lt;br /&gt;
&lt;br /&gt;
We first gather the Colliders around the area of explosion with a radius of 5;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!temp.affected = Physics::OverlapSphere(temp.explosion.transform.position, 5);&lt;br /&gt;
|}&lt;br /&gt;
this will return a list of colliders in the sphere area around the explosion.&lt;br /&gt;
&lt;br /&gt;
We then make sure they have a Rigid Body component and apply explosion force to them;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!temp.col.GetComponent(Type::RigidBody).AddExplosionForce(temp.force, temp.explosion.transform.position, temp.radius, temp.force * 0.5f, ForceMode::Impulse);&lt;br /&gt;
|}&lt;br /&gt;
In this conditional block we ignore the collision if it is between two projectiles;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!if (collision.Gameobject.name.starts(&amp;quot;assets/jimmyminigame/projectile.prefab&amp;quot;)) return;&lt;br /&gt;
|}&lt;br /&gt;
 function destroy() {&lt;br /&gt;
   this.start = false;&lt;br /&gt;
   echo(&amp;quot;destroy&amp;quot;); &lt;br /&gt;
   Object::Destroy(this.turret);&lt;br /&gt;
   Object::Destroy(this.launcher);&lt;br /&gt;
   Object::Destroy(this.robot1);&lt;br /&gt;
   Object::Destroy(this.robot2);&lt;br /&gt;
   Object::Destroy(this.empty);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New : Destroying GameObjects&amp;lt;/u&amp;gt; ====&lt;br /&gt;
Here when the player says &amp;quot;dest&amp;quot;; this function is called and&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Object::Destroy(gameobject);&lt;br /&gt;
|}&lt;br /&gt;
is used to destroy the GameObject.&lt;br /&gt;
&lt;br /&gt;
We can use this function with an added parameter that indicates the time in seconds to wait before destroying the GameObject;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Object::Destroy(gameobject, seconds);&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Graal3D_Scripting_Manual&amp;diff=20956</id>
		<title>Graal3D Scripting Manual</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Graal3D_Scripting_Manual&amp;diff=20956"/>
		<updated>2021-11-18T12:28:09Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Intro ==&lt;br /&gt;
[[File:Graal kart start.jpg|center|frame]]&lt;br /&gt;
Welcome to the Graal3D Scripting Manual!&lt;br /&gt;
&lt;br /&gt;
This Manual comes in handy for beginners wanting to learn Graal3D Scripting, and advanced developers looking to expand their knowledge, as it  contains documentation, examples, tutorials and much more...&lt;br /&gt;
&lt;br /&gt;
What we will focus on in this Manual is programming our gameplay (scripting the behavior of our GameObjects, their interactions, the components attached to them...)&lt;br /&gt;
&lt;br /&gt;
==== How things work in Unity: ====&lt;br /&gt;
Unity is the leading platform for building 2D, 3D, VR and augmented reality games. It offers a scripting API in C#, allowing us to interact with the unity editor and the games we want to build.&lt;br /&gt;
&lt;br /&gt;
In the Unity editor, we create and add GameObjects to our scene, we then attach C# scripts to each that will all run upon starting the scene. Unity sort of runs everything for you, it reads through all the lights, cameras, meshes, behaviors… and processes it for you.&lt;br /&gt;
&lt;br /&gt;
==== How things work in Graal3D: ====&lt;br /&gt;
Since we will be using the Graal Unity Binding, things will be a bit different.&lt;br /&gt;
&lt;br /&gt;
The Graal Unity Binding is a binding between GraalScript and Unity, it is actually still in alpha, but most functionalities needed are present. The goal of this binding is to mimic the Unity C# scripting system (functions and classes). So if you are familiar with Unity and C#, everything should be easy. If not, then do not worry, I will go over everything step by step and include examples done in C# and compare them to GraalScript for each topic.&lt;br /&gt;
&lt;br /&gt;
The Worlds Client (which you will have to download) will serve as the Unity base scene where you instantiate your GameObjects and manipulate them with your GraalScripts.&lt;br /&gt;
&lt;br /&gt;
==== Required Downloads: ====&lt;br /&gt;
'''Unity 2020.2.2f1:''' [https://www.graalonline.com/playerworlds/downloads/file?name=WorldsSetup64-515.exe https://unity3d.com/get-unity/download/archive]&lt;br /&gt;
&lt;br /&gt;
'''The Worlds Client:''' https://www.graalonline.com/playerworlds/downloads/file?name=WorldsSetup64-516.exe&lt;br /&gt;
&lt;br /&gt;
'''RC:''' http://fp4.ca/windows_rc3_beta.zip&lt;br /&gt;
&lt;br /&gt;
==== Tools ====&lt;br /&gt;
In-game Unity Tools (''mimic the Unity Editor)'' &amp;amp; Game Functionality Tools ''(warping, fixing graphics, starting minigames...):'' &amp;lt;u&amp;gt;[[Tools]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
&lt;br /&gt;
==== Unity ====&lt;br /&gt;
&lt;br /&gt;
* [[Overview On Unity Basics]]&lt;br /&gt;
&lt;br /&gt;
==== AssetBundles ====&lt;br /&gt;
&lt;br /&gt;
* [[Uploading and Loading AssetBundles]]&lt;br /&gt;
*[[Placing GameObjects in NPC]]&lt;br /&gt;
&lt;br /&gt;
==== Examples and Tutorials ====&lt;br /&gt;
*[[Getting Started Examples]]&lt;br /&gt;
*[[3DTutorials|Tutorials]]&lt;br /&gt;
*[[Unity UI]]&lt;br /&gt;
*[[Item Manager]]&lt;br /&gt;
&lt;br /&gt;
==== Classes, Functions and Variables ====&lt;br /&gt;
&lt;br /&gt;
* [https://quattro3d.graalonline.com/Documentation/ Quattro3D Scripting]&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Graal3D_Scripting_Manual&amp;diff=20954</id>
		<title>Graal3D Scripting Manual</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Graal3D_Scripting_Manual&amp;diff=20954"/>
		<updated>2021-11-14T19:42:41Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Intro ==&lt;br /&gt;
[[File:Graal kart start.jpg|center|frame]]&lt;br /&gt;
Welcome to the Graal3D Scripting Manual!&lt;br /&gt;
&lt;br /&gt;
This Manual comes in handy for beginners wanting to learn Graal3D Scripting, and advanced developers looking to expand their knowledge, as it  contains documentation, examples, tutorials and much more...&lt;br /&gt;
&lt;br /&gt;
What we will focus on in this Manual is programming our gameplay (scripting the behavior of our GameObjects, their interactions, the components attached to them...)&lt;br /&gt;
&lt;br /&gt;
==== How things work in Unity: ====&lt;br /&gt;
Unity is the leading platform for building 2D, 3D, VR and augmented reality games. It offers a scripting API in C#, allowing us to interact with the unity editor and the games we want to build.&lt;br /&gt;
&lt;br /&gt;
In the Unity editor, we create and add GameObjects to our scene, we then attach C# scripts to each that will all run upon starting the scene. Unity sort of runs everything for you, it reads through all the lights, cameras, meshes, behaviors… and processes it for you.&lt;br /&gt;
&lt;br /&gt;
==== How things work in Graal3D: ====&lt;br /&gt;
Since we will be using the Graal Unity Binding, things will be a bit different.&lt;br /&gt;
&lt;br /&gt;
The Graal Unity Binding is a binding between GraalScript and Unity, it is actually still in alpha, but most functionalities needed are present. The goal of this binding is to mimic the Unity C# scripting system (functions and classes). So if you are familiar with Unity and C#, everything should be easy. If not, then do not worry, I will go over everything step by step and include examples done in C# and compare them to GraalScript for each topic.&lt;br /&gt;
&lt;br /&gt;
The Worlds Client (which you will have to download) will serve as the Unity editor, mentioned earlier, which contains the base scene where you instantiate your GameObjects and manipulate them with your GraalScripts.&lt;br /&gt;
&lt;br /&gt;
==== Required Downloads: ====&lt;br /&gt;
'''Unity 2020.2.2f1:''' [https://www.graalonline.com/playerworlds/downloads/file?name=WorldsSetup64-515.exe https://unity3d.com/get-unity/download/archive]&lt;br /&gt;
&lt;br /&gt;
'''The Worlds Client:''' https://www.graalonline.com/playerworlds/downloads/file?name=WorldsSetup64-516.exe&lt;br /&gt;
&lt;br /&gt;
'''RC:''' http://fp4.ca/windows_rc3_beta.zip&lt;br /&gt;
&lt;br /&gt;
==== Tools ====&lt;br /&gt;
In-game Unity Tools (''mimic the Unity Editor)'' &amp;amp; Game Functionality Tools ''(warping, fixing graphics, starting minigames...):'' &amp;lt;u&amp;gt;[[Tools]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
&lt;br /&gt;
==== Unity ====&lt;br /&gt;
&lt;br /&gt;
* [[Overview On Unity Basics]]&lt;br /&gt;
&lt;br /&gt;
==== AssetBundles ====&lt;br /&gt;
&lt;br /&gt;
* [[Uploading and Loading AssetBundles]]&lt;br /&gt;
*[[Placing GameObjects in NPC]]&lt;br /&gt;
&lt;br /&gt;
==== Examples and Tutorials ====&lt;br /&gt;
*[[Getting Started Examples]]&lt;br /&gt;
*[[3DTutorials|Tutorials]]&lt;br /&gt;
*[[Unity UI]]&lt;br /&gt;
*[[Item Manager]]&lt;br /&gt;
&lt;br /&gt;
==== Classes, Functions and Variables ====&lt;br /&gt;
&lt;br /&gt;
* [https://quattro3d.graalonline.com/Documentation/ Quattro3D Scripting]&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Bomberman_MiniGame&amp;diff=20941</id>
		<title>Bomberman MiniGame</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Bomberman_MiniGame&amp;diff=20941"/>
		<updated>2021-10-15T07:20:27Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the Bomberman Minigame Tutorial!&lt;br /&gt;
&lt;br /&gt;
= BomberMan =&lt;br /&gt;
&lt;br /&gt;
==== Intro ====&lt;br /&gt;
BomberMan is a multiplayer game (usually 4 players). Each player can drop bombs that, upon explosion,  destroy the grey pillars making a path to other players. The objective of the game is to eliminate other players with the exploding bombs. Power ups are also sometimes dropped when pillars are destroyed (increase of speed, explosion power and number of bombs allowed to place at a time).&lt;br /&gt;
[[File:Bomberman cover.png|none|thumb|675x675px]]&lt;br /&gt;
Assets are available on the server under:&lt;br /&gt;
&lt;br /&gt;
'''bombermanprefabs'''&lt;br /&gt;
&lt;br /&gt;
[[File:Bomberman prefabs.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
and '''bombermanlevel1'''&lt;br /&gt;
&lt;br /&gt;
[[File:Bomberman level prefab.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
Since this game is meant to be multiplayer, we will be placing the GameObjects in NPCs for them to be visible to all the players and triggerring the server every time we want to place them. (more info on that here: [[Placing GameObjects in NPC]])&lt;br /&gt;
&lt;br /&gt;
First, we have the weapon that launches the game and places the NPCs (''found under '''weapon: 3D/Samples/BomberMan/Game''''')&lt;br /&gt;
&lt;br /&gt;
We've implemented a graalscript UI (which is not covered in this section, considering you know graalscript) that allows us to launch the game;&lt;br /&gt;
 function onActionServerside(cmd, x, y) {&lt;br /&gt;
   if (cmd == &amp;quot;bomb&amp;quot;) {&lt;br /&gt;
     temp.pnpc = putnpc2(x, y, &amp;quot;&amp;quot;);&lt;br /&gt;
     temp.pnpc.join(&amp;quot;merlin_bomberman_bomb&amp;quot;);&lt;br /&gt;
     //temp.pnpc.DropBomb(explvl);&lt;br /&gt;
   }&lt;br /&gt;
   if (cmd == &amp;quot;level&amp;quot;) {&lt;br /&gt;
      temp.bombernpc = putnpc2(x, y, &amp;quot;&amp;quot;);&lt;br /&gt;
      temp.bombernpc.join(&amp;quot;merlin_bomberman_level&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   echo(this.name @ &amp;quot; OnCreated&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function Load() {&lt;br /&gt;
   level.explosionpower = 3; //for powerups with explosion&lt;br /&gt;
   level.numberofbombs = 2; //number of bombs allowed to place at a time&lt;br /&gt;
   level.speed = 7; //player default speed&lt;br /&gt;
   &lt;br /&gt;
   echo(this.name @ &amp;quot; LOAD&amp;quot;);&lt;br /&gt;
   Object::destroy(this.bomberManParentNode);&lt;br /&gt;
   if (isObject(&amp;quot;bomberman_Quit&amp;quot;)) {&lt;br /&gt;
     &amp;quot;bomberman_Quit&amp;quot;.destroy();&lt;br /&gt;
   }&lt;br /&gt;
   new GuiButtonCtrl(&amp;quot;bomberman_Quit&amp;quot;) {&lt;br /&gt;
     profile = GuiBlueButtonProfile;&lt;br /&gt;
     x = 600;&lt;br /&gt;
     y = 200;&lt;br /&gt;
     width = 150;&lt;br /&gt;
     height = 30;&lt;br /&gt;
     text = &amp;quot;bombermanQuit&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   temp.warpLevel = &amp;quot;only_ground.nw&amp;quot;;&lt;br /&gt;
   temp.warpX = 4.65; &lt;br /&gt;
   temp.warpY = 21.33; &lt;br /&gt;
   temp.warpZ = 0.7; &lt;br /&gt;
   WARPMANAGER.Warp(temp.warpX, temp.warpY ,temp.warpZ ,temp.warpLevel);&lt;br /&gt;
   sleep(0.5);&lt;br /&gt;
   start(); &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function bomberman_Quit.onAction() {&lt;br /&gt;
   BomberManQuit();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function BomberManQuit() {&lt;br /&gt;
   if (isObject(&amp;quot;bomberman_Quit&amp;quot;)) {&lt;br /&gt;
     &amp;quot;bomberman_Quit&amp;quot;.destroy();&lt;br /&gt;
   }&lt;br /&gt;
   PLAYERMOVEMENT.UnFreeze();&lt;br /&gt;
   PLAYERMOVEMENT.canJump = true;&lt;br /&gt;
   this.GAMEON = false;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function start() {&lt;br /&gt;
   PLAYERMOVEMENT.canJump = false;&lt;br /&gt;
   this.GAMEON = true;&lt;br /&gt;
   triggerserver(&amp;quot;gui&amp;quot;, this.name, &amp;quot;level&amp;quot;, -60 , 14);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onKeyPressed(keycode, keychar) {&lt;br /&gt;
   if (this.GAMEON == true) {&lt;br /&gt;
     if (keycode == &amp;quot;32, ,57&amp;quot;) {&lt;br /&gt;
       DropBomb();&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function DropBomb() {&lt;br /&gt;
   this.hit = RaycastHit::create();&lt;br /&gt;
   done = Physics::Raycast(player.gameobject.transform.position, Vector3::Down, this.hit, 100);&lt;br /&gt;
   //sleep(0.05);&lt;br /&gt;
   triggerserver(&amp;quot;gui&amp;quot;, this.name, &amp;quot;bomb&amp;quot;, this.hit.transform.gameobject.transform.position.x, this.hit.transform.gameobject.transform.position.z);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
the '''''Load()''''' function is called when the minigame is launched (Devtools -&amp;gt; Minigames -&amp;gt; BomberMan). &lt;br /&gt;
&lt;br /&gt;
'''level.explosionpower = 3;''' is how much tiles the explosion is going to cover. (at the beginning it's 3)&lt;br /&gt;
&lt;br /&gt;
'''level.numberofbombs = 2;''' is the number of bombs a player is allowed to place at a time. (at the beginning it's 2) &lt;br /&gt;
&lt;br /&gt;
In the function '''''start()''''', we trigger the server with the command &amp;quot;'''level'''&amp;quot; to load the bomberman map by placing an NPC and joining it with the class &amp;quot;'''3d_samples_bomberman_level'''&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Once we start the game, the player is not allowed to Jump: '''PLAYERMOVEMENT.canJump = false;''' &lt;br /&gt;
&lt;br /&gt;
And pressing space will be used to drop a bomb, '''''function onKeyPressed()''''' checks if space is pressed and calls '''''DropBomb()'''.''&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: RayCast:&amp;lt;/u&amp;gt; ====&lt;br /&gt;
Think of RayCast as '''''triggeraction()''''' that triggers NPCs at a given (x,y). Similarly, '''''RayCast''''' casts a ray given a position (origin), a direction and a length, detecting colliders.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Raycast(Vector3 origin, Vector3 direction, float maxDistance = Mathf.Infinity, int layerMask = DefaultRaycastLayers, QueryTriggerInteraction queryTriggerInteraction = QueryTriggerInteraction.UseGlobal);&lt;br /&gt;
|}&lt;br /&gt;
'''Returns:''' Boolean indicating if the RayCast hit a Collider.&lt;br /&gt;
&lt;br /&gt;
''(More info here: https://docs.unity3d.com/ScriptReference/Physics.Raycast.html&amp;lt;nowiki/&amp;gt;)''&lt;br /&gt;
&lt;br /&gt;
Here, since the bomberman level is a grid and the floor is made of squares. We want the player to drop the bomb exactly in one square and not in between two. Therefore, when space is pressed, we RayCast with the PlayerGameObject as '''origin''', with a Vector3::Down '''direction''', '''''this.hit''''' as the '''output''' and 100 for '''length'''. The other parameters are kept as default.&lt;br /&gt;
&lt;br /&gt;
This will return the collider of the GameObject underneath the player, which is one square tile.&lt;br /&gt;
&lt;br /&gt;
We extract the tile's position from '''''this.hit''''':&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.hit.transform.gameobject.transform.position.x / y&lt;br /&gt;
|}&lt;br /&gt;
And we trigger the server, with the command &amp;quot;bomb&amp;quot; and the coordinates, to place a bomb NPC;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!triggerserver(&amp;quot;gui&amp;quot;, this.name, &amp;quot;bomb&amp;quot;, this.hit.transform.gameobject.transform.position.x, this.hit.transform.gameobject.transform.position.z);&lt;br /&gt;
|}&lt;br /&gt;
 function onActionServerside(cmd, x, y) {&lt;br /&gt;
   if (cmd == &amp;quot;bomb&amp;quot;) {&lt;br /&gt;
     temp.pnpc = putnpc2(x, y, &amp;quot;&amp;quot;);&lt;br /&gt;
     temp.pnpc.join(&amp;quot;merlin_bomberman_bomb&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
   if (cmd == &amp;quot;level&amp;quot;) {&lt;br /&gt;
      temp.bombernpc = putnpc2(x, y, &amp;quot;&amp;quot;);&lt;br /&gt;
      temp.bombernpc.join(&amp;quot;merlin_bomberman_level&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
Now, on to the classes!&lt;br /&gt;
&lt;br /&gt;
'''&amp;quot;3d_samples_bomberman_level&amp;quot; Class:'''&lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   //Set a 10 minute timer to automatically destroy the levelprefab&lt;br /&gt;
   scheduleEvent(120, &amp;quot;DestLvl&amp;quot;);  &lt;br /&gt;
 }&lt;br /&gt;
 //Destroy if the server restarts&lt;br /&gt;
 &lt;br /&gt;
 function onInitialized() {&lt;br /&gt;
   this.destroy();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;dest&amp;quot;) onDestLvl();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onDestLvl() {&lt;br /&gt;
   this.destroy();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;bombermanlevel1&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onAssetBundleDownloaded(bundlename){&lt;br /&gt;
   if (bundlename == &amp;quot;bombermanlevel1&amp;quot;) {&lt;br /&gt;
     player.chat = &amp;quot;bombermanlevel loaded&amp;quot;;&lt;br /&gt;
     temp.prefab = GameObject::fromassetbundle(&amp;quot;bombermanlevel1&amp;quot;, &amp;quot;assets/bombermantest/big level 2.prefab&amp;quot;);&lt;br /&gt;
     this.bomberlevel = Object::Instantiate(Type::GameObject, temp.prefab, this.gameobject.transform, false);&lt;br /&gt;
     this.bomberlevel.transform.parent = this.gameobject.transform;&lt;br /&gt;
     this.bomberlevel.transform.localposition = v3(-15,0,0);&lt;br /&gt;
     this.bomberlevel.transform.localscale = v3(1,1,1);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;dest&amp;quot;) Object::Destroy(this.gameobject);&lt;br /&gt;
 }&lt;br /&gt;
Here we place the level GameObject in an NPC ([[Placing GameObjects in NPC]]) and we only load and instantiate the level the usual way ([[Uploading and Loading AssetBundles]]).&lt;br /&gt;
&lt;br /&gt;
'''&amp;quot;3d_samples_bomberman_bomb&amp;quot; Class:'''&lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   //echo(&amp;quot;merlin_testbomb&amp;quot;);&lt;br /&gt;
   scheduleEvent(3600, &amp;quot;RemoveBomb&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //Destroy if the server restarts&lt;br /&gt;
 function onInitialized() {&lt;br /&gt;
   this.destroy();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;/destroy&amp;quot;) {&lt;br /&gt;
     onRemoveBomb();&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onRemoveBomb() {&lt;br /&gt;
   this.destroy();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   this.dropped = false;&lt;br /&gt;
   this.powerup = randomstring({&amp;quot;bomb&amp;quot;, &amp;quot;explosion&amp;quot;, &amp;quot;speed&amp;quot;});&lt;br /&gt;
   &lt;br /&gt;
   DropBomb();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function DropBomb() {&lt;br /&gt;
   if (level.numberofbombs == 0) return;&lt;br /&gt;
   --level.numberofbombs;&lt;br /&gt;
   &lt;br /&gt;
   (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;bombermanprefabs&amp;quot;);&lt;br /&gt;
   (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;staffstick&amp;quot;);&lt;br /&gt;
   this.speedprefab = GameObject::fromassetbundle(&amp;quot;staffstick&amp;quot;,&amp;quot;assets/johntest/staffstick_era.prefab&amp;quot;);&lt;br /&gt;
   this.explosionprefab = GameObject::fromassetbundle(&amp;quot;bombermanprefabs&amp;quot;, &amp;quot;assets/bomberman/prefabs/explosion.prefab&amp;quot;);&lt;br /&gt;
   this.prefab = GameObject::fromassetbundle(&amp;quot;bombermanprefabs&amp;quot;, &amp;quot;assets/bomberman/prefabs/bomb.prefab&amp;quot;);&lt;br /&gt;
   this.bomb = Object::instantiate(Type::GameObject, this.prefab, this.gameobject.transform, false);&lt;br /&gt;
   this.bomb.transform.parent = this.gameobject.transform;&lt;br /&gt;
   this.bomb.transform.localeulerangles = v3(0, 0, 0);&lt;br /&gt;
   this.bomb.transform.localposition = v3(0, 0.5, 0);&lt;br /&gt;
 &lt;br /&gt;
   scheduleEvent(3, &amp;quot;Explode&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onExplode() {&lt;br /&gt;
   echo(&amp;quot;onexplode&amp;quot;);&lt;br /&gt;
   &lt;br /&gt;
   echo (&amp;quot;prefab type=&amp;quot; @ this.explosionprefab.objecttype());&lt;br /&gt;
   this.explosion = Object::instantiate(Type::GameObject, this.explosionprefab, this.gameobject.transform, false);&lt;br /&gt;
   echo (&amp;quot;explosion type=&amp;quot; @ this.explosion.objecttype());&lt;br /&gt;
   this.explosion.transform.parent = this.gameobject.transform;&lt;br /&gt;
   this.explosion.transform.localposition = v3(0, 0, 0);&lt;br /&gt;
   this.explosion.transform.localscale = v3(1,1,1);&lt;br /&gt;
   &lt;br /&gt;
   Object::Destroy(this.bomb, .3f);&lt;br /&gt;
   &lt;br /&gt;
   this.exploded = true;&lt;br /&gt;
 &lt;br /&gt;
   CreateExplosion(Vector3::forward);&lt;br /&gt;
   CreateExplosion(Vector3::right);&lt;br /&gt;
   CreateExplosion(Vector3::back);&lt;br /&gt;
   CreateExplosion(Vector3::left);&lt;br /&gt;
   &lt;br /&gt;
   ++level.numberofbombs;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function CreateExplosion(direction) {&lt;br /&gt;
   for (temp.i = 1; temp.i &amp;lt; level.explosionpower; temp.i++) {&lt;br /&gt;
     this.hit = RaycastHit::create();&lt;br /&gt;
     done = Physics::Raycast(this.bomb.transform.position.Add(v3(0,0.5,0)), direction, this.hit, temp.i);&lt;br /&gt;
      &lt;br /&gt;
     if (!done || this.hit.transform.gameobject.name.starts(&amp;quot;assets/bomberman/prefabs/explosion.prefab&amp;quot;) || this.hit.transform.gameobject.name.starts(&amp;quot;TPlayer&amp;quot;)){&lt;br /&gt;
       temp.explosion = Object::instantiate(Type::GameObject, this.explosionprefab, this.gameobject.transform, false);&lt;br /&gt;
       temp.explosion.transform.localposition = v3(0,0,0).Add(direction.Mult(temp.i));&lt;br /&gt;
       Object::Destroy(temp.explosion, 0.7);&lt;br /&gt;
     }&lt;br /&gt;
     if (this.hit.transform.gameobject.name.starts(&amp;quot;E_Bomber_Pilar_01_&amp;quot;)|| this.hit.transform.gameobject.transform.parent.gameobject.name.starts(&amp;quot;E_Bomber_Pilar_01_&amp;quot;)) {&lt;br /&gt;
       if (!this.dropped) {&lt;br /&gt;
         if (rand(0,1) &amp;lt; 0.2) {&lt;br /&gt;
           this.dropped = true;&lt;br /&gt;
           //drop power up&lt;br /&gt;
           droppowerup(this.hit.transform.gameobject.transform.position.x, this.hit.transform.gameobject.transform.position.z);&lt;br /&gt;
         }&lt;br /&gt;
       }&lt;br /&gt;
       Object::Destroy(this.hit.transform.gameobject.transform.parent.gameobject);&lt;br /&gt;
       Object::Destroy(this.hit.transform.gameobject);&lt;br /&gt;
       Object::Destroy(temp.explosion, 0.7);&lt;br /&gt;
       temp.explosion = Object::instantiate(Type::GameObject, this.explosionprefab, this.gameobject.transform, false);&lt;br /&gt;
       temp.explosion.transform.position = this.hit.transform.position;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function droppowerup(x,z) {&lt;br /&gt;
   if (this.powerup == &amp;quot;bomb&amp;quot;) {&lt;br /&gt;
     this.powerupGO = Object::instantiate(Type::GameObject, this.prefab, this.gameobject.transform, false);&lt;br /&gt;
   }&lt;br /&gt;
   if (this.powerup == &amp;quot;explosion&amp;quot;) {&lt;br /&gt;
     this.powerupGO = Object::instantiate(Type::GameObject, this.explosionprefab, this.gameobject.transform, false);&lt;br /&gt;
   }&lt;br /&gt;
   if (this.powerup == &amp;quot;speed&amp;quot;) {&lt;br /&gt;
     this.powerupGO = Object::instantiate(Type::GameObject, this.speedprefab, this.gameobject.transform, false);&lt;br /&gt;
   }&lt;br /&gt;
   this.powerupGO.transform.position = v3(x, 0.5, z);&lt;br /&gt;
   this.powerupGO.transform.scale = v3(0.5,0.5,0.5);&lt;br /&gt;
 &lt;br /&gt;
   sphereCollider = this.powerupGO.AddComponent(Type::SphereCollider);&lt;br /&gt;
   sphereCollider.size = v3(1, 10, 1);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function onActionGrab() {&lt;br /&gt;
   player.chat = this.powerup;&lt;br /&gt;
   Object::Destroy(this.gameobject);&lt;br /&gt;
   if (this.powerup == &amp;quot;bomb&amp;quot;) {&lt;br /&gt;
     ++level.numberofbombs;&lt;br /&gt;
   }&lt;br /&gt;
   if (this.powerup == &amp;quot;explosion&amp;quot;) {&lt;br /&gt;
     ++level.explosionpower;&lt;br /&gt;
   }&lt;br /&gt;
   if (this.powerup == &amp;quot;speed&amp;quot;) {&lt;br /&gt;
     PLAYERMOVEMENT.setSpeed(7);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
Again, we are loading and instantiating the prefabs in an NPC.&lt;br /&gt;
&lt;br /&gt;
In '''''function onCreated()''''': &lt;br /&gt;
&lt;br /&gt;
* '''''this.dropped''''' variable is used to allow every bomb to drop only one powerup.&lt;br /&gt;
* '''''this.powerup''''' variable is the name of the powerup, chosen randomly each time a bomb is dropped.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''''DropBomb()''''' is responsible for loading, instantiating and placing the bomb. The player can drop 2 bombs at a time at the start of the game. Therefore, we begin by checking if the player can drop bombs. We decrease the variable '''''level.numberofbombs''''' when a bomb is dropped and decrease it when the bomb explodes.&lt;br /&gt;
&lt;br /&gt;
After positioning the bomb, we schedule event to create the explosion after 3 seconds of placing the bomb;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!scheduleEvent(3, &amp;quot;Explode&amp;quot;);&lt;br /&gt;
|}&lt;br /&gt;
'''''onExplode()''''' function instantiates an explosion under the bomb; &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.explosion.transform.localposition = v3(0, 0, 0);&lt;br /&gt;
|}&lt;br /&gt;
and calls '''''CreateExplosion(direction);''''' in all the four directions (forward, right, left, back) to instantiate explosions in a cross shape around the bomb.&lt;br /&gt;
&lt;br /&gt;
'''''CreateExplosion(direction)''''' casts a Ray in all the four directions with the given length ('''level.explosionpower'''; the number of tiles it covers) and the bomb as the origin. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.bomb.transform.position.Add(v3(0,0.5,0));&lt;br /&gt;
|}we add a '''''Vector3 (0, 0.5, 0)''''' to increase the Y of the '''RayCast''' for it to hit the  grey pillars and not the ground.&lt;br /&gt;
&lt;br /&gt;
The two conditional blocks after are used to check if the collider hit by the raycast is a pillar or not. &lt;br /&gt;
&lt;br /&gt;
if it's a Grey Pillar, we destroy it. If not then it's empty space and we instantiate an explosion.&lt;br /&gt;
&lt;br /&gt;
When a Pillar is destroyed, there's a 20% chance it will drop a powerup, by calling the function '''''droppowerup(x,z)''''' with (x,z) the coordinates of the Pillar. &lt;br /&gt;
&lt;br /&gt;
'''''droppowerup(x,z)''''' will check '''''this.powerup''''' and create and place the appropriate GameObject. It also adds a collider Component to be triggered onActionGrab;  &lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: onActionGrab for NPCs:&amp;lt;/u&amp;gt; ====&lt;br /&gt;
For this to work, the GameObject is required to have a collider.&lt;br /&gt;
&lt;br /&gt;
And '''''public function onActionGrab()''''' needs to be implemented.&lt;br /&gt;
&lt;br /&gt;
Here, we destroy the powerup GameObject and give the player the powerup.&lt;br /&gt;
&lt;br /&gt;
(''weapon: '''3D/Player/Grab''''' for more info)&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Unity_UI&amp;diff=20940</id>
		<title>Unity UI</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Unity_UI&amp;diff=20940"/>
		<updated>2021-10-15T07:12:19Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:UnityUI.png|thumb|889x889px|none]]In this section we will go over an example of making a UI on unity and uploading and coding it on Client3D in graalscript.&lt;br /&gt;
&lt;br /&gt;
'''Unity Part:'''&lt;br /&gt;
&lt;br /&gt;
Open the “Quattro3D- Unity Project for bundle asset creation” folder using unity hub.&lt;br /&gt;
&lt;br /&gt;
To the assets folder, add we add a folder that will hold all the prefabs of the assetbundle.&lt;br /&gt;
&lt;br /&gt;
To the scene, add a Canvas (in the Hierarchy, right click -&amp;gt; UI -&amp;gt; Canvas). The Canvas will hold all the elements of our UI (buttons, text, scrollbar, images…).&lt;br /&gt;
&lt;br /&gt;
Select the Canvas and in the Inspector go to '''Canvas Scaler''' and select '''Scale With Screen''' for '''UI Scale Mode'''. This will allow the canvas Canvas to expand to full screen on all screens.&lt;br /&gt;
&lt;br /&gt;
Now to build the UI you see above (devtools). Start by adding Text elements (right click on Canvas -&amp;gt; UI -&amp;gt; Text).&lt;br /&gt;
&lt;br /&gt;
For each element, change the name and the text according to its function, change the color to white, add a button component and add a animation component. In the '''Rect Transform''' component, in the Anchor Presets, hold Alt and select top left to position your element.&lt;br /&gt;
&lt;br /&gt;
Add all the Text elements and position them (Inspector, Bundle Explorer, Console, Camera, Rendering).&lt;br /&gt;
&lt;br /&gt;
Now, to add the back button. Add an Image element to the UI, change its name to “back”, and in the image component add the source of the image (drop down in our case). Rotate it -90 deg on the Z axis for it to face left. Add a button component to turn it to a back button that closes the devtools.&lt;br /&gt;
&lt;br /&gt;
For the grey background you see, add and image just like before, change its color to black and change the A field in RGBA to 48 to make it transparent. Add an '''Outline''' component and change the '''Effect Color''' to white to add an outline to the image.&lt;br /&gt;
[[File:Unity UI.png|none|thumb|1006x1006px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now that we’ve added all our elements to the Canvas, it’s time to create our animations.&lt;br /&gt;
&lt;br /&gt;
To create an animation, in the top menu (next to Files, Edit, Assets…) go to Window -&amp;gt; Animation -&amp;gt; Animation.&lt;br /&gt;
&lt;br /&gt;
The animation tab should open in the bottom. Select the component you want to create an animation for and create and name the animation.&lt;br /&gt;
&lt;br /&gt;
We will be doing the sliding background image example for the animation. &lt;br /&gt;
&lt;br /&gt;
To record the animation, press on the record button. We want the image to slide in. So put the cursor on time 0s, and change the Pos X to -65 (outside of the screen) then move the cursor to 4s and change the Pos X back to 65. Press the record button again to save the recording. &lt;br /&gt;
[[File:Unity UI anim.png|none|thumb|1032x1032px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can press play to view your animation in action. To add the animation to the element; simply add an animation component and add the source of the animation you just created.&lt;br /&gt;
&lt;br /&gt;
Same thing goes for all the other animations.&lt;br /&gt;
&lt;br /&gt;
'''Graal Script Part:'''&lt;br /&gt;
&lt;br /&gt;
Now that we’ve created our prefabs and added the animations, our canvas is ready to be uploaded on the server and scripted. Save the AssetBundle and upload it to the server ([[Uploading and Loading AssetBundles]] for more info).&lt;br /&gt;
  findplayer(&amp;quot;Graal5918039&amp;quot;).addweapon(this.name);&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 &lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;dev&amp;quot;) toggle();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function toggle() {&lt;br /&gt;
   (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;devtoolsui&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onAssetBundleDownloaded(bundlename) {&lt;br /&gt;
   if (bundlename == &amp;quot;devtoolsui&amp;quot;) {&lt;br /&gt;
     this.keepAlive = true;;&lt;br /&gt;
     this.btns = {&amp;quot;inscpector&amp;quot;, &amp;quot;bundleexpl&amp;quot;, &amp;quot;console&amp;quot;, &amp;quot;camera&amp;quot;, &amp;quot;rendering&amp;quot;, &amp;quot;back&amp;quot;};&lt;br /&gt;
     this.devuiprefab = GameObject::fromassetbundle(&amp;quot;devtoolsui&amp;quot;, &amp;quot;assets/menuui/canvasdevtools.prefab&amp;quot;);&lt;br /&gt;
     this.devui = Object::Instantiate(Type::GameObject, this.devuiprefab);&lt;br /&gt;
 &lt;br /&gt;
     for (btnb: this.btns) {&lt;br /&gt;
       temp.btn = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, btn);&lt;br /&gt;
       Quattro::EventManager::AddEventHandlerTo(temp.btn.gameobject.GetComponent(Type::UI::Button));&lt;br /&gt;
       this.catcheventobject(temp.btn.gameobject, &amp;quot;onClick&amp;quot;, &amp;quot;onDevToolClick&amp;quot;);&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     Object::Destroy(this.devui, 4);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function onDevToolClick(go) {&lt;br /&gt;
   if (go.name == &amp;quot;inscpector&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;bundleexpl&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;console&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;camera&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;rendering&amp;quot;) player.chat = go.name;&lt;br /&gt;
   &lt;br /&gt;
   if (go.name == &amp;quot;back&amp;quot;) close();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function close() {&lt;br /&gt;
   for (btn : this.btns) {&lt;br /&gt;
     temp.btn = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, btn);&lt;br /&gt;
     Object::Destroy(temp.btn.gameobject);&lt;br /&gt;
   } &lt;br /&gt;
   &lt;br /&gt;
   temp.img = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, &amp;quot;Image&amp;quot;);&lt;br /&gt;
   temp.anim = temp.img.gameobject.GetComponent(Type::Animation);&lt;br /&gt;
   temp.anim.play(&amp;quot;devtools2&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
We load the assetbundle the usual way: &lt;br /&gt;
 (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;devtoolsui&amp;quot;);&lt;br /&gt;
 function onAssetBundleDownloaded(bundlename) {&lt;br /&gt;
   if (bundlename == &amp;quot;devtoolsui&amp;quot;) {&lt;br /&gt;
'''''this.keepAlive = true;''''' is necessary for the weapon to keep checking for button clicks.&lt;br /&gt;
&lt;br /&gt;
We create and instantiate the canvas prefab.&lt;br /&gt;
 this.devuiprefab = GameObject::fromassetbundle(&amp;quot;devtoolsui&amp;quot;, &amp;quot;assets/menuui/canvasdevtools.prefab&amp;quot;);&lt;br /&gt;
 this.devui = Object::Instantiate(Type::GameObject, this.devuiprefab);&lt;br /&gt;
this will display the canvas on the client screen.&lt;br /&gt;
&lt;br /&gt;
To detect button clicks;&lt;br /&gt;
 temp.btn = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, btn);&lt;br /&gt;
 Quattro::EventManager::AddEventHandlerTo(temp.btn.gameobject.GetComponent(Type::UI::Button));&lt;br /&gt;
 this.catcheventobject(temp.btn.gameobject, &amp;quot;onClick&amp;quot;, &amp;quot;onDevToolClick&amp;quot;);&lt;br /&gt;
we first find the button GameObject by name ('''this.devui.transform''' being the transform component of the canvas, and '''btn''' is the button name we want to find).&lt;br /&gt;
&lt;br /&gt;
Next, we add an EventManager to the button component of the GameObject we just found ('''temp.btn.gameobject.GetComponent(Type::UI::Button)''').&lt;br /&gt;
&lt;br /&gt;
And '''this.catcheventobject(temp.btn.gameobject, &amp;quot;onClick&amp;quot;, &amp;quot;onDevToolClick&amp;quot;)''' to catch all the onClick events.&lt;br /&gt;
&lt;br /&gt;
Finally, we implement '''public function onDevToolClick(go)''' to add functionalities after button is pressed (with '''go''' the GameObject being pressed).&lt;br /&gt;
&lt;br /&gt;
For animations, to add or play an animation, you will need to get the animation component of the GameObject first. (using: '''temp.img.gameobject.GetComponent(Type::Animation)''')&lt;br /&gt;
 temp.img = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, &amp;quot;Image&amp;quot;);&lt;br /&gt;
 temp.anim = temp.img.gameobject.GetComponent(Type::Animation);&lt;br /&gt;
 temp.anim.play(&amp;quot;devtools2&amp;quot;);&lt;br /&gt;
(more script functionalities for animations available here: https://docs.unity3d.com/ScriptReference/Animation.html).&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Category:Creation&amp;diff=20939</id>
		<title>Category:Creation</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Category:Creation&amp;diff=20939"/>
		<updated>2021-10-15T07:06:06Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Table_Of_Contents]]&lt;br /&gt;
{{template:Creation}}&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Creation&amp;diff=20938</id>
		<title>Creation</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Creation&amp;diff=20938"/>
		<updated>2021-10-15T07:05:52Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Creation]]&lt;br /&gt;
{{template:Creation}}&lt;br /&gt;
Graal3D&lt;br /&gt;
&lt;br /&gt;
* [[Graal3D Scripting Manual]]&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Plane_MiniGame&amp;diff=20937</id>
		<title>Plane MiniGame</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Plane_MiniGame&amp;diff=20937"/>
		<updated>2021-10-12T12:20:46Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This minigame is similar to the Car driving minigame. However, we move a plane through obstacles.&lt;br /&gt;
&lt;br /&gt;
'''AssetBundles:''' ''minigameplane - env''&lt;br /&gt;
&lt;br /&gt;
using the bundle explorer (F10):&lt;br /&gt;
&lt;br /&gt;
'''minigameplane:'''&lt;br /&gt;
&lt;br /&gt;
[[File:Plane.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
[[File:Obstacles.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
'''env:'''&lt;br /&gt;
&lt;br /&gt;
[[File:Environment.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
Weapon: '''''3D/Samples/Planeminigame'''''&lt;br /&gt;
 findplayer(&amp;quot;GraalID&amp;quot;).addweapon(this.name);&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 &lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   this.keepAlive = true;//SetTimer(9999);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;plane&amp;quot;) start();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function start() {&lt;br /&gt;
   WARPMANAGER.Warp(19, 14 ,0.7 ,&amp;quot;only_ground.nw&amp;quot;);&lt;br /&gt;
   new GuiWindowCtrl(&amp;quot;PlaneMinigame&amp;quot;) {&lt;br /&gt;
     profile = GuiBlueWindowProfile;&lt;br /&gt;
     x = 120;&lt;br /&gt;
     y = 0;&lt;br /&gt;
     width = 670;&lt;br /&gt;
     height = 340;&lt;br /&gt;
     text = &amp;quot;Plane Minigame&amp;quot;;&lt;br /&gt;
     &lt;br /&gt;
     new GuiButtonCtrl(&amp;quot;Plane&amp;quot;) {&lt;br /&gt;
       profile = GuiBlueButtonProfile;&lt;br /&gt;
       x = 150;&lt;br /&gt;
       y = 90;&lt;br /&gt;
       width = 150;&lt;br /&gt;
       height = 30;&lt;br /&gt;
       text = &amp;quot;Spawnplane&amp;quot;;&lt;br /&gt;
     }&lt;br /&gt;
       new GuiButtonCtrl(&amp;quot;Exit&amp;quot;) {&lt;br /&gt;
       profile = GuiBlueButtonProfile;&lt;br /&gt;
       x = 150;&lt;br /&gt;
       y = 120;&lt;br /&gt;
       width = 150;&lt;br /&gt;
       height = 30;&lt;br /&gt;
       text = &amp;quot;Exit&amp;quot;;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function Plane.onAction() {&lt;br /&gt;
   exit();&lt;br /&gt;
   PLAYERMOVEMENT.Freeze();&lt;br /&gt;
   //Quattro3D::PlayerCamera::Instance.FreeCam = true;&lt;br /&gt;
   CAMERAMANGER.freecam = true;&lt;br /&gt;
   this.empty = GameObject::Create(&amp;quot;empty&amp;quot;);&lt;br /&gt;
   Quattro3D::PlayerCamera::Instance.transform.rotation = Quaternion::euler(0, -90, 0);&lt;br /&gt;
   (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;minigameplane&amp;quot;);&lt;br /&gt;
   (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;env&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onAssetBundleDownloaded(bundlename) {&lt;br /&gt;
   if (bundlename == &amp;quot;minigameplane&amp;quot;) {&lt;br /&gt;
     this.planeprefab = GameObject::fromassetbundle(&amp;quot;minigameplane&amp;quot;, &amp;quot;assets/drivingplane/vehicles/planes/small_plane02.prefab&amp;quot;);&lt;br /&gt;
     this.plane = Object::Instantiate(Type::GameObject, this.planeprefab);&lt;br /&gt;
     this.plane.transform.position = v3(player.x, player.z, player.y);&lt;br /&gt;
     this.plane.transform.localscale = v3(0.3, 0.3, 0.3);&lt;br /&gt;
     this.plane.transform.parent = this.empty.transform;&lt;br /&gt;
     &lt;br /&gt;
     this.RB = this.plane.AddComponent(Type::RigidBody);&lt;br /&gt;
     this.RB.useGravity = false;&lt;br /&gt;
     &lt;br /&gt;
     boxCollider = this.plane.AddComponent(Type::BoxCollider);&lt;br /&gt;
     boxCollider.size = v3(4,4,4);&lt;br /&gt;
 &lt;br /&gt;
     Quattro::EventManager::AddOnCollisionHandlerTo(this.plane, this.plane.layer);&lt;br /&gt;
     this.catcheventobject(this.plane, &amp;quot;onCollisionEnter&amp;quot;, &amp;quot;onPlaneCollisionEnter&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     this.obstacleprefab = GameObject::fromassetbundle(&amp;quot;minigameplane&amp;quot;, &amp;quot;assets/drivingplane/vehicles/planes/obstacles 1.prefab&amp;quot;);&lt;br /&gt;
     this.obstacle = Object::Instantiate(Type::GameObject, this.obstacleprefab);&lt;br /&gt;
     this.obstacle.transform.position = v3(player.x, player.z + 10, player.y + 20);&lt;br /&gt;
     this.obstacle.transform.localscale = v3(0.3, 0.3, 0.3);&lt;br /&gt;
     this.obstacle.transform.parent = this.empty.transform;&lt;br /&gt;
   }&lt;br /&gt;
   if (bundlename == &amp;quot;env&amp;quot;) {&lt;br /&gt;
     this.envprefab = GameObject::fromassetbundle(&amp;quot;env&amp;quot;, &amp;quot;assets/jimmyenv2/environment.prefab&amp;quot;);&lt;br /&gt;
     this.env = Object::Instantiate(Type::GameObject, this.envprefab);&lt;br /&gt;
     this.env.transform.position = v3(player.x, player.z + 1.5, player.y);&lt;br /&gt;
     this.env.transform.parent = this.empty.transform; &lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onUpdate() {&lt;br /&gt;
   temp.campos = this.plane.transform.position.Add(v3(20,0,0));&lt;br /&gt;
   Quattro3D::PlayerCamera::Instance.transform.position = temp.campos;&lt;br /&gt;
   &lt;br /&gt;
   this.verticalInput = Input::GetAxis(&amp;quot;Vertical&amp;quot;);&lt;br /&gt;
   this.horizontalInput = Input::GetAxis(&amp;quot;Horizontal&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
   this.plane.transform.translate(Vector3::forward.Mult(Time::deltaTime * 5));&lt;br /&gt;
 &lt;br /&gt;
   this.plane.transform.rotate(Vector3::Right.Mult(700 * Time::deltaTime * this.verticalInput));&lt;br /&gt;
 &lt;br /&gt;
   this.plane.transform.rotate(Vector3::Forward.Mult(700 * Time::deltaTime * this.horizontalInput * -1));&lt;br /&gt;
 &lt;br /&gt;
   this.propellor = this.plane.transform.Find(&amp;quot;Propellor&amp;quot;);&lt;br /&gt;
   this.propellor.transform.rotate(Vector3::Forward.Mult(1700 * Time::deltaTime)); &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function onPlaneCollisionEnter(gameobject, collision) {&lt;br /&gt;
   player.chat = &amp;quot;BOOM YOU LOST!&amp;quot;;&lt;br /&gt;
   exit();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function Exit.onAction() {&lt;br /&gt;
   exit(); &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function exit() {&lt;br /&gt;
   findweapon(&amp;quot;3D/Dev/ToolBar/Camera&amp;quot;).cam1();&lt;br /&gt;
   PLAYERMOVEMENT.unfreeze();&lt;br /&gt;
   Object::Destroy(this.empty);&lt;br /&gt;
   Input::ResetInputAxes();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The function '''''start()''''' creates a UI with two buttons (Spawn Plane and Exit) allowing us to start and end the game.&lt;br /&gt;
&lt;br /&gt;
'''Plane.onAction()''' ''(when the Spawn button is pressed) :'' &lt;br /&gt;
&lt;br /&gt;
Calls the '''''exit()''''' function first to destroy GameObjects instantiated before, freezes the player using '''PLAYERMOVEMENT.Freeze();''' ,frees the camera with '''Quattro3D::PlayerCamera::Instance.FreeCam = true;''' and loads all the assets we'll need to use.&lt;br /&gt;
&lt;br /&gt;
In function '''''onAssetBundleDownloaded(bundlename)''''' we catch all the loaded assetbundles, we instantiate the plane, obstacles and environment. And we position them, modify their scales, add components to them and make them a child of an empty GameObject.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.empty = GameObject::Create(&amp;quot;empty&amp;quot;);&lt;br /&gt;
|}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.obstacle.transform.parent = this.empty.transform;&lt;br /&gt;
|}&lt;br /&gt;
This will help delete all the GameObjects upon deleting the empty GameObject. ('''Object::Destroy(this.empty);''')&lt;br /&gt;
&lt;br /&gt;
Now, the '''''onUpdate()''''' function checks for updates on every frame. '''''SetTimer(9999)''''' needs to be added for it to work.&lt;br /&gt;
&lt;br /&gt;
This function will be responsible for moving the plane, moving the camera following the plane and turning the propeller of the plane.&lt;br /&gt;
&lt;br /&gt;
First for the Camera, we want it to be looking side ways at the plane. We take the plane's position and add to the X axis:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!temp.campos = this.plane.transform.position.Add(v3(20,0,0));&lt;br /&gt;
|}&lt;br /&gt;
then we change the camera position to '''''temp.campos;'''''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Quattro3D::PlayerCamera::Instance.transform.position = temp.campos;&lt;br /&gt;
|}&lt;br /&gt;
We'll also need to change the rotation of the camera since it's initially facing forward and we want it to face the plane;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Quattro3D::PlayerCamera::Instance.transform.rotation = Quaternion::euler(0, -90, 0);&lt;br /&gt;
|}&lt;br /&gt;
Now, for the movement of the plane. It will be moving forward at a constant speed; '''''this.plane.transform.translate(Vector3::forward.Mult(Time::deltaTime * 5));'''''&lt;br /&gt;
&lt;br /&gt;
And the '''''Input::GetAxis()''''' will help us move it up/down and sideways.&lt;br /&gt;
&lt;br /&gt;
We also find the propellor of the plane and move it at a constant rotation speed;&lt;br /&gt;
&lt;br /&gt;
'''''this.propellor = this.plane.transform.Find(&amp;quot;Propellor&amp;quot;);'''''&lt;br /&gt;
&lt;br /&gt;
'''''this.propellor.transform.rotate(Vector3::Forward.Mult(1700 * Time::deltaTime));''''' &lt;br /&gt;
&lt;br /&gt;
Finally, the function '''''exit()''''' switches back to the default camera: '''''findweapon(&amp;quot;3D/Dev/ToolBar/Camera&amp;quot;).cam1();'''''&lt;br /&gt;
&lt;br /&gt;
unfreezes the Player, destroys the GameObjects and resets the Input Axes using: '''''Input::ResetInputAxes();'''''&lt;br /&gt;
[[File:Planeminigame gameplay.png|center|thumb|1108x1108px]]You can also add collision detection to the plane to turn it into an actual game.&lt;br /&gt;
 Quattro::EventManager::AddOnCollisionHandlerTo(this.plane, this.plane.layer);&lt;br /&gt;
 this.catcheventobject(this.plane, &amp;quot;onCollisionEnter&amp;quot;, &amp;quot;onPlaneCollisionEnter&amp;quot;);&lt;br /&gt;
and implement the function:&lt;br /&gt;
 public function onPlaneCollisionEnter(gameobject, collision) {&lt;br /&gt;
   player.chat = &amp;quot;BOOM YOU LOST!&amp;quot;;&lt;br /&gt;
   exit();&lt;br /&gt;
 }&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Driving_MiniGame&amp;diff=20936</id>
		<title>Driving MiniGame</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Driving_MiniGame&amp;diff=20936"/>
		<updated>2021-10-12T12:19:40Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the Driving MiniGame tutorial.&lt;br /&gt;
&lt;br /&gt;
= Intro =&lt;br /&gt;
&lt;br /&gt;
==== DrivingMiniGame ====&lt;br /&gt;
This is a simple and easy car driving example. In the assetbundle, there's an environment that we load and instantiate and multiple cars that we can spawn. This game is not focused on the actual driving experience itself, but more on introducing new Unity functionalities.&lt;br /&gt;
&lt;br /&gt;
'''Asset Bundles: ''minigame2, env'''''&lt;br /&gt;
&lt;br /&gt;
using the bundle explorer (F10):&lt;br /&gt;
&lt;br /&gt;
'''minigame2:'''&lt;br /&gt;
&lt;br /&gt;
[[File:Minigame2.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
'''env:'''&lt;br /&gt;
&lt;br /&gt;
[[File:Minigame2 env.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
Weapon: '''''3D/Samples/Drivingminigame'''''&lt;br /&gt;
 findplayer(&amp;quot;GraalID&amp;quot;).addweapon(this.name);&lt;br /&gt;
 this.join(&amp;quot;3d_merlin_camera&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;dest&amp;quot;) dest();&lt;br /&gt;
   if (player.chat == &amp;quot;drive&amp;quot;) drive();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function drive() {&lt;br /&gt;
   destLevelName = &amp;quot;only_ground.nw&amp;quot;;&lt;br /&gt;
   x = 19;&lt;br /&gt;
   y = 10;&lt;br /&gt;
   z = 0.7;//0.7;&lt;br /&gt;
   WARPMANAGER.Warp(x, y ,z ,destLevelName);&lt;br /&gt;
 &lt;br /&gt;
   sleep(1);&lt;br /&gt;
  &lt;br /&gt;
   new GuiWindowCtrl(&amp;quot;MyGUI_Minigame_Window1&amp;quot;) {&lt;br /&gt;
     profile = GuiBlueWindowProfile;&lt;br /&gt;
     style = $pref::Video::defaultguistyle;&lt;br /&gt;
     clientrelative = true;&lt;br /&gt;
     clientextent = &amp;quot;320,240&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
     canmove = true;&lt;br /&gt;
     canresize = true;&lt;br /&gt;
     closequery = false;&lt;br /&gt;
     destroyonhide = false;&lt;br /&gt;
     text = &amp;quot;Window 1&amp;quot;;&lt;br /&gt;
     x = 490;&lt;br /&gt;
     y = 242;&lt;br /&gt;
 &lt;br /&gt;
     new GuiButtonCtrl(&amp;quot;MyGUI_Minigame_Button1&amp;quot;) {&lt;br /&gt;
       profile = GuiBlueButtonProfile;&lt;br /&gt;
       text = &amp;quot;Car&amp;quot;;&lt;br /&gt;
       width = 80;&lt;br /&gt;
       x = 77;&lt;br /&gt;
       y = 31;&lt;br /&gt;
     }&lt;br /&gt;
     new GuiButtonCtrl(&amp;quot;MyGUI_Minigame_Button2&amp;quot;) {&lt;br /&gt;
       profile = GuiBlueButtonProfile;&lt;br /&gt;
       height = 31;&lt;br /&gt;
       text = &amp;quot;Bus&amp;quot;;&lt;br /&gt;
       width = 80;&lt;br /&gt;
       x = 77;&lt;br /&gt;
       y = 69;&lt;br /&gt;
     }&lt;br /&gt;
     new GuiButtonCtrl(&amp;quot;MyGUI_Minigame_Button3&amp;quot;) {&lt;br /&gt;
       profile = GuiBlueButtonProfile;&lt;br /&gt;
       height = 31;&lt;br /&gt;
       text = &amp;quot;Quit&amp;quot;;&lt;br /&gt;
       width = 80;&lt;br /&gt;
       x = 78;&lt;br /&gt;
       y = 109;&lt;br /&gt;
     }&lt;br /&gt;
     new GuiTextCtrl(&amp;quot;MyGUI_Minigame_Text1&amp;quot;) {&lt;br /&gt;
       profile = GuiBlueTextProfile;&lt;br /&gt;
       height = 20;&lt;br /&gt;
       text = &amp;quot;Select Type:&amp;quot;;&lt;br /&gt;
       width = 71;&lt;br /&gt;
       x = 11;&lt;br /&gt;
       y = 5;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function MyGUI_Minigame_Button1.onAction() {&lt;br /&gt;
   // Button &amp;quot;Car&amp;quot; has been pressed&lt;br /&gt;
   (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;minigame2&amp;quot;);&lt;br /&gt;
   (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;env&amp;quot;);&lt;br /&gt;
   this.vehicle = &amp;quot;car&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function MyGUI_Minigame_Button2.onAction() {&lt;br /&gt;
   // Button &amp;quot;Bus&amp;quot; has been pressed&lt;br /&gt;
   (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;minigame2&amp;quot;);&lt;br /&gt;
   (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;env&amp;quot;);&lt;br /&gt;
   this.vehicle = &amp;quot;bus&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function MyGUI_Minigame_Button3.onAction() {&lt;br /&gt;
   dest();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onAssetBundleDownloaded(bundlename) {&lt;br /&gt;
   if (bundlename == &amp;quot;env&amp;quot;) {&lt;br /&gt;
     this.env = GameObject::fromassetbundle(&amp;quot;env&amp;quot;, &amp;quot;assets/jimmyenv2/Environment.prefab&amp;quot;);&lt;br /&gt;
     this.env = Object::Instantiate(Type::GameObject, this.env);&lt;br /&gt;
     this.env.transform.position = v3(player.x, player.z, player.y);&lt;br /&gt;
   }&lt;br /&gt;
   if (bundlename == &amp;quot;minigame2&amp;quot;) {&lt;br /&gt;
     if (this.vehicle == &amp;quot;bus&amp;quot;) {&lt;br /&gt;
       dest();&lt;br /&gt;
       this.vh = GameObject::fromassetbundle(&amp;quot;minigame2&amp;quot;, &amp;quot;assets/jimmyminigame2/Veh_Bus_Blue_Z.prefab&amp;quot;);&lt;br /&gt;
     }&lt;br /&gt;
     &lt;br /&gt;
     if (this.vehicle == &amp;quot;car&amp;quot;) {&lt;br /&gt;
       dest();&lt;br /&gt;
       this.vh = GameObject::fromassetbundle(&amp;quot;minigame2&amp;quot;, &amp;quot;assets/jimmyminigame2/Veh_Car_Blue_Z.prefab&amp;quot;);&lt;br /&gt;
     }&lt;br /&gt;
     &lt;br /&gt;
     this.vh = Object::Instantiate(Type::GameObject, this.vh);&lt;br /&gt;
     this.vh.transform.position = v3(player.x - 2, player.z, player.y - 5);&lt;br /&gt;
     this.vh.AddComponent(Type::RigidBody);&lt;br /&gt;
 &lt;br /&gt;
     PLAYERMOVEMENT.Freeze();&lt;br /&gt;
     //Quattro3D::PlayerCamera::Instance.FreeCam = true;&lt;br /&gt;
     CAMERAMANAGER.freecam = true;&lt;br /&gt;
     handleMovement();&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function handleMovement() {&lt;br /&gt;
   this.on = true;&lt;br /&gt;
   SetTimer(0.05);&lt;br /&gt;
   this.speed = 20;&lt;br /&gt;
   this.rotation = 400;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onFixedUpdate() {&lt;br /&gt;
   this.vInput = Input::GetAxis(&amp;quot;Vertical&amp;quot;);&lt;br /&gt;
   this.vh.transform.Translate(Vector3::forward.Mult(Time::deltaTime * this.speed * this.vInput));&lt;br /&gt;
     &lt;br /&gt;
   this.hInput = Input::GetAxis(&amp;quot;Horizontal&amp;quot;);&lt;br /&gt;
   this.vh.transform.Rotate(Vector3::up.Mult(Time::deltaTime * this.rotation * this.hInput * this.vInput));&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onTimeOut() {&lt;br /&gt;
   if(this.on) {&lt;br /&gt;
     temp.campos = this.vh.transform.position.Add(v3(0,10,-7));&lt;br /&gt;
     Quattro3D::PlayerCamera::Instance.transform.position = temp.campos;&lt;br /&gt;
     &lt;br /&gt;
     //this.vInput = Input::GetAxis(&amp;quot;Vertical&amp;quot;);&lt;br /&gt;
     &lt;br /&gt;
     //this.hInput = Input::GetAxis(&amp;quot;Horizontal&amp;quot;);&lt;br /&gt;
     //if (this.vInput &amp;lt; 0) this.hInput = - Input::GetAxis(&amp;quot;Horizontal&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     //this.vh.transform.Translate(Vector3::forward.Mult(Time::deltaTime * this.speed * this.vInput));&lt;br /&gt;
     &lt;br /&gt;
     SetTimer(0.05);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function dest() {&lt;br /&gt;
   this.on = false;&lt;br /&gt;
   findweapon(&amp;quot;3D/Dev/ToolBar/Camera&amp;quot;).cam1();&lt;br /&gt;
   PLAYERMOVEMENT.unfreeze();&lt;br /&gt;
   Object::Destroy(this.vh);&lt;br /&gt;
   Object::Destroy(this.env);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Here we create a UI for the player to choose what vehicle to choose, and we load and instantiate the prefab based on the choice.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Camera&amp;lt;/u&amp;gt; ====&lt;br /&gt;
The Camera is the point of view. Here we want the Camera to follow the car while driving and not the player.&lt;br /&gt;
&lt;br /&gt;
In '''''function onAssetBundleDownloaded(bundlename)''''' We use:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Quattro3D::PlayerCamera::Instance.FreeCam = true;&lt;br /&gt;
|}&lt;br /&gt;
To free the camera. This will free it from following the player GameObject.&lt;br /&gt;
&lt;br /&gt;
Then in '''''function onTimeOut()''''' we want the camera position to be updated with the vehicle's position.&lt;br /&gt;
&lt;br /&gt;
'''''temp.campos''''' is the variable we store the camera's position in. We want it to be behind and above the vehicle for a good view. This is why we get the vehicle's position and add a Vector3 to it:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!temp.campos = this.vh.transform.position.Add(v3(0,10,-7));&lt;br /&gt;
|}&lt;br /&gt;
now:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Quattro3D::PlayerCamera::Instance.transform.position&lt;br /&gt;
|}&lt;br /&gt;
allows us to the get the Camera GameObject and to access its transform component and change its position.&lt;br /&gt;
&lt;br /&gt;
We have implemented default cameras found in Weapon: '''''3D/Dev/ToolBar/Camera'''''&lt;br /&gt;
&lt;br /&gt;
We access them through the Weapon &amp;quot;'''''3D/Dev/ToolBar/Camera'''''&amp;quot; using:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!''findweapon(&amp;quot;3D/Dev/ToolBar/Camera&amp;quot;).cam1();''&lt;br /&gt;
|}and we call the function '''''cam1();''''' in '''''function dest()''''' to go back to the default cam.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Unity Input&amp;lt;/u&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Input::GetAxis(&amp;quot;Vertical&amp;quot;);&lt;br /&gt;
|}&lt;br /&gt;
&amp;quot;Vertical&amp;quot; / &amp;quot;Horizontal&amp;quot;&lt;br /&gt;
&lt;br /&gt;
It checks the arrows pressed and gives a value in the range of (-1 to 1) -1 indicating &amp;quot;down&amp;quot;, 1 &amp;quot;up&amp;quot; and 0 &amp;quot;neutral&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
We use it here to translate and rotate the vehicle.&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Turret_MiniGame&amp;diff=20935</id>
		<title>Turret MiniGame</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Turret_MiniGame&amp;diff=20935"/>
		<updated>2021-10-12T12:17:29Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the Turret Minigame!&lt;br /&gt;
&lt;br /&gt;
In this Tutorial, we will build a turret that rotates and shoots targets around it. The Assets are available on the server. &lt;br /&gt;
&lt;br /&gt;
==== TurretMiniGame GameObjects ====&lt;br /&gt;
All the prefabs are under the asset bundle: '''minigame''' (you can view them in the bundle explorer &amp;quot;F10&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Turret that shoots the projectiles:&lt;br /&gt;
&lt;br /&gt;
[[File:Turret.png|frameless|407x407px]]&lt;br /&gt;
&lt;br /&gt;
Robot that will serve as a target:&lt;br /&gt;
&lt;br /&gt;
[[File:Robot Obstacle Minigame.png|frameless|407x407px]]&lt;br /&gt;
&lt;br /&gt;
Cubes Instantiated in different position also for targets:&lt;br /&gt;
&lt;br /&gt;
[[File:Turret Minigame targets.png|frameless|405x405px]]&lt;br /&gt;
&lt;br /&gt;
 findplayer(&amp;quot;GraalID&amp;quot;).addweapon(this.name);&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;start&amp;quot;) {&lt;br /&gt;
     destroy();&lt;br /&gt;
     start();&lt;br /&gt;
   }&lt;br /&gt;
   if (player.chat == &amp;quot;dest&amp;quot;) destroy();&lt;br /&gt;
 }&lt;br /&gt;
The way I start the minigame is '''onPlayerChats'''; when the player says &amp;quot;start&amp;quot;. We'll also see how to '''destroy the GameObjects''' when the player says &amp;quot;dest&amp;quot;.&lt;br /&gt;
 function start() {&lt;br /&gt;
   this.start = true;&lt;br /&gt;
   //PLAYERMOVEMENT.Freeze();&lt;br /&gt;
   &lt;br /&gt;
   //for turret control&lt;br /&gt;
   this.rotateangle = 0; //Rotation angle of the turret&lt;br /&gt;
   this.rotateangleB = 270; //Rotation angle of the barrel&lt;br /&gt;
   this.speed = 15;&lt;br /&gt;
   &lt;br /&gt;
   this.currentX = player.x;&lt;br /&gt;
   this.currentY = player.y;&lt;br /&gt;
   this.currentZ = player.z;&lt;br /&gt;
   echo (&amp;quot;TurretMiniGame warp from=&amp;quot; @ this.currentLevel @ &amp;quot; x=&amp;quot; @ this.currentX @ &amp;quot; y=&amp;quot; @ this.currentY @ &amp;quot; z=&amp;quot; @ this.currentZ);&lt;br /&gt;
   WARPMANAGER.Warp(19, 14 ,0.7 ,&amp;quot;only_ground.nw&amp;quot;);&lt;br /&gt;
   sleep(1.5);&lt;br /&gt;
 &lt;br /&gt;
   (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;minigame&amp;quot;); //loading the assetbundle&lt;br /&gt;
 }&lt;br /&gt;
'''''this.start = true;''''' will be used to indicate that the game has started.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Using PLAYERMOVEMENT and WARPMANAGER&amp;lt;/u&amp;gt; ====&lt;br /&gt;
'''PLAYERMOVEMENT.Freeze()''' is a method that freezes the player (weapon: '''3D/Player/Core/Movement)''' &lt;br /&gt;
&lt;br /&gt;
'''WARPMANAGER.Warp(x,y,z,level)''' (weapon: '''3D/Player/Core/Warp/Manager''')&lt;br /&gt;
&lt;br /&gt;
Having uploaded the Asset bundle called &amp;quot;'''minigame'''&amp;quot; that contains the prefabs to the server, I start off by loading them, creating the prefabs, instantiating them and giving them a position in the '''start function'''  ([[Uploading and Loading AssetBundles|&amp;lt;u&amp;gt;Uploading and Loading AssetBundles&amp;lt;/u&amp;gt;]] for info on how to upload assets).&lt;br /&gt;
 function onAssetBundleDownloaded(bundlename) {&lt;br /&gt;
   if (bundlename == &amp;quot;minigame&amp;quot;) { &lt;br /&gt;
     SetTimer(9999);&lt;br /&gt;
     this.empty = GameObject::Create(&amp;quot;empty&amp;quot;); // for parenting and deleting&lt;br /&gt;
 &lt;br /&gt;
     this.turret = GameObject::fromassetbundle(&amp;quot;minigame&amp;quot;, &amp;quot;assets/jimmyminigame/turret.prefab&amp;quot;);&lt;br /&gt;
     this.robot1 = GameObject::fromassetbundle(&amp;quot;minigame&amp;quot;, &amp;quot;assets/jimmyminigame/robot.prefab&amp;quot;);&lt;br /&gt;
     this.robot2 = GameObject::fromassetbundle(&amp;quot;minigame&amp;quot;, &amp;quot;assets/jimmyminigame/robot.prefab&amp;quot;);&lt;br /&gt;
     this.wreckedrobotprefab = GameObject::fromassetbundle(&amp;quot;minigame&amp;quot;, &amp;quot;assets/jimmyminigame/robot wrecked.prefab&amp;quot;);&lt;br /&gt;
     this.projectileprefab = GameObject::fromassetbundle(&amp;quot;minigame&amp;quot;, &amp;quot;assets/jimmyminigame/projectile.prefab&amp;quot;);&lt;br /&gt;
     this.explosion = GameObject::fromassetbundle(&amp;quot;minigame&amp;quot;, &amp;quot;assets/jimmyminigame/explosion.prefab&amp;quot;);&lt;br /&gt;
     &lt;br /&gt;
     this.turret = Object::Instantiate(Type::GameObject, this.turret);&lt;br /&gt;
     this.robot1 = Object::Instantiate(Type::GameObject, this.robot1);&lt;br /&gt;
     this.robot2 = Object::Instantiate(Type::GameObject, this.robot2);&lt;br /&gt;
     &lt;br /&gt;
     this.turret.transform.position = v3(player.x, player.z, player.y);&lt;br /&gt;
     this.robot1.transform.position = v3(player.x - 5, player.z - 1, player.y + 10);&lt;br /&gt;
     this.robot2.transform.position = v3(player.x + 5, player.z - 1, player.y + 10);&lt;br /&gt;
     &lt;br /&gt;
     this.turret.transform.localscale = v3(1,1,1);&lt;br /&gt;
     this.robot1.transform.localscale = v3(1,1,1);&lt;br /&gt;
     this.robot2.transform.localscale = v3(1,1,1);&lt;br /&gt;
     &lt;br /&gt;
     loadCubes();&lt;br /&gt;
     &lt;br /&gt;
     player.charactercontroller.enabled = false;&lt;br /&gt;
     player.gameobject.transform.position = v3(player.x, player.z+5, player.y);&lt;br /&gt;
 &lt;br /&gt;
     this.launcher = GameObject::Find(&amp;quot;Launcher&amp;quot;);&lt;br /&gt;
     this.barrel = GameObject::Find(&amp;quot;Barrel&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function loadCubes() {&lt;br /&gt;
   temp.width = 10;&lt;br /&gt;
   temp.height = 4;&lt;br /&gt;
 &lt;br /&gt;
   for (temp.y = 0; temp.y &amp;lt; temp.height; ++temp.y) {&lt;br /&gt;
     for (temp.x = 0; temp.x &amp;lt; temp.width; ++temp.x) {&lt;br /&gt;
       temp.block = GameObject::CreatePrimitive(PrimitiveType::Cube);&lt;br /&gt;
       temp.block.Name = &amp;quot;myblock&amp;quot;;&lt;br /&gt;
       temp.block.transform.parent = this.empty.transform; // for deleting&lt;br /&gt;
       temp.block.transform.position = v3(player.x - 5 + temp.x, player.z + temp.y, player.y + 15);&lt;br /&gt;
       temp.block.AddComponent(Type::RigidBody);&lt;br /&gt;
       temp.block.layer = this.projectile.layer; &lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   temp.nbofobjects = 20;&lt;br /&gt;
   temp.radius = 7f;&lt;br /&gt;
 &lt;br /&gt;
   for (temp.i = 0; temp.i &amp;lt; temp.nbofobjects; ++temp.i) {&lt;br /&gt;
     temp.angle = temp.i * Mathf::PI * 2 / temp.nbofobjects;&lt;br /&gt;
     temp.x1 = cos(temp.angle) * temp.radius;&lt;br /&gt;
     temp.y1 = sin(temp.angle) * temp.radius;&lt;br /&gt;
     this.cube = GameObject::CreatePrimitive(PrimitiveType::Cube);&lt;br /&gt;
     this.cube.transform.parent = this.empty.transform;&lt;br /&gt;
     this.cube.transform.position = v3(player.x + temp.x1, player.z, player.y + temp.y1);&lt;br /&gt;
     this.cube.AddComponent(Type::RigidBody);&lt;br /&gt;
     temp.angleDegrees = -temp.angle * Mathf::Rad2Deg;&lt;br /&gt;
     this.cube.transform.rotation = Quaternion::euler(0, temp.angleDegrees, 0); &lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
In the '''''loadCubes()''''' function we instantiate primitive type cubes and position them to build a wall and a circular formation around the turret.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Moving the Player GameObject&amp;lt;/u&amp;gt; ====&lt;br /&gt;
The player is a GameObject, and its accessed by:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!player.gameobject&lt;br /&gt;
|}&lt;br /&gt;
Before changing the player's transform, the '''''player.charactercontroller''''' must be disabled:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!player.charactercontroller.enabled = false;&lt;br /&gt;
|}&lt;br /&gt;
Then we can change the position accessing the transform component of the GameObject:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!player.gameobject.transform.position = Vector3::Create(player.x, player.z+5, player.y);&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Parenting&amp;lt;/u&amp;gt; ====&lt;br /&gt;
In Unity, parenting is when a GameObject becomes a parent of another GameObject. The child GameObject will perform all it's transform changes in respect to the parent GameObject and not the Camera. Additionally, deleting the parent GameObject will delete all its children.&lt;br /&gt;
&lt;br /&gt;
We use it for the latter. We create the '''Empty GameObject''', which will serve as a parent for the Cubes ''(children)'' in order to delete them all, since we don't have a reference to each and every cube.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Finding GameObjects by Name&amp;lt;/u&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!GameObject::Find(&amp;quot;name&amp;quot;)&lt;br /&gt;
|}&lt;br /&gt;
We use it to find the barrel that we'll move up and down and the launcher that shoots the projectiles.&lt;br /&gt;
&lt;br /&gt;
Now to move the Turret;&lt;br /&gt;
 function onKeyPressed(keycode) {&lt;br /&gt;
   if (keycode == &amp;quot;90&amp;quot;) { // Z&lt;br /&gt;
     this.rotateangle -= 4;&lt;br /&gt;
     this.turret.transform.rotation = Quaternion::euler(0, this.rotateangle, 0); &lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   if (keycode == &amp;quot;67&amp;quot;) { // C&lt;br /&gt;
     this.rotateangle += 4;&lt;br /&gt;
     this.turret.transform.rotation = Quaternion::euler(0, this.rotateangle, 0);&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   if (keycode == &amp;quot;87&amp;quot;) { // W&lt;br /&gt;
     this.rotateangleB = this.rotateangleB &amp;lt; 300? this.rotateangleB + 4: 300;&lt;br /&gt;
     this.barrel.transform.LocalRotation = Quaternion::euler(this.rotateangleB, 0, 0);&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   if (keycode == &amp;quot;83&amp;quot;) { // S&lt;br /&gt;
     this.rotateangleB = this.rotateangleB &amp;gt; 258? this.rotateangleB - 4: 258;&lt;br /&gt;
     this.barrel.transform.LocalRotation = Quaternion::euler(this.rotateangleB, 0, 0);&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   if (keycode == &amp;quot;32, ,57&amp;quot;) { // Space&lt;br /&gt;
     if (this.start) {&lt;br /&gt;
       shoot();&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
We rotate the barrel around the X axis for it to go up and down;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Quaternion::euler(this.rotateangleB, 0, 0);&lt;br /&gt;
|}&lt;br /&gt;
And rotate the turret around the Y axis (Vertical axis);&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Quaternion::euler(0, this.rotateangle, 0);&lt;br /&gt;
|}&lt;br /&gt;
this.rotateangle for both cases starts at the initial rotation of the GameObjects and is incremented/decremented based on the direction of the rotation.&lt;br /&gt;
&lt;br /&gt;
In the last conditional block, if space is pressed and if the Game is on ('''''this.start == true'''''), the projectile is shot. Here's how it's done;&lt;br /&gt;
 function shoot() {&lt;br /&gt;
     SetTimer(9999);&lt;br /&gt;
     this.projectile = Object::Instantiate(Type::GameObject, this.projectileprefab);&lt;br /&gt;
     this.projectile.transform.parent = this.empty.transform;&lt;br /&gt;
     this.projectile.transform.position = this.launcher.transform.position;&lt;br /&gt;
     this.projectile.transform.scale = v3(1,1,1);&lt;br /&gt;
 &lt;br /&gt;
     temp.rigidBody = this.projectile.GetComponent(Type::RigidBody); &lt;br /&gt;
     temp.rigidBody.velocity = this.launcher.transform.forward.Mult(this.speed);&lt;br /&gt;
 &lt;br /&gt;
     Quattro::EventManager::AddOnCollisionHandlerTo(this.projectile, this.projectile.layer);&lt;br /&gt;
     this.catcheventobject(this.projectile, &amp;quot;onCollisionEnter&amp;quot;, &amp;quot;onProjectileCollisionEnter&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
The projectile is initialized and positioned on the launcher.&lt;br /&gt;
&lt;br /&gt;
We'll need to use physics to shoot the projectile, this is why we get the RigidBody component of the GameObject;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!temp.rigidBody = this.projectile.GetComponent(Type::RigidBody);&lt;br /&gt;
|}&lt;br /&gt;
(if the GameObject doesn't have a RigidBody by default, you'll need to add it using:  '''''gameobject.AddComponent(Type::RigidBody);''''')&lt;br /&gt;
&lt;br /&gt;
We then add velocity (which is a vector that represents speed in a certain direction). The direction is the Launcher's forward direction, it is multiplied by the desired speed;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!temp.rigidBody.velocity = this.launcher.transform.forward.Mult(this.speed);&lt;br /&gt;
|}&lt;br /&gt;
Now to detect collision, we make sure we '''''SetTimer(9999)''''' for the script to stay up and looking for events, we add the Collision Handler to the projectile;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Quattro::EventManager::AddOnCollisionHandlerTo(this.projectile, this.projectile.layer);&lt;br /&gt;
|}&lt;br /&gt;
and we wait for collisions;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.catcheventobject(this.projectile, &amp;quot;onCollisionEnter&amp;quot;, &amp;quot;onProjectileCollisionEnter&amp;quot;);&lt;br /&gt;
|}&lt;br /&gt;
 public function onProjectileCollisionEnter(gameobject, collision) {&lt;br /&gt;
   temp.radius = 4;&lt;br /&gt;
   temp.force = 5;&lt;br /&gt;
   &lt;br /&gt;
   player.chat = &amp;quot;boom=&amp;quot; @ collision.Gameobject.name;&lt;br /&gt;
   echo (&amp;quot;collision.Gameobject.name=&amp;quot; @ collision.Gameobject.name);&lt;br /&gt;
   &lt;br /&gt;
   temp.explosion = Object::Instantiate(Type::GameObject, this.explosion);&lt;br /&gt;
   temp.explosion.transform.parent = this.empty.transform;&lt;br /&gt;
   temp.explosion.transform.position = collision.Gameobject.transform.position;&lt;br /&gt;
   temp.explosion.transform.scale = v3(1,1,1);&lt;br /&gt;
   &lt;br /&gt;
   temp.affected = Physics::OverlapSphere(temp.explosion.transform.position, 5);&lt;br /&gt;
   for (temp.col: temp.affected) {&lt;br /&gt;
     if (temp.col.GetComponent(Type::RigidBody)!= NULL) {&lt;br /&gt;
       temp.col.GetComponent(Type::RigidBody).AddExplosionForce(temp.force, temp.explosion.transform.position, temp.radius, temp.force * 0.5f, ForceMode::Impulse);&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   if (collision.Gameobject.name == &amp;quot;assets/jimmyminigame/robot.prefab(CLONE)&amp;quot;) {&lt;br /&gt;
     this.wreckedrobot = Object::Instantiate(Type::GameObject, this.wreckedrobotprefab);&lt;br /&gt;
     this.wreckedrobot.transform.parent = this.empty.transform;&lt;br /&gt;
     this.wreckedrobot.transform.position = collision.Gameobject.transform.position;;&lt;br /&gt;
     Object::Destroy(collision.Gameobject);&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   if (collision.Gameobject.name.starts(&amp;quot;assets/jimmyminigame/projectile.prefab&amp;quot;)) return;&lt;br /&gt;
   &lt;br /&gt;
   Object::Destroy(gameobject);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Adding Explosion Force&amp;lt;/u&amp;gt; ====&lt;br /&gt;
Upon Collision, we instantiate and place the explosion. To make it seem more realistic we add an explosion force. &lt;br /&gt;
&lt;br /&gt;
We first gather the Colliders around the area of explosion with a radius of 5;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!temp.affected = Physics::OverlapSphere(temp.explosion.transform.position, 5);&lt;br /&gt;
|}&lt;br /&gt;
this will return a list of colliders in the sphere area around the explosion.&lt;br /&gt;
&lt;br /&gt;
We then make sure they have a Rigid Body component and apply explosion force to them;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!temp.col.GetComponent(Type::RigidBody).AddExplosionForce(temp.force, temp.explosion.transform.position, temp.radius, temp.force * 0.5f, ForceMode::Impulse);&lt;br /&gt;
|}&lt;br /&gt;
In this conditional block we ignore the collision if it is between two projectiles;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!if (collision.Gameobject.name.starts(&amp;quot;assets/jimmyminigame/projectile.prefab&amp;quot;)) return;&lt;br /&gt;
|}&lt;br /&gt;
 function destroy() {&lt;br /&gt;
   this.start = false;&lt;br /&gt;
   echo(&amp;quot;destroy&amp;quot;); &lt;br /&gt;
   Object::Destroy(this.turret);&lt;br /&gt;
   Object::Destroy(this.launcher);&lt;br /&gt;
   Object::Destroy(this.robot1);&lt;br /&gt;
   Object::Destroy(this.robot2);&lt;br /&gt;
   Object::Destroy(this.empty);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New : Destroying GameObjects&amp;lt;/u&amp;gt; ====&lt;br /&gt;
Here when the player says &amp;quot;dest&amp;quot;; this function is called and&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Object::Destroy(gameobject);&lt;br /&gt;
|}&lt;br /&gt;
is used to destroy the GameObject.&lt;br /&gt;
&lt;br /&gt;
We can use this function with an added parameter that indicates the time in seconds to wait before destroying the GameObject;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Object::Destroy(gameobject, seconds);&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Placing_GameObjects_in_NPC&amp;diff=20934</id>
		<title>Placing GameObjects in NPC</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Placing_GameObjects_in_NPC&amp;diff=20934"/>
		<updated>2021-10-12T11:55:37Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Another way to make GameObjects visible to all the Players is by placing them in NPCs. &lt;br /&gt;
&lt;br /&gt;
However, placing many NPCs may be heavy on the server, so beware of that whenever you're doing so.&lt;br /&gt;
&lt;br /&gt;
Start off by creating the NPC the normal way:&lt;br /&gt;
&lt;br /&gt;
Create a Script file in classes. You load the assets the same it was done before in weapons; under '''//#CLIENTSIDE'''&lt;br /&gt;
[[File:3d samples documentation test.png|none|thumb|1040x1040px]]&lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;/destroy&amp;quot;) this.destroy();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 &lt;br /&gt;
 function onCreated() {&lt;br /&gt;
     (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;documentationexample&amp;quot;);&lt;br /&gt;
     this.prefab = GameObject::fromassetbundle(&amp;quot;documentationexample&amp;quot;, &amp;quot;assets/example/bomb.prefab&amp;quot;);&lt;br /&gt;
     this.bomb = Object::Instantiate(Type::GameObject, this.prefab);&lt;br /&gt;
     this.bomb.transform.parent = this.gameobject.transform;&lt;br /&gt;
     this.bomb.transform.localposition = v3(0,0.5,0);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;u&amp;gt;Class:&amp;lt;/u&amp;gt;''' ''3d_samples_documentation_test'' &lt;br /&gt;
&lt;br /&gt;
Everything is the same when it comes to loading and instantiating the prefabs. &lt;br /&gt;
&lt;br /&gt;
The only difference is for this line of code:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.projectile.transform.parent = this.gameobject.transform;&lt;br /&gt;
|}&lt;br /&gt;
Here, '''''this.gameobject''''' is the NPC GameObject. It is an empty GameObject we attach our prefabs to. We create the prefabs and make them children of this NPC GameObject.  &lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;u&amp;gt;Destroying the NPC:&amp;lt;/u&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
* '''''this.destroy''''' will destroy the NPC and all the children as well. (''done on'' ''ServerSide'') &lt;br /&gt;
* You could also destroy the NPC and its children using the Unity Binding function: '''''Object::Destroy(this.gameobject).''''' (''done on ClientSide'')  &lt;br /&gt;
&lt;br /&gt;
Now in your other script/weapon. To place the NPC in the scene, we use '''''putnpc2(x,y,&amp;quot;&amp;quot;)'''''; &lt;br /&gt;
&lt;br /&gt;
On ClientSide we trigger server in order to place the NPC containing the prefabs, and inform all the other clients of it, by implementing '''''onActionServerSide()'''''. &lt;br /&gt;
 findplayer(&amp;quot;Graal5918039&amp;quot;).addweapon(this.name);&lt;br /&gt;
 &lt;br /&gt;
 function onActionServerside(cmd,x,y) {&lt;br /&gt;
   if (cmd == &amp;quot;bomb&amp;quot;) {&lt;br /&gt;
     temp.bombernpc = putnpc2(x,y,&amp;quot;&amp;quot;);&lt;br /&gt;
     temp.bombernpc.join(&amp;quot;3d_samples_documentation_test&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 &lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   triggerserver(&amp;quot;gui&amp;quot;, this.name, &amp;quot;bomb&amp;quot;, player.x, player.y);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;u&amp;gt;'''Weapon:'''&amp;lt;/u&amp;gt; ''3D/Samples/Examples/DocumentationTest''&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=File:3d_samples_documentation_test.png&amp;diff=20933</id>
		<title>File:3d samples documentation test.png</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=File:3d_samples_documentation_test.png&amp;diff=20933"/>
		<updated>2021-10-12T11:54:08Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;placing GO in npcs&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Uploading_and_Loading_AssetBundles&amp;diff=20932</id>
		<title>Uploading and Loading AssetBundles</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Uploading_and_Loading_AssetBundles&amp;diff=20932"/>
		<updated>2021-10-12T11:49:45Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Up until now, we have been using PrimitiveTypes for our GameObjects.&lt;br /&gt;
&lt;br /&gt;
In this section, we will start using different GameObjects. I will go over how to upload your assetbundles containing all your customized prefabs to the server. How to load, instantiate, and manipulate them.&lt;br /&gt;
===Uploading AssetBundles===&lt;br /&gt;
You will need to have Unity installed for this part.&lt;br /&gt;
&lt;br /&gt;
You will also need to have the “Quattro3D- Unity Project for bundle asset creation.7z&amp;quot; Unity project installed from the google drive.&lt;br /&gt;
&lt;br /&gt;
I will be going through an example, demonstrating how it’s done.&lt;br /&gt;
&lt;br /&gt;
Begin by choosing what prefabs you want to upload. In our case, I will upload a bomb and a character prefab, which I already have ready in a different project.&lt;br /&gt;
&lt;br /&gt;
Note: Remember you cant put scripts in your asset bundles.&lt;br /&gt;
&lt;br /&gt;
Open the Unity project downloaded (“Quattro3D- Unity Project for bundle asset creation.7z&amp;quot;). This project contains a script that builds the assetbundles and puts them in the Assets/StreamingAssets folder, which will hold all our uploadable files.&lt;br /&gt;
&lt;br /&gt;
In the Assets folder, I will create a new folder and name it Example.&lt;br /&gt;
&lt;br /&gt;
Next I will import my prefabs;&lt;br /&gt;
&lt;br /&gt;
In the top left menu hit (Assets&amp;gt;Import New Asset/Import Package). Go to the location of your prefabs and select them and press Import.&lt;br /&gt;
&lt;br /&gt;
[[File:Uploading assetbundles.png|frameless|371x371px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Prefabs.png|frameless|476x476px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Imported prefabs.png|frameless|773x773px]]&lt;br /&gt;
&lt;br /&gt;
Now that we’ve imported our assets, we’ll create an assetbundle to be uploaded to the server;&lt;br /&gt;
&lt;br /&gt;
Using the Unity way of creating assetbundles by flagging the prefabs:&lt;br /&gt;
&lt;br /&gt;
Select all the prefabs in the asset folder, the Inspector Window should open. At the bottom right of your screen, in the Inspector Window, create or select an existing name for your assetbundle.&lt;br /&gt;
&lt;br /&gt;
The bundle will embed all the assets/prefabs under that flagged directory. You can of course put multiple prefabs/files/subdir...etc inside an asset bundle.&lt;br /&gt;
&lt;br /&gt;
[[File:Adding a tag to the prefabs.png|frameless|541x541px]]    [[File:Tagging prefabs.png|frameless|541x541px]]&lt;br /&gt;
&lt;br /&gt;
Now build your asset by pressing on BuildAssetBundles&amp;gt;PackagesBuilder&amp;gt;buildAssetBundles in that project.&lt;br /&gt;
&lt;br /&gt;
The built asset will be stored in the downloaded Unity Project in “Quattro3D- Unity Project for bundle asset creation\Assets\StreamingAssets”&lt;br /&gt;
&lt;br /&gt;
[[File:Uploading assets to the server.png|frameless|712x712px]]&lt;br /&gt;
&lt;br /&gt;
The file that we’ll use to upload to graal should end with “.txt”&lt;br /&gt;
&lt;br /&gt;
[[File:Uploading to the server.png|frameless|800x800px]]&lt;br /&gt;
&lt;br /&gt;
Finally to upload the asset to the server, login on rc, go to levels/assetbundles and drop the “.txt” file there.&lt;br /&gt;
&lt;br /&gt;
It should be automatically downloaded to /Users/”yourusername”/AppData/LocalLow/Graal Worlds/Levels3d/assetbundles[[File:Uploading assets through rc.png|center|frameless|477x477px]]''You’re strongly advised to generate a unitypackage too when you generate an asset bundle and upload it to the server, so that everyone can rebuild the bundle on every platform.''&lt;br /&gt;
&lt;br /&gt;
To view your asset and your prefabs, login to the Client, hit F10 to open the Bundle Explorer and search for your asset name.[[File:Bundle explorer.png|center|frameless|768x768px]]&lt;br /&gt;
===ClientSide Loading Assets===&lt;br /&gt;
Now to load your prefabs using GraalScript; to your code add the following:&lt;br /&gt;
&lt;br /&gt;
You can use the Bundle Explorer (F10) to copy the path of the AssetBundle.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|findplayer(&amp;quot;Graal5918039&amp;quot;).addweapon(this.name);&lt;br /&gt;
//#CLIENTSIDE&lt;br /&gt;
&lt;br /&gt;
function onCreated() {&lt;br /&gt;
&lt;br /&gt;
  (@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;documentationexample&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function onAssetBundleDownloaded(bundlename) {&lt;br /&gt;
&lt;br /&gt;
  if (bundlename == &amp;quot;documentationexample&amp;quot;) {&lt;br /&gt;
&lt;br /&gt;
    player.chat = &amp;quot;example loaded&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
    temp.prefab = GameObject::fromassetbundle(&amp;quot;documentationexample&amp;quot;, &amp;quot;assets/example/bomb.prefab&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    this.bomb = Object::Instantiate(Type::GameObject, temp.prefab);&lt;br /&gt;
&lt;br /&gt;
    this.bomb.transform.position = v3(player.x + 5, player.z, player.y);&lt;br /&gt;
&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
|}[[File:Loading prefabs.png|center|frameless|406x406px]]&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!(@&amp;quot;3D/Dev/AssetManager&amp;quot;).loadAssetBundle(&amp;quot;documentationexample&amp;quot;);&lt;br /&gt;
|}&lt;br /&gt;
The above method loads and downloads the AssetBundle.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! function onAssetBundleDownloaded(bundlename) {} &lt;br /&gt;
|}&lt;br /&gt;
And Implementing the '''''onAssetBundleDownloaded''''' will make sure the Assetbundle has been loaded. We could've skipped this step and directly created the prefab, but best is to make sure the Asset has been loaded.&lt;br /&gt;
&lt;br /&gt;
We then create a prefab:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!temp.prefab = GameObject::fromassetbundle(&amp;quot;documentationexample&amp;quot;, &amp;quot;assets/example/bomb.prefab&amp;quot;);&lt;br /&gt;
|}&lt;br /&gt;
instantiate it,&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.bomb = Object::Instantiate(Type::GameObject, temp.prefab);&lt;br /&gt;
|}&lt;br /&gt;
and give it a position in the scene:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.bomb.transform.position = v3(player.x + 5, player.z, player.y);&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Getting_Started_Examples&amp;diff=20931</id>
		<title>Getting Started Examples</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Getting_Started_Examples&amp;diff=20931"/>
		<updated>2021-10-12T11:13:26Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Here are a few examples for beginners wanting to get into Graal3D. You will need to have both the '''Worlds Client''' and '''RC''' downloaded. You will also need an authorized account to be able to login to the server.&lt;br /&gt;
#Download the build compressed file, uncompress it and run the Build application.&lt;br /&gt;
#Login with your GraalID and password, a window will open containing Worlds and Account info.&lt;br /&gt;
#Login to the erareloaded server by typing “erareloaded” in the bottom left server field and press Enter.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Once logged in, you're required to know how to use the tools that allow you to warp to different levels, debug your code... Unity tools are also available as well.&lt;br /&gt;
&lt;br /&gt;
An explanation of all the tools is available here: [[Tools]] &lt;br /&gt;
===Building a Wall Example - ''Creating prefabs and instantiating them''===&lt;br /&gt;
This example is found in the Unity Manual; We will build a wall using primitive type Cubes as Gameobjects. It will be demonstrated using Unity C# and on Graal3D using Graalscript.&lt;br /&gt;
====Using Unity====&lt;br /&gt;
Open the Unity editor with a new project.&lt;br /&gt;
&lt;br /&gt;
'''Step1: Creating an empty Gameobject to hold our Script'''&lt;br /&gt;
&lt;br /&gt;
To your scene add an empty Gameobject. To do that, right click in the Hierarchy Section (on the left) and click on '''Create Empty''', place the created Gameobject in the scene in front of the camera.&lt;br /&gt;
&lt;br /&gt;
This Gameobject will hold our script to build a wall.&lt;br /&gt;
&lt;br /&gt;
[[File:1.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
'''Step2: Creating a Prefab'''&lt;br /&gt;
&lt;br /&gt;
In the same way add a Cube Gameobject to the Hierarchy (right click in Hierarchy -&amp;gt; 3D Object -&amp;gt; Cube).&lt;br /&gt;
&lt;br /&gt;
Now drag the Cube from the Hierarchy to the Assets Section to create a prefab (it will serve as a template to instantiate cubes). Rename the Cube to block (right click on the prefab -&amp;gt; rename).&lt;br /&gt;
&lt;br /&gt;
[[File:2.png|frameless|349x349px]]&lt;br /&gt;
&lt;br /&gt;
'''Step3: Running the script'''&lt;br /&gt;
&lt;br /&gt;
Now to the empty Gameobject we’ll need to add the script that builds a wall.&lt;br /&gt;
&lt;br /&gt;
Press on the Gameobject in the Hierarchy, all its details will pop up in the Inspector Section (on the right). Press on Add Component and search for “script” to add a new script.&lt;br /&gt;
&lt;br /&gt;
[[File:3.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
To modify the script, open it in your IDE and copy the C# script below.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Make sure you name the public class the same name as your script file.&lt;br /&gt;
 using System.Collections;&lt;br /&gt;
 using System.Collections.Generic;&lt;br /&gt;
 using UnityEngine;&lt;br /&gt;
 public class wall: MonoBehaviour {&lt;br /&gt;
   public GameObject block;&lt;br /&gt;
   public int width = 10;&lt;br /&gt;
   public int height = 4;&lt;br /&gt;
   void Start(){&lt;br /&gt;
     for (int y = 0; y &amp;lt; height; ++y) {&lt;br /&gt;
       for (int x = 0; x &amp;lt; width; ++x) {&lt;br /&gt;
         Instantiate(block, new Vector3(x, y, 0), Quaternion.identity);&lt;br /&gt;
       }&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
''Building a Wall - C# Script''&lt;br /&gt;
&lt;br /&gt;
Finally, you’ll need to add the block prefab that we’ve created earlier to script component (to replace the public Gameobject variable “block” in the script).&lt;br /&gt;
&lt;br /&gt;
To do that, drag it from the assets folder to the script component.&lt;br /&gt;
&lt;br /&gt;
[[File:Prefab.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After having completed all the steps above, you should be able to start your scene, it will run all the scripts of the Gameobjects... et Voilà! A Wall![[File:WallOnUnity.png|frameless|671x671px]]&lt;br /&gt;
&lt;br /&gt;
''Wall with 10 Columns and 4 Rows''                                           &lt;br /&gt;
&lt;br /&gt;
'''Explanation:'''&lt;br /&gt;
&lt;br /&gt;
A script needs to implement a class that extends the built-in class '''MonoBehavior'''.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|public class wall: MonoBehaviour { }&lt;br /&gt;
|}The '''Start''' function is where you instantiate your Gameobjects.&lt;br /&gt;
&lt;br /&gt;
The '''Update''' function is where the gameplay updates happen (Gameobject movement, triggering actions, taking user input...). It is similar to the onTimeOut / onMouseDown / onKeyPressed... functions in Graalscript.&lt;br /&gt;
&lt;br /&gt;
'''Important Note:'''&lt;br /&gt;
&lt;br /&gt;
[[File:Coordinates.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Everything related to movement, direction, rotation, speed… in Unity is done using Vectors: '''''new Vector3(x, y, z)'''''&lt;br /&gt;
&lt;br /&gt;
In unity the y axis represents the vertical axis (usually referred to as z)&lt;br /&gt;
&lt;br /&gt;
'''Instantiate Function in Unity:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|Instantiate(block, new Vector3(x, y, 0), Quaternion.identity);&lt;br /&gt;
|}'''Instantiate Function in Unity:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|public static Object Instantiate(Object original, Vector3 position, Quaternion rotation);&lt;br /&gt;
|}In the example, the Object is the block and the rotation is&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|Quaternion.identity&lt;br /&gt;
|}&lt;br /&gt;
to indicate 0 rotation.&lt;br /&gt;
&lt;br /&gt;
'''Quaternions:'''&lt;br /&gt;
&lt;br /&gt;
Quaternions are used to represent rotations. The most used Quaternion functions: Quaternion.LookRotation, Quaternion.Angle, Quaternion.Euler, Quaternion.Slerp, Quaternion.FromToRotation, and Quaternion.identity.&lt;br /&gt;
&lt;br /&gt;
'''Another Way:'''&lt;br /&gt;
&lt;br /&gt;
For primitive types there’s no need to actually create a prefab since they are recognized by Unity. We could have skipped step 2 where we create the prefab and modified our code to this:&lt;br /&gt;
 using System.Collections;&lt;br /&gt;
 using System.Collections.Generic;&lt;br /&gt;
 using UnityEngine;&lt;br /&gt;
 public class wall: MonoBehaviour {&lt;br /&gt;
   public int width = 10;&lt;br /&gt;
   public int height = 4;&lt;br /&gt;
   void Start() {&lt;br /&gt;
     for (int y = 0; y &amp;lt; height; ++y) {&lt;br /&gt;
       for (int x = 0; x &amp;lt; width; ++x) {&lt;br /&gt;
         GameObject.CreatePrimitive(PrimitiveType.Cube).transform.position = new Vector3(x, y, 0);&lt;br /&gt;
       }&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
''Building a Wall - C# Script''&lt;br /&gt;
====Using Graal3D====&lt;br /&gt;
We are going to mimic the second C# script since it would be useless to upload a Cube prefab to the server, when we can simply instantiate them using PrimitiveType.&lt;br /&gt;
&lt;br /&gt;
The same script above will look like this in GraalScript: ('''''Weapon:''''' ''3D/Samples/Examples/BuildingWall'')&lt;br /&gt;
 findplayer(&amp;quot;GraalID&amp;quot;).addweapon(this.name);&lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   this.width = 10;&lt;br /&gt;
   this.height = 4;&lt;br /&gt;
   for (temp.y = 0; temp.y &amp;lt; this.height; ++temp.y) {&lt;br /&gt;
     for (temp.x = 0; temp.x &amp;lt; this.width; ++temp.x) {&lt;br /&gt;
       GameObject::CreatePrimitive(PrimitiveType::Cube).transform.position = v3(player.x - 5 + temp.x, temp.y, player.y + 1);&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
''Building a Wall - Graal Script''&lt;br /&gt;
&lt;br /&gt;
The two codes are almost the same except for:&lt;br /&gt;
*The '''''onCreated()''''' function replaces the '''''start()''''' function&lt;br /&gt;
*The “ . ” for methods is replaced by “:: ”&lt;br /&gt;
'''Function format:''' Unity C#: '''''Type.method''''' =&amp;gt; Graal Script: '''''Type::Method'''''&lt;br /&gt;
*'''''v3(x,y,z)''''' replaces '''new''' '''''Vector3(x,y,z)'''''&lt;br /&gt;
*The Gameobject is instantiated close to the player using (player.x and player.y)&lt;br /&gt;
[[File:Wall.png|frameless|695x695px]]&lt;br /&gt;
&lt;br /&gt;
''Wall with 10 Columns and 4 Rows''&lt;br /&gt;
===Circle Formation Example - Using Rotation and Mathf functions===&lt;br /&gt;
This example is similar to the one above, we’ll instantiate the Cubes in a circular shape with rotation so that they all point towards the player.&lt;br /&gt;
====Using Unity====&lt;br /&gt;
Just like in the previous example; create a new script file named “CircleFormation”, open it in you editor and copy paste this code:&lt;br /&gt;
 using UnityEngine;&lt;br /&gt;
 public class CircleFormation: MonoBehaviour {&lt;br /&gt;
   public GameObject prefab;&lt;br /&gt;
   public int numberOfObjects = 20;&lt;br /&gt;
   public float radius = 5f;&lt;br /&gt;
   void Start() {&lt;br /&gt;
     for (int i = 0; i &amp;lt; numberOfObjects; i++) {&lt;br /&gt;
       float angle = i * Mathf.PI * 2 / numberOfObjects;&lt;br /&gt;
       float x = Mathf.Cos(angle) * radius;&lt;br /&gt;
       float z = Mathf.Sin(angle) * radius;&lt;br /&gt;
       Vector3 pos = transform.position + new Vector3(x, 0, z);&lt;br /&gt;
       float angleDegrees = -angle*Mathf.Rad2Deg;&lt;br /&gt;
       Quaternion rot = Quaternion.Euler(0, angleDegrees, 0);&lt;br /&gt;
       Instantiate(prefab, pos, rot);&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
''Circle Formation - C# Script''&lt;br /&gt;
&lt;br /&gt;
Create an empty Gameobject in the Hierarchy, add the script to it (as a component).&lt;br /&gt;
&lt;br /&gt;
Add a Cube Gameobject to the Hierarchy (right click -&amp;gt; 3D Object -&amp;gt; Cube).&lt;br /&gt;
&lt;br /&gt;
Now drag the Cube from the Hierarchy to the Assets Section to create a prefab, rename it to “prefab” to be referenced by the script. Finally add it to the script on the Empty Gameobject and hit run.&lt;br /&gt;
&lt;br /&gt;
[[File:Circle formation unity.png|frameless|751x751px]]&lt;br /&gt;
&lt;br /&gt;
'''Explanation:'''&lt;br /&gt;
&lt;br /&gt;
In this example we use the '''Mathf''' collection, a struct containing all the static math methods.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;https://docs.unity3d.com/ScriptReference/Mathf.html&amp;lt;/u&amp;gt; for all the methods.&lt;br /&gt;
&lt;br /&gt;
We also use the '''''Quaternion.Euler''''' to rotate the cubes. You can rotate around whatever axis you want, in our example '''''Quaternion.Euler(0, angleDegress, 0)''''' rotates the cubes around the y axis.&lt;br /&gt;
&lt;br /&gt;
'''Another Way:'''&lt;br /&gt;
&lt;br /&gt;
Just like before we could’ve just used '''''GameObject.CreatePrimitive(PrimitiveType.Cube)''''' to create the cubes and then change the transform.position and the transform.rotation.&lt;br /&gt;
====Using Graal3D====&lt;br /&gt;
Again, since we don’t want to upload useless PrimitiveType prefabs to the server, we use this approach: ('''''Weapon:''''' ''3D/Samples/Examples/CircleFormation'')&lt;br /&gt;
 findplayer(&amp;quot;GraalID&amp;quot;).addweapon(this.name);&lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   temp.nbofobjects = 20;&lt;br /&gt;
   temp.radius = 5f;&lt;br /&gt;
   for (temp.i = 0; temp.i &amp;lt; temp.nbofobjects; ++temp.i) {&lt;br /&gt;
     temp.angle = temp.i * Mathf::PI * 2 / temp.nbofobjects;&lt;br /&gt;
     temp.x1 = cos(temp.angle) * temp.radius;&lt;br /&gt;
     temp.y1 = sin(temp.angle) * temp.radius;&lt;br /&gt;
     temp.cube = GameObject::CreatePrimitive(PrimitiveType::Cube);&lt;br /&gt;
     temp.cube.transform.position = v3(player.x + temp.x1, player.z, player.y + temp.y1);&lt;br /&gt;
     temp.angleDegrees = -temp.angle * Mathf::Rad2Deg;&lt;br /&gt;
     temp.cube.transform.rotation = Quaternion::euler(0, temp.angleDegrees, 0);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
[[File:Circle formation graal3d.png|frameless|639x639px]]&lt;br /&gt;
&lt;br /&gt;
''Circle Formation - Graal Script''&lt;br /&gt;
===Moving Cube Example - Using the Update function===&lt;br /&gt;
====Using Unity====&lt;br /&gt;
 using System.Collections;&lt;br /&gt;
 using System.Collections.Generic;&lt;br /&gt;
 using UnityEngine;&lt;br /&gt;
 public class MovingCube: MonoBehaviour {&lt;br /&gt;
   GameObject cube;&lt;br /&gt;
   public int height = 10;&lt;br /&gt;
   public float yCenter = 0f;&lt;br /&gt;
   void Start() {&lt;br /&gt;
     cube = GameObject.CreatePrimitive(PrimitiveType.Cube);&lt;br /&gt;
     cube.transform.position = new Vector3(0, 0f, 0);&lt;br /&gt;
   }&lt;br /&gt;
   void Update() {&lt;br /&gt;
     cube.transform.position = new Vector3(cube.transform.position.x, yCenter + Mathf.PingPong(Time.time * 2, height) - height / 2f,       cube.transform.position.z);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
''Moving Cube - C# Script''&lt;br /&gt;
&lt;br /&gt;
Here we use the Update function. As its name suggests, it will serve to update gameplay and move the cube up and down depending on the time.&lt;br /&gt;
====Using Graal3D====&lt;br /&gt;
('''''Weapon:''''' ''3D/Samples/Examples/MovingCube'')&lt;br /&gt;
 findplayer(&amp;quot;GraalID&amp;quot;).addweapon(this.name);&lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 function onCreated(){&lt;br /&gt;
   this.cube = GameObject::CreatePrimitive(PrimitiveType::Cube);&lt;br /&gt;
   this.cube.transform.position = v3(player.x,player.z,player.y);&lt;br /&gt;
   this.height = 10;//max height of Box's movement&lt;br /&gt;
   this.yCenter = 0.0;&lt;br /&gt;
   SetTimer(0.001);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onTimeout() {&lt;br /&gt;
   this.cube.transform.position = v3(this.cube.transform.position.x,this.yCenter + Mathf::PingPong(Time::time *2,    this.height)  - height / 2.0,this.cube.transform.position.z);&lt;br /&gt;
   SetTimer(0.001);&lt;br /&gt;
 }&lt;br /&gt;
Moving Cube - GraalScript&lt;br /&gt;
&lt;br /&gt;
Here the '''''SetTimer()''''' and '''''onTimeout()''''' functions replace the '''''Update()''''' function in Unity.&lt;br /&gt;
===Cube with Physics - Using Physics and Collision===&lt;br /&gt;
In this example we will add physics to our Gameobject, it will be subject to gravity, forces and collisions with other Gameobjects. We will also see how to detect and handle these collisions.&lt;br /&gt;
&lt;br /&gt;
('''''Weapon:''''' ''3D/Samples/Examples/SimplePhysicObject'')&lt;br /&gt;
 findplayer(&amp;quot;GraalID&amp;quot;).addweapon(this.name);&lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   SetTimer(9999);&lt;br /&gt;
   this.cube = GameObject::CreatePrimitive(PrimitiveType::Cube);&lt;br /&gt;
   this.cube.transform.position = v3(player.x + 5, player.z, player.y);&lt;br /&gt;
   this.cube.AddComponent(Type::RigidBody);&lt;br /&gt;
   Quattro::EventManager::AddOnCollisionHandlerTo(this.cube, this.cube.layer);&lt;br /&gt;
   this.catcheventobject(this.cube, &amp;quot;onCollisionEnter&amp;quot;, &amp;quot;onCubeCollisionEnter&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function onCubeCollisionEnter(gameobject, collision) {&lt;br /&gt;
   player.chat = &amp;quot;Collision!&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
''Cube with Physics - Graal Script''&lt;br /&gt;
&lt;br /&gt;
We create and place a Cube just like the examples before. &lt;br /&gt;
&lt;br /&gt;
To add physics to the GameObject, we add the '''RigidBody Component''';&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.cube.AddComponent(Type::RigidBody);&lt;br /&gt;
|}&lt;br /&gt;
Now to add a Collision Handler;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!''Quattro::EventManager::AddOnCollisionHandlerTo()''&lt;br /&gt;
|}&lt;br /&gt;
And &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!''this.catcheventobject(GameObject, “onCollisionEnter”, “onFunctionName”)''&lt;br /&gt;
|}&lt;br /&gt;
Which will catch collision and call the function '''''onFunctionName()''''' that you have to implement;&lt;br /&gt;
 public function onCubeCollisionEnter(gameobject, collision) {&lt;br /&gt;
   player.chat = &amp;quot;Collision!&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
The two parameters:&lt;br /&gt;
&lt;br /&gt;
'''gameobject:''' it is the Gameobject that was just used to detect collision (''the cube in our example'')&lt;br /&gt;
&lt;br /&gt;
'''collision:''' describes the collider we hit, you can retrieve the GameObject collided with by using: '''''collision.GameObject'''.''&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Whenever we use collisions, the '''''SetTimer(9999)''''' is essential; it will keep the script alive and always checking for events. the Unity function OnUpdate() will be triggered for every frame.&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Graal3D_Scripting_Manual&amp;diff=20930</id>
		<title>Graal3D Scripting Manual</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Graal3D_Scripting_Manual&amp;diff=20930"/>
		<updated>2021-10-12T11:02:24Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: changing worlds client download link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Intro ==&lt;br /&gt;
[[File:Graal kart start.jpg|center|frame]]&lt;br /&gt;
Welcome to the Graal3D Scripting Manual!&lt;br /&gt;
&lt;br /&gt;
This Manual comes in handy for beginners wanting to learn Graal3D Scripting, and advanced developers looking to expand their knowledge, as it  contains documentation, examples, tutorials and much more...&lt;br /&gt;
&lt;br /&gt;
What we will focus on in this Manual is programming our gameplay (scripting the behavior of our GameObjects, their interactions, the components attached to them...)&lt;br /&gt;
&lt;br /&gt;
==== How things work in Unity: ====&lt;br /&gt;
Unity is the leading platform for building 2D, 3D, VR and augmented reality games. It offers a scripting API in C#, allowing us to interact with the unity editor and the games we want to build.&lt;br /&gt;
&lt;br /&gt;
In the Unity editor, we create and add GameObjects to our scene, we then attach C# scripts to each that will all run upon starting the scene. Unity sort of runs everything for you, it reads through all the lights, cameras, meshes, behaviors… and processes it for you.&lt;br /&gt;
&lt;br /&gt;
==== How things work in Graal3D: ====&lt;br /&gt;
Since we will be using the Graal Unity Binding, things will be a bit different.&lt;br /&gt;
&lt;br /&gt;
The Graal Unity Binding is a binding between GraalScript and Unity, it is actually still in alpha, but most functionalities needed are present. The goal of this binding is to mimic the Unity C# scripting system (functions and classes). So if you are familiar with Unity and C#, everything should be easy. If not, then do not worry, I will go over everything step by step and include examples done in C# and compare them to GraalScript for each topic.&lt;br /&gt;
&lt;br /&gt;
The Worlds Client (which you will have to download) will serve as the Unity editor, mentioned earlier, which contains the base scene where you instantiate your GameObjects and manipulate them with your GraalScripts.&lt;br /&gt;
&lt;br /&gt;
==== Required Downloads ====&lt;br /&gt;
'''Unity 2020.2.2f1:''' https://unity3d.com/get-unity/download/archive&lt;br /&gt;
&lt;br /&gt;
'''The Worlds Client:''' https://github.com/TOONSLAB/GRAALONLINE/releases&lt;br /&gt;
&lt;br /&gt;
'''RC:''' http://fp4.ca/windows_rc3_beta.zip&lt;br /&gt;
&lt;br /&gt;
==== Tools ====&lt;br /&gt;
In-game Unity Tools (''mimic the Unity Editor)'' &amp;amp; Game Functionality Tools ''(warping, fixing graphics, starting minigames...):'' &amp;lt;u&amp;gt;[[Tools]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
&lt;br /&gt;
==== Unity ====&lt;br /&gt;
&lt;br /&gt;
* [[Overview On Unity Basics]]&lt;br /&gt;
&lt;br /&gt;
==== AssetBundles ====&lt;br /&gt;
&lt;br /&gt;
* [[Uploading and Loading AssetBundles]]&lt;br /&gt;
*[[Placing GameObjects in NPC]]&lt;br /&gt;
&lt;br /&gt;
==== Examples and Tutorials ====&lt;br /&gt;
*[[Getting Started Examples]]&lt;br /&gt;
*[[3DTutorials|Tutorials]]&lt;br /&gt;
*[[Unity UI]]&lt;br /&gt;
*[[Item Manager]]&lt;br /&gt;
&lt;br /&gt;
==== Classes, Functions and Variables ====&lt;br /&gt;
&lt;br /&gt;
* [https://quattro3d.graalonline.com/Documentation/ Quattro3D Scripting]&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Graal3D_Scripting_Manual&amp;diff=20929</id>
		<title>Graal3D Scripting Manual</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Graal3D_Scripting_Manual&amp;diff=20929"/>
		<updated>2021-10-12T10:42:29Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: changing graal3d client with worlds client&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Intro ==&lt;br /&gt;
[[File:Graal kart start.jpg|center|frame]]&lt;br /&gt;
Welcome to the Graal3D Scripting Manual!&lt;br /&gt;
&lt;br /&gt;
This Manual comes in handy for beginners wanting to learn Graal3D Scripting, and advanced developers looking to expand their knowledge, as it  contains documentation, examples, tutorials and much more...&lt;br /&gt;
&lt;br /&gt;
What we will focus on in this Manual is programming our gameplay (scripting the behavior of our GameObjects, their interactions, the components attached to them...)&lt;br /&gt;
&lt;br /&gt;
==== How things work in Unity: ====&lt;br /&gt;
Unity is the leading platform for building 2D, 3D, VR and augmented reality games. It offers a scripting API in C#, allowing us to interact with the unity editor and the games we want to build.&lt;br /&gt;
&lt;br /&gt;
In the Unity editor, we create and add GameObjects to our scene, we then attach C# scripts to each that will all run upon starting the scene. Unity sort of runs everything for you, it reads through all the lights, cameras, meshes, behaviors… and processes it for you.&lt;br /&gt;
&lt;br /&gt;
==== How things work in Graal3D: ====&lt;br /&gt;
Since we will be using the Graal Unity Binding, things will be a bit different.&lt;br /&gt;
&lt;br /&gt;
The Graal Unity Binding is a binding between GraalScript and Unity, it is actually still in alpha, but most functionalities needed are present. The goal of this binding is to mimic the Unity C# scripting system (functions and classes). So if you are familiar with Unity and C#, everything should be easy. If not, then do not worry, I will go over everything step by step and include examples done in C# and compare them to GraalScript for each topic.&lt;br /&gt;
&lt;br /&gt;
The Worlds Client (which you will have to download) will serve as the Unity editor, mentioned earlier, which contains the base scene where you instantiate your GameObjects and manipulate them with your GraalScripts.&lt;br /&gt;
&lt;br /&gt;
==== Required Downloads ====&lt;br /&gt;
'''Unity 2020.2.2f1:''' https://unity3d.com/get-unity/download/archive&lt;br /&gt;
&lt;br /&gt;
'''The Worlds Client:''' https://drive.google.com/drive/u/0/folders/1rpOli0fxnA-Q7-IpYg3rUFJ44M0PsSxd&lt;br /&gt;
&lt;br /&gt;
'''RC:''' http://fp4.ca/windows_rc3_beta.zip&lt;br /&gt;
&lt;br /&gt;
==== Tools ====&lt;br /&gt;
In-game Unity Tools (''mimic the Unity Editor)'' &amp;amp; Game Functionality Tools ''(warping, fixing graphics, starting minigames...):'' &amp;lt;u&amp;gt;[[Tools]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
&lt;br /&gt;
==== Unity ====&lt;br /&gt;
&lt;br /&gt;
* [[Overview On Unity Basics]]&lt;br /&gt;
&lt;br /&gt;
==== AssetBundles ====&lt;br /&gt;
&lt;br /&gt;
* [[Uploading and Loading AssetBundles]]&lt;br /&gt;
*[[Placing GameObjects in NPC]]&lt;br /&gt;
&lt;br /&gt;
==== Examples and Tutorials ====&lt;br /&gt;
*[[Getting Started Examples]]&lt;br /&gt;
*[[3DTutorials|Tutorials]]&lt;br /&gt;
*[[Unity UI]]&lt;br /&gt;
*[[Item Manager]]&lt;br /&gt;
&lt;br /&gt;
==== Classes, Functions and Variables ====&lt;br /&gt;
&lt;br /&gt;
* [https://quattro3d.graalonline.com/Documentation/ Quattro3D Scripting]&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Unity_UI&amp;diff=20928</id>
		<title>Unity UI</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Unity_UI&amp;diff=20928"/>
		<updated>2021-09-02T18:04:08Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:UnityUI.png|thumb|889x889px|none]]In this section we will go over an example of making a UI on unity and uploading and coding it on Client3D in graalscript.&lt;br /&gt;
&lt;br /&gt;
'''Unity Part:'''&lt;br /&gt;
&lt;br /&gt;
Open the “Quattro3D- Unity Project for bundle asset creation” folder using unity hub.&lt;br /&gt;
&lt;br /&gt;
To the assets folder, add we add a folder that will hold all the prefabs of the assetbundle.&lt;br /&gt;
&lt;br /&gt;
To the scene, add a Canvas (in the Hierarchy, right click -&amp;gt; UI -&amp;gt; Canvas). The Canvas will hold all the elements of our UI (buttons, text, scrollbar, images…).&lt;br /&gt;
&lt;br /&gt;
Select the Canvas and in the Inspector go to '''Canvas Scaler''' and select '''Scale With Screen''' for '''UI Scale Mode'''. This will allow the canvas Canvas to expand to full screen on all screens.&lt;br /&gt;
&lt;br /&gt;
Now to build the UI you see above (devtools). Start by adding Text elements (right click on Canvas -&amp;gt; UI -&amp;gt; Text).&lt;br /&gt;
&lt;br /&gt;
For each element, change the name and the text according to its function, change the color to white, add a button component and add a animation component. In the '''Rect Transform''' component, in the Anchor Presets, hold Alt and select top left to position your element.&lt;br /&gt;
&lt;br /&gt;
Add all the Text elements and position them (Inspector, Bundle Explorer, Console, Camera, Rendering).&lt;br /&gt;
&lt;br /&gt;
Now, to add the back button. Add an Image element to the UI, change its name to “back”, and in the image component add the source of the image (drop down in our case). Rotate it -90 deg on the Z axis for it to face left. Add a button component to turn it to a back button that closes the devtools.&lt;br /&gt;
&lt;br /&gt;
For the grey background you see, add and image just like before, change its color to black and change the A field in RGBA to 48 to make it transparent. Add an '''Outline''' component and change the '''Effect Color''' to white to add an outline to the image.&lt;br /&gt;
[[File:Unity UI.png|none|thumb|1006x1006px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now that we’ve added all our elements to the Canvas, it’s time to create our animations.&lt;br /&gt;
&lt;br /&gt;
To create an animation, in the top menu (next to Files, Edit, Assets…) go to Window -&amp;gt; Animation -&amp;gt; Animation.&lt;br /&gt;
&lt;br /&gt;
The animation tab should open in the bottom. Select the component you want to create an animation for and create and name the animation.&lt;br /&gt;
&lt;br /&gt;
We will be doing the sliding background image example for the animation. &lt;br /&gt;
&lt;br /&gt;
To record the animation, press on the record button. We want the image to slide in. So put the cursor on time 0s, and change the Pos X to -65 (outside of the screen) then move the cursor to 4s and change the Pos X back to 65. Press the record button again to save the recording. &lt;br /&gt;
[[File:Unity UI anim.png|none|thumb|1032x1032px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can press play to view your animation in action. To add the animation to the element; simply add an animation component and add the source of the animation you just created.&lt;br /&gt;
&lt;br /&gt;
Same thing goes for all the other animations.&lt;br /&gt;
&lt;br /&gt;
'''Graal Script Part:'''&lt;br /&gt;
&lt;br /&gt;
Now that we’ve created our prefabs and added the animations, our canvas is ready to be uploaded on the server and scripted. Save the AssetBundle and upload it to the server ([[Uploading and Loading AssetBundles]] for more info).&lt;br /&gt;
  findplayer(&amp;quot;Graal5918039&amp;quot;).addweapon(this.name);&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 &lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;dev&amp;quot;) toggle();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function toggle() {&lt;br /&gt;
   Quattro::AssetManagement::LoadAssetBundle(&amp;quot;devtoolsui&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onAssetBundleDownloaded(bundlename) {&lt;br /&gt;
   if (bundlename == &amp;quot;devtoolsui&amp;quot;) {&lt;br /&gt;
     SetTimer(9999);&lt;br /&gt;
     this.btns = {&amp;quot;inscpector&amp;quot;, &amp;quot;bundleexpl&amp;quot;, &amp;quot;console&amp;quot;, &amp;quot;camera&amp;quot;, &amp;quot;rendering&amp;quot;, &amp;quot;back&amp;quot;};&lt;br /&gt;
     this.devuiprefab = GameObject::fromassetbundle(&amp;quot;devtoolsui&amp;quot;, &amp;quot;assets/menuui/canvasdevtools.prefab&amp;quot;);&lt;br /&gt;
     this.devui = Object::Instantiate(Type::GameObject, this.devuiprefab);&lt;br /&gt;
 &lt;br /&gt;
     for (btnb: this.btns) {&lt;br /&gt;
       temp.btn = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, btn);&lt;br /&gt;
       Quattro::EventManager::AddEventHandlerTo(temp.btn.gameobject.GetComponent(Type::UI::Button));&lt;br /&gt;
       this.catcheventobject(temp.btn.gameobject, &amp;quot;onClick&amp;quot;, &amp;quot;onDevToolClick&amp;quot;);&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     Object::Destroy(this.devui, 4);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function onDevToolClick(go) {&lt;br /&gt;
   if (go.name == &amp;quot;inscpector&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;bundleexpl&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;console&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;camera&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;rendering&amp;quot;) player.chat = go.name;&lt;br /&gt;
   &lt;br /&gt;
   if (go.name == &amp;quot;back&amp;quot;) close();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function close() {&lt;br /&gt;
   for (btn : this.btns) {&lt;br /&gt;
     temp.btn = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, btn);&lt;br /&gt;
     Object::Destroy(temp.btn.gameobject);&lt;br /&gt;
   } &lt;br /&gt;
   &lt;br /&gt;
   temp.img = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, &amp;quot;Image&amp;quot;);&lt;br /&gt;
   temp.anim = temp.img.gameobject.GetComponent(Type::Animation);&lt;br /&gt;
   temp.anim.play(&amp;quot;devtools2&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
We load the assetbundle the usual way: &lt;br /&gt;
 Quattro::AssetManagement::LoadAssetBundle(&amp;quot;devtoolsui&amp;quot;);&lt;br /&gt;
 function onAssetBundleDownloaded(bundlename) {&lt;br /&gt;
   if (bundlename == &amp;quot;devtoolsui&amp;quot;) {&lt;br /&gt;
'''''Settimer(9999);''''' is necessary for the weapon to keep checking for button clicks.&lt;br /&gt;
&lt;br /&gt;
We create and instantiate the canvas prefab.&lt;br /&gt;
 this.devuiprefab = GameObject::fromassetbundle(&amp;quot;devtoolsui&amp;quot;, &amp;quot;assets/menuui/canvasdevtools.prefab&amp;quot;);&lt;br /&gt;
 this.devui = Object::Instantiate(Type::GameObject, this.devuiprefab);&lt;br /&gt;
this will display the canvas on the client screen.&lt;br /&gt;
&lt;br /&gt;
To detect button clicks;&lt;br /&gt;
 temp.btn = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, btn);&lt;br /&gt;
 Quattro::EventManager::AddEventHandlerTo(temp.btn.gameobject.GetComponent(Type::UI::Button));&lt;br /&gt;
 this.catcheventobject(temp.btn.gameobject, &amp;quot;onClick&amp;quot;, &amp;quot;onDevToolClick&amp;quot;);&lt;br /&gt;
we first find the button GameObject by name ('''this.devui.transform''' being the transform component of the canvas, and '''btn''' is the button name we want to find).&lt;br /&gt;
&lt;br /&gt;
Next, we add an EventManager to the button component of the gameobject we just found ('''temp.btn.gameobject.GetComponent(Type::UI::Button)''').&lt;br /&gt;
&lt;br /&gt;
And '''this.catcheventobject(temp.btn.gameobject, &amp;quot;onClick&amp;quot;, &amp;quot;onDevToolClick&amp;quot;)''' to catch all the onClick events.&lt;br /&gt;
&lt;br /&gt;
Finally, we implement '''public function onDevToolClick(go)''' to add functionalities after button is pressed (with '''go''' the gameobject being pressed).&lt;br /&gt;
&lt;br /&gt;
For animations, to add or play an animation, you will need to get the animation component of the GameObject first. (using: '''temp.img.gameobject.GetComponent(Type::Animation)''')&lt;br /&gt;
 temp.img = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, &amp;quot;Image&amp;quot;);&lt;br /&gt;
 temp.anim = temp.img.gameobject.GetComponent(Type::Animation);&lt;br /&gt;
 temp.anim.play(&amp;quot;devtools2&amp;quot;);&lt;br /&gt;
(more script functionalities for animations available here: https://docs.unity3d.com/ScriptReference/Animation.html).&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Bomberman_MiniGame&amp;diff=20927</id>
		<title>Bomberman MiniGame</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Bomberman_MiniGame&amp;diff=20927"/>
		<updated>2021-09-02T17:49:49Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the Bomberman Minigame Tutorial!&lt;br /&gt;
&lt;br /&gt;
= BomberMan =&lt;br /&gt;
&lt;br /&gt;
==== Intro ====&lt;br /&gt;
BomberMan is a multiplayer game (usually 4 players). Each player can drop bombs that, upon explosion,  destroy the grey pillars making a path to other players. The objective of the game is to eliminate other players with the exploding bombs. Power ups are also sometimes dropped when pillars are destroyed (increase of speed, explosion power and number of bombs allowed to place at a time).&lt;br /&gt;
[[File:Bomberman cover.png|none|thumb|675x675px]]&lt;br /&gt;
Assets are available on the server under:&lt;br /&gt;
&lt;br /&gt;
'''bombermanprefabs'''&lt;br /&gt;
&lt;br /&gt;
[[File:Bomberman prefabs.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
and '''bombermanlevel1'''&lt;br /&gt;
&lt;br /&gt;
[[File:Bomberman level prefab.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
Since this game is meant to be multiplayer, we will be placing the GameObjects in NPCs for them to be visible to all the players and triggerring the server every time we want to place them. (more info on that here: [[Placing GameObjects in NPC]])&lt;br /&gt;
&lt;br /&gt;
First, we have the weapon that launches the game and places the NPCs (''found under '''weapon: 3D/Samples/BomberMan/Game''''')&lt;br /&gt;
&lt;br /&gt;
We've implemented a graalscript UI (which is not covered in this section, considering you know graalscript) that allows us to launch the game;&lt;br /&gt;
 function onActionServerside(cmd, x, y) {&lt;br /&gt;
   if (cmd == &amp;quot;bomb&amp;quot;) {&lt;br /&gt;
     temp.pnpc = putnpc2(x, y, &amp;quot;&amp;quot;);&lt;br /&gt;
     temp.pnpc.join(&amp;quot;merlin_bomberman_bomb&amp;quot;);&lt;br /&gt;
     //temp.pnpc.DropBomb(explvl);&lt;br /&gt;
   }&lt;br /&gt;
   if (cmd == &amp;quot;level&amp;quot;) {&lt;br /&gt;
      temp.bombernpc = putnpc2(x, y, &amp;quot;&amp;quot;);&lt;br /&gt;
      temp.bombernpc.join(&amp;quot;merlin_bomberman_level&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   echo(this.name @ &amp;quot; OnCreated&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function Load() {&lt;br /&gt;
   level.explosionpower = 3; //for powerups with explosion&lt;br /&gt;
   level.numberofbombs = 2; //number of bombs allowed to place at a time&lt;br /&gt;
   level.speed = 7; //player default speed&lt;br /&gt;
   &lt;br /&gt;
   echo(this.name @ &amp;quot; LOAD&amp;quot;);&lt;br /&gt;
   Object::destroy(this.bomberManParentNode);&lt;br /&gt;
   if (isObject(&amp;quot;bomberman_Quit&amp;quot;)) {&lt;br /&gt;
     &amp;quot;bomberman_Quit&amp;quot;.destroy();&lt;br /&gt;
   }&lt;br /&gt;
   new GuiButtonCtrl(&amp;quot;bomberman_Quit&amp;quot;) {&lt;br /&gt;
     profile = GuiBlueButtonProfile;&lt;br /&gt;
     x = 600;&lt;br /&gt;
     y = 200;&lt;br /&gt;
     width = 150;&lt;br /&gt;
     height = 30;&lt;br /&gt;
     text = &amp;quot;bombermanQuit&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   temp.warpLevel = &amp;quot;only_ground.nw&amp;quot;;&lt;br /&gt;
   temp.warpX = 4.65; &lt;br /&gt;
   temp.warpY = 21.33; &lt;br /&gt;
   temp.warpZ = 0.7; &lt;br /&gt;
   WARPMANAGER.Warp(temp.warpX, temp.warpY ,temp.warpZ ,temp.warpLevel);&lt;br /&gt;
   sleep(0.5);&lt;br /&gt;
   start(); &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function bomberman_Quit.onAction() {&lt;br /&gt;
   BomberManQuit();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function BomberManQuit() {&lt;br /&gt;
   if (isObject(&amp;quot;bomberman_Quit&amp;quot;)) {&lt;br /&gt;
     &amp;quot;bomberman_Quit&amp;quot;.destroy();&lt;br /&gt;
   }&lt;br /&gt;
   PLAYERMOVEMENT.UnFreeze();&lt;br /&gt;
   PLAYERMOVEMENT.canJump = true;&lt;br /&gt;
   this.GAMEON = false;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function start() {&lt;br /&gt;
   PLAYERMOVEMENT.canJump = false;&lt;br /&gt;
   this.GAMEON = true;&lt;br /&gt;
   triggerserver(&amp;quot;gui&amp;quot;, this.name, &amp;quot;level&amp;quot;, -60 , 14);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onKeyPressed(keycode, keychar) {&lt;br /&gt;
   if (this.GAMEON == true) {&lt;br /&gt;
     if (keycode == &amp;quot;32, ,57&amp;quot;) {&lt;br /&gt;
       DropBomb();&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function DropBomb() {&lt;br /&gt;
   this.hit = RaycastHit::create();&lt;br /&gt;
   done = Physics::Raycast(player.gameobject.transform.position, Vector3::Down, this.hit, 100);&lt;br /&gt;
   //sleep(0.05);&lt;br /&gt;
   triggerserver(&amp;quot;gui&amp;quot;, this.name, &amp;quot;bomb&amp;quot;, this.hit.transform.gameobject.transform.position.x, this.hit.transform.gameobject.transform.position.z);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
the '''''Load()''''' function is called when the minigame is launched (Devtools -&amp;gt; Minigames -&amp;gt; BomberMan). &lt;br /&gt;
&lt;br /&gt;
'''level.explosionpower = 3;''' is how much tiles the explosion is going to cover. (at the beginning it's 3)&lt;br /&gt;
&lt;br /&gt;
'''level.numberofbombs = 2;''' is the number of bombs a player is allowed to place at a time. (at the beginning it's 2) &lt;br /&gt;
&lt;br /&gt;
In the function '''''start()''''', we trigger the server with the command &amp;quot;'''level'''&amp;quot; to load the bomberman map by placing an NPC and joining it with the class &amp;quot;'''3d_samples_bomberman_level'''&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Once we start the game, the player is not allowed to Jump: '''PLAYERMOVEMENT.canJump = false;''' &lt;br /&gt;
&lt;br /&gt;
And pressing space will be used to drop a bomb, '''''function onKeyPressed()''''' checks if space is pressed and calls '''''DropBomb()'''.''&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: RayCast:&amp;lt;/u&amp;gt; ====&lt;br /&gt;
Think of RayCast as '''''triggeraction()''''' that triggers NPCs at a given (x,y). Similarly, '''''RayCast''''' casts a ray given a position (origin), a direction and a length, detecting colliders.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Raycast(Vector3 origin, Vector3 direction, float maxDistance = Mathf.Infinity, int layerMask = DefaultRaycastLayers, QueryTriggerInteraction queryTriggerInteraction = QueryTriggerInteraction.UseGlobal);&lt;br /&gt;
|}&lt;br /&gt;
'''Returns:''' Boolean indicating if the RayCast hit a Collider.&lt;br /&gt;
&lt;br /&gt;
''(More info here: https://docs.unity3d.com/ScriptReference/Physics.Raycast.html&amp;lt;nowiki/&amp;gt;)''&lt;br /&gt;
&lt;br /&gt;
Here, since the bomberman level is a grid and the floor is made of squares. We want the player to drop the bomb exactly in one square and not in between two. Therefore, when space is pressed, we RayCast with the PlayerGameObject as '''origin''', with a Vector3::Down '''direction''', '''''this.hit''''' as the '''output''' and 100 for '''length'''. The other parameters are kept as default.&lt;br /&gt;
&lt;br /&gt;
This will return the collider of the GameObject underneath the player, which is one square tile.&lt;br /&gt;
&lt;br /&gt;
We extract the tile's position from '''''this.hit''''':&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.hit.transform.gameobject.transform.position.x / y&lt;br /&gt;
|}&lt;br /&gt;
And we trigger the server, with the command &amp;quot;bomb&amp;quot; and the coordinates, to place a bomb NPC;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!triggerserver(&amp;quot;gui&amp;quot;, this.name, &amp;quot;bomb&amp;quot;, this.hit.transform.gameobject.transform.position.x, this.hit.transform.gameobject.transform.position.z);&lt;br /&gt;
|}&lt;br /&gt;
 function onActionServerside(cmd, x, y) {&lt;br /&gt;
   if (cmd == &amp;quot;bomb&amp;quot;) {&lt;br /&gt;
     temp.pnpc = putnpc2(x, y, &amp;quot;&amp;quot;);&lt;br /&gt;
     temp.pnpc.join(&amp;quot;merlin_bomberman_bomb&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
   if (cmd == &amp;quot;level&amp;quot;) {&lt;br /&gt;
      temp.bombernpc = putnpc2(x, y, &amp;quot;&amp;quot;);&lt;br /&gt;
      temp.bombernpc.join(&amp;quot;merlin_bomberman_level&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
Now, on to the classes!&lt;br /&gt;
&lt;br /&gt;
'''&amp;quot;3d_samples_bomberman_level&amp;quot; Class:'''&lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   //Set a 10 minute timer to automatically destroy the levelprefab&lt;br /&gt;
   scheduleEvent(120, &amp;quot;DestLvl&amp;quot;);  &lt;br /&gt;
 }&lt;br /&gt;
 //Destroy if the server restarts&lt;br /&gt;
 &lt;br /&gt;
 function onInitialized() {&lt;br /&gt;
   this.destroy();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;dest&amp;quot;) onDestLvl();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onDestLvl() {&lt;br /&gt;
   this.destroy();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   Quattro::AssetManagement::LoadAssetBundle(&amp;quot;bombermanlevel1&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onAssetBundleDownloaded(bundlename){&lt;br /&gt;
   if (bundlename == &amp;quot;bombermanlevel1&amp;quot;) {&lt;br /&gt;
     player.chat = &amp;quot;bombermanlevel loaded&amp;quot;;&lt;br /&gt;
     temp.prefab = GameObject::fromassetbundle(&amp;quot;bombermanlevel1&amp;quot;, &amp;quot;assets/bombermantest/big level 2.prefab&amp;quot;);&lt;br /&gt;
     this.bomberlevel = Object::Instantiate(Type::GameObject, temp.prefab, this.gameobject.transform, false);&lt;br /&gt;
     this.bomberlevel.transform.parent = this.gameobject.transform;&lt;br /&gt;
     this.bomberlevel.transform.localposition = v3(-15,0,0);&lt;br /&gt;
     this.bomberlevel.transform.localscale = v3(1,1,1);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;dest&amp;quot;) Object::Destroy(this.gameobject);&lt;br /&gt;
 }&lt;br /&gt;
Here we place the level GameObject in an NPC ([[Placing GameObjects in NPC]]) and we only load and instantiate the level the usual way ([[Uploading and Loading AssetBundles]]).&lt;br /&gt;
&lt;br /&gt;
'''&amp;quot;3d_samples_bomberman_bomb&amp;quot; Class:'''&lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   //echo(&amp;quot;merlin_testbomb&amp;quot;);&lt;br /&gt;
   scheduleEvent(3600, &amp;quot;RemoveBomb&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //Destroy if the server restarts&lt;br /&gt;
 function onInitialized() {&lt;br /&gt;
   this.destroy();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;/destroy&amp;quot;) {&lt;br /&gt;
     onRemoveBomb();&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onRemoveBomb() {&lt;br /&gt;
   this.destroy();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   this.dropped = false;&lt;br /&gt;
   this.powerup = randomstring({&amp;quot;bomb&amp;quot;, &amp;quot;explosion&amp;quot;, &amp;quot;speed&amp;quot;});&lt;br /&gt;
   &lt;br /&gt;
   DropBomb();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function DropBomb() {&lt;br /&gt;
   if (level.numberofbombs == 0) return;&lt;br /&gt;
   --level.numberofbombs;&lt;br /&gt;
   &lt;br /&gt;
   Quattro::AssetManagement::LoadAssetBundle(&amp;quot;bombermanprefabs&amp;quot;);&lt;br /&gt;
   Quattro::AssetManagement::LoadAssetBundle(&amp;quot;staffstick&amp;quot;);&lt;br /&gt;
   this.speedprefab = GameObject::fromassetbundle(&amp;quot;staffstick&amp;quot;,&amp;quot;assets/johntest/staffstick_era.prefab&amp;quot;);&lt;br /&gt;
   this.explosionprefab = GameObject::fromassetbundle(&amp;quot;bombermanprefabs&amp;quot;, &amp;quot;assets/bomberman/prefabs/explosion.prefab&amp;quot;);&lt;br /&gt;
   this.prefab = GameObject::fromassetbundle(&amp;quot;bombermanprefabs&amp;quot;, &amp;quot;assets/bomberman/prefabs/bomb.prefab&amp;quot;);&lt;br /&gt;
   this.bomb = Object::instantiate(Type::GameObject, this.prefab, this.gameobject.transform, false);&lt;br /&gt;
   this.bomb.transform.parent = this.gameobject.transform;&lt;br /&gt;
   this.bomb.transform.localeulerangles = v3(0, 0, 0);&lt;br /&gt;
   this.bomb.transform.localposition = v3(0, 0.5, 0);&lt;br /&gt;
 &lt;br /&gt;
   scheduleEvent(3, &amp;quot;Explode&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onExplode() {&lt;br /&gt;
   echo(&amp;quot;onexplode&amp;quot;);&lt;br /&gt;
   &lt;br /&gt;
   echo (&amp;quot;prefab type=&amp;quot; @ this.explosionprefab.objecttype());&lt;br /&gt;
   this.explosion = Object::instantiate(Type::GameObject, this.explosionprefab, this.gameobject.transform, false);&lt;br /&gt;
   echo (&amp;quot;explosion type=&amp;quot; @ this.explosion.objecttype());&lt;br /&gt;
   this.explosion.transform.parent = this.gameobject.transform;&lt;br /&gt;
   this.explosion.transform.localposition = v3(0, 0, 0);&lt;br /&gt;
   this.explosion.transform.localscale = v3(1,1,1);&lt;br /&gt;
   &lt;br /&gt;
   Object::Destroy(this.bomb, .3f);&lt;br /&gt;
   &lt;br /&gt;
   this.exploded = true;&lt;br /&gt;
 &lt;br /&gt;
   CreateExplosion(Vector3::forward);&lt;br /&gt;
   CreateExplosion(Vector3::right);&lt;br /&gt;
   CreateExplosion(Vector3::back);&lt;br /&gt;
   CreateExplosion(Vector3::left);&lt;br /&gt;
   &lt;br /&gt;
   ++level.numberofbombs;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function CreateExplosion(direction) {&lt;br /&gt;
   for (temp.i = 1; temp.i &amp;lt; level.explosionpower; temp.i++) {&lt;br /&gt;
     this.hit = RaycastHit::create();&lt;br /&gt;
     done = Physics::Raycast(this.bomb.transform.position.Add(v3(0,0.5,0)), direction, this.hit, temp.i);&lt;br /&gt;
      &lt;br /&gt;
     if (!done || this.hit.transform.gameobject.name.starts(&amp;quot;assets/bomberman/prefabs/explosion.prefab&amp;quot;) || this.hit.transform.gameobject.name.starts(&amp;quot;TPlayer&amp;quot;)){&lt;br /&gt;
       temp.explosion = Object::instantiate(Type::GameObject, this.explosionprefab, this.gameobject.transform, false);&lt;br /&gt;
       temp.explosion.transform.localposition = v3(0,0,0).Add(direction.Mult(temp.i));&lt;br /&gt;
       Object::Destroy(temp.explosion, 0.7);&lt;br /&gt;
     }&lt;br /&gt;
     if (this.hit.transform.gameobject.name.starts(&amp;quot;E_Bomber_Pilar_01_&amp;quot;)|| this.hit.transform.gameobject.transform.parent.gameobject.name.starts(&amp;quot;E_Bomber_Pilar_01_&amp;quot;)) {&lt;br /&gt;
       if (!this.dropped) {&lt;br /&gt;
         if (rand(0,1) &amp;lt; 0.2) {&lt;br /&gt;
           this.dropped = true;&lt;br /&gt;
           //drop power up&lt;br /&gt;
           droppowerup(this.hit.transform.gameobject.transform.position.x, this.hit.transform.gameobject.transform.position.z);&lt;br /&gt;
         }&lt;br /&gt;
       }&lt;br /&gt;
       Object::Destroy(this.hit.transform.gameobject.transform.parent.gameobject);&lt;br /&gt;
       Object::Destroy(this.hit.transform.gameobject);&lt;br /&gt;
       Object::Destroy(temp.explosion, 0.7);&lt;br /&gt;
       temp.explosion = Object::instantiate(Type::GameObject, this.explosionprefab, this.gameobject.transform, false);&lt;br /&gt;
       temp.explosion.transform.position = this.hit.transform.position;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function droppowerup(x,z) {&lt;br /&gt;
   if (this.powerup == &amp;quot;bomb&amp;quot;) {&lt;br /&gt;
     this.powerupGO = Object::instantiate(Type::GameObject, this.prefab, this.gameobject.transform, false);&lt;br /&gt;
   }&lt;br /&gt;
   if (this.powerup == &amp;quot;explosion&amp;quot;) {&lt;br /&gt;
     this.powerupGO = Object::instantiate(Type::GameObject, this.explosionprefab, this.gameobject.transform, false);&lt;br /&gt;
   }&lt;br /&gt;
   if (this.powerup == &amp;quot;speed&amp;quot;) {&lt;br /&gt;
     this.powerupGO = Object::instantiate(Type::GameObject, this.speedprefab, this.gameobject.transform, false);&lt;br /&gt;
   }&lt;br /&gt;
   this.powerupGO.transform.position = v3(x, 0.5, z);&lt;br /&gt;
   this.powerupGO.transform.scale = v3(0.5,0.5,0.5);&lt;br /&gt;
 &lt;br /&gt;
   sphereCollider = this.powerupGO.AddComponent(Type::SphereCollider);&lt;br /&gt;
   sphereCollider.size = v3(1, 10, 1);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function onActionGrab() {&lt;br /&gt;
   player.chat = this.powerup;&lt;br /&gt;
   Object::Destroy(this.gameobject);&lt;br /&gt;
   if (this.powerup == &amp;quot;bomb&amp;quot;) {&lt;br /&gt;
     ++level.numberofbombs;&lt;br /&gt;
   }&lt;br /&gt;
   if (this.powerup == &amp;quot;explosion&amp;quot;) {&lt;br /&gt;
     ++level.explosionpower;&lt;br /&gt;
   }&lt;br /&gt;
   if (this.powerup == &amp;quot;speed&amp;quot;) {&lt;br /&gt;
     PLAYERMOVEMENT.setSpeed(7);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
Again, we are loading and instantiating the prefabs in an NPC.&lt;br /&gt;
&lt;br /&gt;
In '''''function onCreated()''''': &lt;br /&gt;
&lt;br /&gt;
* '''''this.dropped''''' variable is used to allow every bomb to drop only one powerup.&lt;br /&gt;
* '''''this.powerup''''' variable is the name of the powerup, chosen randomly each time a bomb is dropped.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''''DropBomb()''''' is responsible for loading, instantiating and placing the bomb. The player can drop 2 bombs at a time at the start of the game. Therefore, we begin by checking if the player can drop bombs. We decrease the variable '''''level.numberofbombs''''' when a bomb is dropped and decrease it when the bomb explodes.&lt;br /&gt;
&lt;br /&gt;
After positioning the bomb, we schedule event to create the explosion after 3 seconds of placing the bomb;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!scheduleEvent(3, &amp;quot;Explode&amp;quot;);&lt;br /&gt;
|}&lt;br /&gt;
'''''onExplode()''''' function instantiates an explosion under the bomb; &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.explosion.transform.localposition = v3(0, 0, 0);&lt;br /&gt;
|}&lt;br /&gt;
and calls '''''CreateExplosion(direction);''''' in all the four directions (forward, right, left, back) to instantiate explosions in a cross shape around the bomb.&lt;br /&gt;
&lt;br /&gt;
'''''CreateExplosion(direction)''''' casts a Ray in all the four directions with the given length ('''level.explosionpower'''; the number of tiles it covers) and the bomb as the origin. &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.bomb.transform.position.Add(v3(0,0.5,0));&lt;br /&gt;
|}we add a '''''Vector3 (0, 0.5, 0)''''' to increase the Y of the '''RayCast''' for it to hit the  grey pillars and not the ground.&lt;br /&gt;
&lt;br /&gt;
The two conditional blocks after are used to check if the collider hit by the raycast is a pillar or not. &lt;br /&gt;
&lt;br /&gt;
if it's a Grey Pillar, we destroy it. If not then it's empty space and we instantiate an explosion.&lt;br /&gt;
&lt;br /&gt;
When a Pillar is destroyed, there's a 20% chance it will drop a powerup, by calling the function '''''droppowerup(x,z)''''' with (x,z) the coordinates of the Pillar. &lt;br /&gt;
&lt;br /&gt;
'''''droppowerup(x,z)''''' will check '''''this.powerup''''' and create and place the appropriate GameObject. It also adds a collider Component to be triggered onActionGrab;  &lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: onActionGrab for NPCs:&amp;lt;/u&amp;gt; ====&lt;br /&gt;
For this to work, the GameObject is required to have a collider.&lt;br /&gt;
&lt;br /&gt;
And '''''public function onActionGrab()''''' needs to be implemented.&lt;br /&gt;
&lt;br /&gt;
Here, we destroy the powerup GameObject and give the player the powerup.&lt;br /&gt;
&lt;br /&gt;
(''weapon: '''3D/Player/Grab''''' for more info)&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Plane_MiniGame&amp;diff=20926</id>
		<title>Plane MiniGame</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Plane_MiniGame&amp;diff=20926"/>
		<updated>2021-09-02T17:41:40Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This minigame is similar to the Car driving minigame. However, we move a plane through obstacles.&lt;br /&gt;
&lt;br /&gt;
'''AssetBundles:''' ''minigameplane - env''&lt;br /&gt;
&lt;br /&gt;
using the bundle explorer (F10):&lt;br /&gt;
&lt;br /&gt;
'''minigameplane:'''&lt;br /&gt;
&lt;br /&gt;
[[File:Plane.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
[[File:Obstacles.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
'''env:'''&lt;br /&gt;
&lt;br /&gt;
[[File:Environment.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
Weapon: '''''3D/Samples/Planeminigame'''''&lt;br /&gt;
 findplayer(&amp;quot;Graal5918039&amp;quot;).addweapon(this.name);&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 &lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   this.keepAlive = true;//SetTimer(9999);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;plane&amp;quot;) start();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function start() {&lt;br /&gt;
   WARPMANAGER.Warp(19, 14 ,0.7 ,&amp;quot;only_ground.nw&amp;quot;);&lt;br /&gt;
   new GuiWindowCtrl(&amp;quot;PlaneMinigame&amp;quot;) {&lt;br /&gt;
     profile = GuiBlueWindowProfile;&lt;br /&gt;
     x = 120;&lt;br /&gt;
     y = 0;&lt;br /&gt;
     width = 670;&lt;br /&gt;
     height = 340;&lt;br /&gt;
     text = &amp;quot;Plane Minigame&amp;quot;;&lt;br /&gt;
     &lt;br /&gt;
     new GuiButtonCtrl(&amp;quot;Plane&amp;quot;) {&lt;br /&gt;
       profile = GuiBlueButtonProfile;&lt;br /&gt;
       x = 150;&lt;br /&gt;
       y = 90;&lt;br /&gt;
       width = 150;&lt;br /&gt;
       height = 30;&lt;br /&gt;
       text = &amp;quot;Spawnplane&amp;quot;;&lt;br /&gt;
     }&lt;br /&gt;
       new GuiButtonCtrl(&amp;quot;Exit&amp;quot;) {&lt;br /&gt;
       profile = GuiBlueButtonProfile;&lt;br /&gt;
       x = 150;&lt;br /&gt;
       y = 120;&lt;br /&gt;
       width = 150;&lt;br /&gt;
       height = 30;&lt;br /&gt;
       text = &amp;quot;Exit&amp;quot;;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function Plane.onAction() {&lt;br /&gt;
   exit();&lt;br /&gt;
   PLAYERMOVEMENT.Freeze();&lt;br /&gt;
   //Quattro3D::PlayerCamera::Instance.FreeCam = true;&lt;br /&gt;
   CAMERAMANGER.freecam = true;&lt;br /&gt;
   this.empty = GameObject::Create(&amp;quot;empty&amp;quot;);&lt;br /&gt;
   Quattro3D::PlayerCamera::Instance.transform.rotation = Quaternion::euler(0, -90, 0);&lt;br /&gt;
   Quattro::AssetManagement::LoadAssetBundle(&amp;quot;minigameplane&amp;quot;);&lt;br /&gt;
   Quattro::AssetManagement::LoadAssetBundle(&amp;quot;env&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onAssetBundleDownloaded(bundlename) {&lt;br /&gt;
   if (bundlename == &amp;quot;minigameplane&amp;quot;) {&lt;br /&gt;
     this.planeprefab = GameObject::fromassetbundle(&amp;quot;minigameplane&amp;quot;, &amp;quot;assets/drivingplane/vehicles/planes/small_plane02.prefab&amp;quot;);&lt;br /&gt;
     this.plane = Object::Instantiate(Type::GameObject, this.planeprefab);&lt;br /&gt;
     this.plane.transform.position = v3(player.x, player.z, player.y);&lt;br /&gt;
     this.plane.transform.localscale = v3(0.3, 0.3, 0.3);&lt;br /&gt;
     this.plane.transform.parent = this.empty.transform;&lt;br /&gt;
     &lt;br /&gt;
     this.RB = this.plane.AddComponent(Type::RigidBody);&lt;br /&gt;
     this.RB.useGravity = false;&lt;br /&gt;
     &lt;br /&gt;
     boxCollider = this.plane.AddComponent(Type::BoxCollider);&lt;br /&gt;
     boxCollider.size = v3(4,4,4);&lt;br /&gt;
 &lt;br /&gt;
     Quattro::EventManager::AddOnCollisionHandlerTo(this.plane, this.plane.layer);&lt;br /&gt;
     this.catcheventobject(this.plane, &amp;quot;onCollisionEnter&amp;quot;, &amp;quot;onPlaneCollisionEnter&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     this.obstacleprefab = GameObject::fromassetbundle(&amp;quot;minigameplane&amp;quot;, &amp;quot;assets/drivingplane/vehicles/planes/obstacles 1.prefab&amp;quot;);&lt;br /&gt;
     this.obstacle = Object::Instantiate(Type::GameObject, this.obstacleprefab);&lt;br /&gt;
     this.obstacle.transform.position = v3(player.x, player.z + 10, player.y + 20);&lt;br /&gt;
     this.obstacle.transform.localscale = v3(0.3, 0.3, 0.3);&lt;br /&gt;
     this.obstacle.transform.parent = this.empty.transform;&lt;br /&gt;
   }&lt;br /&gt;
   if (bundlename == &amp;quot;env&amp;quot;) {&lt;br /&gt;
     this.envprefab = GameObject::fromassetbundle(&amp;quot;env&amp;quot;, &amp;quot;assets/jimmyenv2/environment.prefab&amp;quot;);&lt;br /&gt;
     this.env = Object::Instantiate(Type::GameObject, this.envprefab);&lt;br /&gt;
     this.env.transform.position = v3(player.x, player.z + 1.5, player.y);&lt;br /&gt;
     this.env.transform.parent = this.empty.transform; &lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onUpdate() {&lt;br /&gt;
   temp.campos = this.plane.transform.position.Add(v3(20,0,0));&lt;br /&gt;
   Quattro3D::PlayerCamera::Instance.transform.position = temp.campos;&lt;br /&gt;
   &lt;br /&gt;
   this.verticalInput = Input::GetAxis(&amp;quot;Vertical&amp;quot;);&lt;br /&gt;
   this.horizontalInput = Input::GetAxis(&amp;quot;Horizontal&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
   this.plane.transform.translate(Vector3::forward.Mult(Time::deltaTime * 5));&lt;br /&gt;
 &lt;br /&gt;
   this.plane.transform.rotate(Vector3::Right.Mult(700 * Time::deltaTime * this.verticalInput));&lt;br /&gt;
 &lt;br /&gt;
   this.plane.transform.rotate(Vector3::Forward.Mult(700 * Time::deltaTime * this.horizontalInput * -1));&lt;br /&gt;
 &lt;br /&gt;
   this.propellor = this.plane.transform.Find(&amp;quot;Propellor&amp;quot;);&lt;br /&gt;
   this.propellor.transform.rotate(Vector3::Forward.Mult(1700 * Time::deltaTime)); &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function onPlaneCollisionEnter(gameobject, collision) {&lt;br /&gt;
   player.chat = &amp;quot;BOOM YOU LOST!&amp;quot;;&lt;br /&gt;
   exit();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function Exit.onAction() {&lt;br /&gt;
   exit(); &lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function exit() {&lt;br /&gt;
   findweapon(&amp;quot;3D/Dev/ToolBar/Camera&amp;quot;).cam1();&lt;br /&gt;
   PLAYERMOVEMENT.unfreeze();&lt;br /&gt;
   Object::Destroy(this.empty);&lt;br /&gt;
   Input::ResetInputAxes();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
The function '''''start()''''' creates a UI with two buttons (Spawn Plane and Exit) allowing us to start and end the game.&lt;br /&gt;
&lt;br /&gt;
'''Plane.onAction()''' ''(when the Spawn button is pressed) :'' &lt;br /&gt;
&lt;br /&gt;
Calls the '''''exit()''''' function first to destroy GameObjects instantiated before, freezes the player using '''PLAYERMOVEMENT.Freeze();''' ,frees the camera with '''Quattro3D::PlayerCamera::Instance.FreeCam = true;''' and loads all the assets we'll need to use.&lt;br /&gt;
&lt;br /&gt;
In function '''''onAssetBundleDownloaded(bundlename)''''' we catch all the loaded assetbundles, we instantiate the plane, obstacles and environment. And we position them, modify their scales, add components to them and make them a child of an empty GameObject.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.empty = GameObject::Create(&amp;quot;empty&amp;quot;);&lt;br /&gt;
|}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.obstacle.transform.parent = this.empty.transform;&lt;br /&gt;
|}&lt;br /&gt;
This will help delete all the GameObjects upon deleting the empty GameObject. ('''Object::Destroy(this.empty);''')&lt;br /&gt;
&lt;br /&gt;
Now, the '''''onUpdate()''''' function checks for updates on every frame. '''''SetTimer(9999)''''' needs to be added for it to work.&lt;br /&gt;
&lt;br /&gt;
This function will be responsible for moving the plane, moving the camera following the plane and turning the propeller of the plane.&lt;br /&gt;
&lt;br /&gt;
First for the Camera, we want it to be looking side ways at the plane. We take the plane's position and add to the X axis:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!temp.campos = this.plane.transform.position.Add(v3(20,0,0));&lt;br /&gt;
|}&lt;br /&gt;
then we change the camera position to '''''temp.campos;'''''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Quattro3D::PlayerCamera::Instance.transform.position = temp.campos;&lt;br /&gt;
|}&lt;br /&gt;
We'll also need to change the rotation of the camera since it's initially facing forward and we want it to face the plane;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Quattro3D::PlayerCamera::Instance.transform.rotation = Quaternion::euler(0, -90, 0);&lt;br /&gt;
|}&lt;br /&gt;
Now, for the movement of the plane. It will be moving forward at a constant speed; '''''this.plane.transform.translate(Vector3::forward.Mult(Time::deltaTime * 5));'''''&lt;br /&gt;
&lt;br /&gt;
And the '''''Input::GetAxis()''''' will help us move it up/down and sideways.&lt;br /&gt;
&lt;br /&gt;
We also find the propellor of the plane and move it at a constant rotation speed;&lt;br /&gt;
&lt;br /&gt;
'''''this.propellor = this.plane.transform.Find(&amp;quot;Propellor&amp;quot;);'''''&lt;br /&gt;
&lt;br /&gt;
'''''this.propellor.transform.rotate(Vector3::Forward.Mult(1700 * Time::deltaTime));''''' &lt;br /&gt;
&lt;br /&gt;
Finally, the function '''''exit()''''' switches back to the default camera: '''''findweapon(&amp;quot;3D/Dev/ToolBar/Camera&amp;quot;).cam1();'''''&lt;br /&gt;
&lt;br /&gt;
unfreezes the Player, destroys the GameObjects and resets the Input Axes using: '''''Input::ResetInputAxes();'''''&lt;br /&gt;
[[File:Planeminigame gameplay.png|center|thumb|1108x1108px]]You can also add collision detection to the plane to turn it into an actual game.&lt;br /&gt;
 Quattro::EventManager::AddOnCollisionHandlerTo(this.plane, this.plane.layer);&lt;br /&gt;
 this.catcheventobject(this.plane, &amp;quot;onCollisionEnter&amp;quot;, &amp;quot;onPlaneCollisionEnter&amp;quot;);&lt;br /&gt;
and implement the function:&lt;br /&gt;
 public function onPlaneCollisionEnter(gameobject, collision) {&lt;br /&gt;
   player.chat = &amp;quot;BOOM YOU LOST!&amp;quot;;&lt;br /&gt;
   exit();&lt;br /&gt;
 }&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Driving_MiniGame&amp;diff=20925</id>
		<title>Driving MiniGame</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Driving_MiniGame&amp;diff=20925"/>
		<updated>2021-09-02T17:39:51Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the Driving MiniGame tutorial.&lt;br /&gt;
&lt;br /&gt;
= Intro =&lt;br /&gt;
&lt;br /&gt;
==== DrivingMiniGame ====&lt;br /&gt;
This is a simple and easy car driving example. In the assetbundle, there's an environment that we load and instantiate and multiple cars that we can spawn. This game is not focused on the actual driving experience itself, but more on introducing new Unity functionalities.&lt;br /&gt;
&lt;br /&gt;
'''Asset Bundles: ''minigame2, env'''''&lt;br /&gt;
&lt;br /&gt;
using the bundle explorer (F10):&lt;br /&gt;
&lt;br /&gt;
'''minigame2:'''&lt;br /&gt;
&lt;br /&gt;
[[File:Minigame2.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
'''env:'''&lt;br /&gt;
&lt;br /&gt;
[[File:Minigame2 env.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
Weapon: '''''3D/Samples/Drivingminigame'''''&lt;br /&gt;
 findplayer(&amp;quot;GraalID&amp;quot;).addweapon(this.name);&lt;br /&gt;
 this.join(&amp;quot;3d_merlin_camera&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;dest&amp;quot;) dest();&lt;br /&gt;
   if (player.chat == &amp;quot;drive&amp;quot;) drive();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function drive() {&lt;br /&gt;
   destLevelName = &amp;quot;only_ground.nw&amp;quot;;&lt;br /&gt;
   x = 19;&lt;br /&gt;
   y = 10;&lt;br /&gt;
   z = 0.7;//0.7;&lt;br /&gt;
   WARPMANAGER.Warp(x, y ,z ,destLevelName);&lt;br /&gt;
 &lt;br /&gt;
   sleep(1);&lt;br /&gt;
  &lt;br /&gt;
   new GuiWindowCtrl(&amp;quot;MyGUI_Minigame_Window1&amp;quot;) {&lt;br /&gt;
     profile = GuiBlueWindowProfile;&lt;br /&gt;
     style = $pref::Video::defaultguistyle;&lt;br /&gt;
     clientrelative = true;&lt;br /&gt;
     clientextent = &amp;quot;320,240&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
     canmove = true;&lt;br /&gt;
     canresize = true;&lt;br /&gt;
     closequery = false;&lt;br /&gt;
     destroyonhide = false;&lt;br /&gt;
     text = &amp;quot;Window 1&amp;quot;;&lt;br /&gt;
     x = 490;&lt;br /&gt;
     y = 242;&lt;br /&gt;
 &lt;br /&gt;
     new GuiButtonCtrl(&amp;quot;MyGUI_Minigame_Button1&amp;quot;) {&lt;br /&gt;
       profile = GuiBlueButtonProfile;&lt;br /&gt;
       text = &amp;quot;Car&amp;quot;;&lt;br /&gt;
       width = 80;&lt;br /&gt;
       x = 77;&lt;br /&gt;
       y = 31;&lt;br /&gt;
     }&lt;br /&gt;
     new GuiButtonCtrl(&amp;quot;MyGUI_Minigame_Button2&amp;quot;) {&lt;br /&gt;
       profile = GuiBlueButtonProfile;&lt;br /&gt;
       height = 31;&lt;br /&gt;
       text = &amp;quot;Bus&amp;quot;;&lt;br /&gt;
       width = 80;&lt;br /&gt;
       x = 77;&lt;br /&gt;
       y = 69;&lt;br /&gt;
     }&lt;br /&gt;
     new GuiButtonCtrl(&amp;quot;MyGUI_Minigame_Button3&amp;quot;) {&lt;br /&gt;
       profile = GuiBlueButtonProfile;&lt;br /&gt;
       height = 31;&lt;br /&gt;
       text = &amp;quot;Quit&amp;quot;;&lt;br /&gt;
       width = 80;&lt;br /&gt;
       x = 78;&lt;br /&gt;
       y = 109;&lt;br /&gt;
     }&lt;br /&gt;
     new GuiTextCtrl(&amp;quot;MyGUI_Minigame_Text1&amp;quot;) {&lt;br /&gt;
       profile = GuiBlueTextProfile;&lt;br /&gt;
       height = 20;&lt;br /&gt;
       text = &amp;quot;Select Type:&amp;quot;;&lt;br /&gt;
       width = 71;&lt;br /&gt;
       x = 11;&lt;br /&gt;
       y = 5;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function MyGUI_Minigame_Button1.onAction() {&lt;br /&gt;
   // Button &amp;quot;Car&amp;quot; has been pressed&lt;br /&gt;
   Quattro::AssetManagement::LoadAssetBundle(&amp;quot;minigame2&amp;quot;);&lt;br /&gt;
   Quattro::AssetManagement::LoadAssetBundle(&amp;quot;env&amp;quot;);&lt;br /&gt;
   this.vehicle = &amp;quot;car&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function MyGUI_Minigame_Button2.onAction() {&lt;br /&gt;
   // Button &amp;quot;Bus&amp;quot; has been pressed&lt;br /&gt;
   Quattro::AssetManagement::LoadAssetBundle(&amp;quot;minigame2&amp;quot;);&lt;br /&gt;
   Quattro::AssetManagement::LoadAssetBundle(&amp;quot;env&amp;quot;);&lt;br /&gt;
   this.vehicle = &amp;quot;bus&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function MyGUI_Minigame_Button3.onAction() {&lt;br /&gt;
   dest();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onAssetBundleDownloaded(bundlename) {&lt;br /&gt;
   if (bundlename == &amp;quot;env&amp;quot;) {&lt;br /&gt;
     this.env = GameObject::fromassetbundle(&amp;quot;env&amp;quot;, &amp;quot;assets/jimmyenv2/Environment.prefab&amp;quot;);&lt;br /&gt;
     this.env = Object::Instantiate(Type::GameObject, this.env);&lt;br /&gt;
     this.env.transform.position = v3(player.x, player.z, player.y);&lt;br /&gt;
   }&lt;br /&gt;
   if (bundlename == &amp;quot;minigame2&amp;quot;) {&lt;br /&gt;
     if (this.vehicle == &amp;quot;bus&amp;quot;) {&lt;br /&gt;
       dest();&lt;br /&gt;
       this.vh = GameObject::fromassetbundle(&amp;quot;minigame2&amp;quot;, &amp;quot;assets/jimmyminigame2/Veh_Bus_Blue_Z.prefab&amp;quot;);&lt;br /&gt;
     }&lt;br /&gt;
     &lt;br /&gt;
     if (this.vehicle == &amp;quot;car&amp;quot;) {&lt;br /&gt;
       dest();&lt;br /&gt;
       this.vh = GameObject::fromassetbundle(&amp;quot;minigame2&amp;quot;, &amp;quot;assets/jimmyminigame2/Veh_Car_Blue_Z.prefab&amp;quot;);&lt;br /&gt;
     }&lt;br /&gt;
     &lt;br /&gt;
     this.vh = Object::Instantiate(Type::GameObject, this.vh);&lt;br /&gt;
     this.vh.transform.position = v3(player.x - 2, player.z, player.y - 5);&lt;br /&gt;
     this.vh.AddComponent(Type::RigidBody);&lt;br /&gt;
 &lt;br /&gt;
     PLAYERMOVEMENT.Freeze();&lt;br /&gt;
     //Quattro3D::PlayerCamera::Instance.FreeCam = true;&lt;br /&gt;
     CAMERAMANAGER.freecam = true;&lt;br /&gt;
     handleMovement();&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function handleMovement() {&lt;br /&gt;
   this.on = true;&lt;br /&gt;
   SetTimer(0.05);&lt;br /&gt;
   this.speed = 20;&lt;br /&gt;
   this.rotation = 400;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onFixedUpdate() {&lt;br /&gt;
   this.vInput = Input::GetAxis(&amp;quot;Vertical&amp;quot;);&lt;br /&gt;
   this.vh.transform.Translate(Vector3::forward.Mult(Time::deltaTime * this.speed * this.vInput));&lt;br /&gt;
     &lt;br /&gt;
   this.hInput = Input::GetAxis(&amp;quot;Horizontal&amp;quot;);&lt;br /&gt;
   this.vh.transform.Rotate(Vector3::up.Mult(Time::deltaTime * this.rotation * this.hInput * this.vInput));&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onTimeOut() {&lt;br /&gt;
   if(this.on) {&lt;br /&gt;
     temp.campos = this.vh.transform.position.Add(v3(0,10,-7));&lt;br /&gt;
     Quattro3D::PlayerCamera::Instance.transform.position = temp.campos;&lt;br /&gt;
     &lt;br /&gt;
     //this.vInput = Input::GetAxis(&amp;quot;Vertical&amp;quot;);&lt;br /&gt;
     &lt;br /&gt;
     //this.hInput = Input::GetAxis(&amp;quot;Horizontal&amp;quot;);&lt;br /&gt;
     //if (this.vInput &amp;lt; 0) this.hInput = - Input::GetAxis(&amp;quot;Horizontal&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     //this.vh.transform.Translate(Vector3::forward.Mult(Time::deltaTime * this.speed * this.vInput));&lt;br /&gt;
     &lt;br /&gt;
     SetTimer(0.05);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function dest() {&lt;br /&gt;
   this.on = false;&lt;br /&gt;
   findweapon(&amp;quot;3D/Dev/ToolBar/Camera&amp;quot;).cam1();&lt;br /&gt;
   PLAYERMOVEMENT.unfreeze();&lt;br /&gt;
   Object::Destroy(this.vh);&lt;br /&gt;
   Object::Destroy(this.env);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Here we create a UI for the player to choose what vehicle to choose, and we load and instantiate the prefab based on the choice.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Camera&amp;lt;/u&amp;gt; ====&lt;br /&gt;
The Camera is the point of view. Here we want the Camera to follow the car while driving and not the player.&lt;br /&gt;
&lt;br /&gt;
In '''''function onAssetBundleDownloaded(bundlename)''''' We use:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Quattro3D::PlayerCamera::Instance.FreeCam = true;&lt;br /&gt;
|}&lt;br /&gt;
To free the camera. This will free it from following the player GameObject.&lt;br /&gt;
&lt;br /&gt;
Then in '''''function onTimeOut()''''' we want the camera position to be updated with the vehicle's position.&lt;br /&gt;
&lt;br /&gt;
'''''temp.campos''''' is the variable we store the camera's position in. We want it to be behind and above the vehicle for a good view. This is why we get the vehicle's position and add a Vector3 to it:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!temp.campos = this.vh.transform.position.Add(v3(0,10,-7));&lt;br /&gt;
|}&lt;br /&gt;
now:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Quattro3D::PlayerCamera::Instance.transform.position&lt;br /&gt;
|}&lt;br /&gt;
allows us to the get the Camera GameObject and to access its transform component and change its position.&lt;br /&gt;
&lt;br /&gt;
We have implemented default cameras found in Weapon: '''''3D/Dev/ToolBar/Camera'''''&lt;br /&gt;
&lt;br /&gt;
We access them through the Weapon &amp;quot;'''''3D/Dev/ToolBar/Camera'''''&amp;quot; using:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!''findweapon(&amp;quot;3D/Dev/ToolBar/Camera&amp;quot;).cam1();''&lt;br /&gt;
|}and we call the function '''''cam1();''''' in '''''function dest()''''' to go back to the default cam.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Unity Input&amp;lt;/u&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Input::GetAxis(&amp;quot;Vertical&amp;quot;);&lt;br /&gt;
|}&lt;br /&gt;
&amp;quot;Vertical&amp;quot; / &amp;quot;Horizontal&amp;quot;&lt;br /&gt;
&lt;br /&gt;
It checks the arrows pressed and gives a value in the range of (-1 to 1) -1 indicating &amp;quot;down&amp;quot;, 1 &amp;quot;up&amp;quot; and 0 &amp;quot;neutral&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
We use it here to translate and rotate the vehicle.&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Turret_MiniGame&amp;diff=20924</id>
		<title>Turret MiniGame</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Turret_MiniGame&amp;diff=20924"/>
		<updated>2021-09-02T17:35:12Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the Turret Minigame!&lt;br /&gt;
&lt;br /&gt;
In this Tutorial, we will build a turret that rotates and shoots targets around it. The Assets are available on the server. &lt;br /&gt;
&lt;br /&gt;
==== TurretMiniGame GameObjects ====&lt;br /&gt;
All the prefabs are under the asset bundle: '''minigame''' (you can view them in the bundle explorer &amp;quot;F10&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Turret that shoots the projectiles:&lt;br /&gt;
&lt;br /&gt;
[[File:Turret.png|frameless|407x407px]]&lt;br /&gt;
&lt;br /&gt;
Robot that will serve as a target:&lt;br /&gt;
&lt;br /&gt;
[[File:Robot Obstacle Minigame.png|frameless|407x407px]]&lt;br /&gt;
&lt;br /&gt;
Cubes Instantiated in different position also for targets:&lt;br /&gt;
&lt;br /&gt;
[[File:Turret Minigame targets.png|frameless|405x405px]]&lt;br /&gt;
&lt;br /&gt;
 findplayer(&amp;quot;GraalID&amp;quot;).addweapon(this.name);&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;start&amp;quot;) {&lt;br /&gt;
     destroy();&lt;br /&gt;
     start();&lt;br /&gt;
   }&lt;br /&gt;
   if (player.chat == &amp;quot;dest&amp;quot;) destroy();&lt;br /&gt;
 }&lt;br /&gt;
The way I start the minigame is '''onPlayerChats'''; when the player says &amp;quot;start&amp;quot;. We'll also see how to '''destroy the GameObjects''' when the player says &amp;quot;dest&amp;quot;.&lt;br /&gt;
 function start() {&lt;br /&gt;
   this.start = true;&lt;br /&gt;
   //PLAYERMOVEMENT.Freeze();&lt;br /&gt;
   &lt;br /&gt;
   //for turret control&lt;br /&gt;
   this.rotateangle = 0; //Rotation angle of the turret&lt;br /&gt;
   this.rotateangleB = 270; //Rotation angle of the barrel&lt;br /&gt;
   this.speed = 15;&lt;br /&gt;
   &lt;br /&gt;
   this.currentX = player.x;&lt;br /&gt;
   this.currentY = player.y;&lt;br /&gt;
   this.currentZ = player.z;&lt;br /&gt;
   echo (&amp;quot;TurretMiniGame warp from=&amp;quot; @ this.currentLevel @ &amp;quot; x=&amp;quot; @ this.currentX @ &amp;quot; y=&amp;quot; @ this.currentY @ &amp;quot; z=&amp;quot; @ this.currentZ);&lt;br /&gt;
   WARPMANAGER.Warp(19, 14 ,0.7 ,&amp;quot;only_ground.nw&amp;quot;);&lt;br /&gt;
   sleep(1.5);&lt;br /&gt;
 &lt;br /&gt;
   Quattro::AssetManagement::LoadAssetBundle(&amp;quot;minigame&amp;quot;); //loading the assetbundle&lt;br /&gt;
 }&lt;br /&gt;
'''''this.start = true;''''' will be used to indicate that the game has started.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Using PLAYERMOVEMENT and WARPMANAGER&amp;lt;/u&amp;gt; ====&lt;br /&gt;
'''PLAYERMOVEMENT.Freeze()''' is a method that freezes the player (weapon: '''3D/Player/Core/Movement)''' &lt;br /&gt;
&lt;br /&gt;
'''WARPMANAGER.Warp(x,y,z,level)''' (weapon: '''3D/Player/Core/Warp/Manager''')&lt;br /&gt;
&lt;br /&gt;
Having uploaded the Asset bundle called &amp;quot;'''minigame'''&amp;quot; that contains the prefabs to the server, I start off by loading them, creating the prefabs, instantiating them and giving them a position in the '''start function'''  ([[Uploading and Loading AssetBundles|&amp;lt;u&amp;gt;Uploading and Loading AssetBundles&amp;lt;/u&amp;gt;]] for info on how to upload assets).&lt;br /&gt;
 function onAssetBundleDownloaded(bundlename) {&lt;br /&gt;
   if (bundlename == &amp;quot;minigame&amp;quot;) { &lt;br /&gt;
     SetTimer(9999);&lt;br /&gt;
     this.empty = GameObject::Create(&amp;quot;empty&amp;quot;); // for parenting and deleting&lt;br /&gt;
 &lt;br /&gt;
     this.turret = GameObject::fromassetbundle(&amp;quot;minigame&amp;quot;, &amp;quot;assets/jimmyminigame/turret.prefab&amp;quot;);&lt;br /&gt;
     this.robot1 = GameObject::fromassetbundle(&amp;quot;minigame&amp;quot;, &amp;quot;assets/jimmyminigame/robot.prefab&amp;quot;);&lt;br /&gt;
     this.robot2 = GameObject::fromassetbundle(&amp;quot;minigame&amp;quot;, &amp;quot;assets/jimmyminigame/robot.prefab&amp;quot;);&lt;br /&gt;
     this.wreckedrobotprefab = GameObject::fromassetbundle(&amp;quot;minigame&amp;quot;, &amp;quot;assets/jimmyminigame/robot wrecked.prefab&amp;quot;);&lt;br /&gt;
     this.projectileprefab = GameObject::fromassetbundle(&amp;quot;minigame&amp;quot;, &amp;quot;assets/jimmyminigame/projectile.prefab&amp;quot;);&lt;br /&gt;
     this.explosion = GameObject::fromassetbundle(&amp;quot;minigame&amp;quot;, &amp;quot;assets/jimmyminigame/explosion.prefab&amp;quot;);&lt;br /&gt;
     &lt;br /&gt;
     this.turret = Object::Instantiate(Type::GameObject, this.turret);&lt;br /&gt;
     this.robot1 = Object::Instantiate(Type::GameObject, this.robot1);&lt;br /&gt;
     this.robot2 = Object::Instantiate(Type::GameObject, this.robot2);&lt;br /&gt;
     &lt;br /&gt;
     this.turret.transform.position = v3(player.x, player.z, player.y);&lt;br /&gt;
     this.robot1.transform.position = v3(player.x - 5, player.z - 1, player.y + 10);&lt;br /&gt;
     this.robot2.transform.position = v3(player.x + 5, player.z - 1, player.y + 10);&lt;br /&gt;
     &lt;br /&gt;
     this.turret.transform.localscale = v3(1,1,1);&lt;br /&gt;
     this.robot1.transform.localscale = v3(1,1,1);&lt;br /&gt;
     this.robot2.transform.localscale = v3(1,1,1);&lt;br /&gt;
     &lt;br /&gt;
     loadCubes();&lt;br /&gt;
     &lt;br /&gt;
     player.charactercontroller.enabled = false;&lt;br /&gt;
     player.gameobject.transform.position = v3(player.x, player.z+5, player.y);&lt;br /&gt;
 &lt;br /&gt;
     this.launcher = GameObject::Find(&amp;quot;Launcher&amp;quot;);&lt;br /&gt;
     this.barrel = GameObject::Find(&amp;quot;Barrel&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function loadCubes() {&lt;br /&gt;
   temp.width = 10;&lt;br /&gt;
   temp.height = 4;&lt;br /&gt;
 &lt;br /&gt;
   for (temp.y = 0; temp.y &amp;lt; temp.height; ++temp.y) {&lt;br /&gt;
     for (temp.x = 0; temp.x &amp;lt; temp.width; ++temp.x) {&lt;br /&gt;
       temp.block = GameObject::CreatePrimitive(PrimitiveType::Cube);&lt;br /&gt;
       temp.block.Name = &amp;quot;myblock&amp;quot;;&lt;br /&gt;
       temp.block.transform.parent = this.empty.transform; // for deleting&lt;br /&gt;
       temp.block.transform.position = v3(player.x - 5 + temp.x, player.z + temp.y, player.y + 15);&lt;br /&gt;
       temp.block.AddComponent(Type::RigidBody);&lt;br /&gt;
       temp.block.layer = this.projectile.layer; &lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   temp.nbofobjects = 20;&lt;br /&gt;
   temp.radius = 7f;&lt;br /&gt;
 &lt;br /&gt;
   for (temp.i = 0; temp.i &amp;lt; temp.nbofobjects; ++temp.i) {&lt;br /&gt;
     temp.angle = temp.i * Mathf::PI * 2 / temp.nbofobjects;&lt;br /&gt;
     temp.x1 = cos(temp.angle) * temp.radius;&lt;br /&gt;
     temp.y1 = sin(temp.angle) * temp.radius;&lt;br /&gt;
     this.cube = GameObject::CreatePrimitive(PrimitiveType::Cube);&lt;br /&gt;
     this.cube.transform.parent = this.empty.transform;&lt;br /&gt;
     this.cube.transform.position = v3(player.x + temp.x1, player.z, player.y + temp.y1);&lt;br /&gt;
     this.cube.AddComponent(Type::RigidBody);&lt;br /&gt;
     temp.angleDegrees = -temp.angle * Mathf::Rad2Deg;&lt;br /&gt;
     this.cube.transform.rotation = Quaternion::euler(0, temp.angleDegrees, 0); &lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
In the '''''loadCubes()''''' function we instantiate primitive type cubes and position them to build a wall and a circular formation around the turret.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Moving the Player GameObject&amp;lt;/u&amp;gt; ====&lt;br /&gt;
The player is a GameObject, and its accessed by:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!player.gameobject&lt;br /&gt;
|}&lt;br /&gt;
Before changing the player's transform, the '''''player.charactercontroller''''' must be disabled:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!player.charactercontroller.enabled = false;&lt;br /&gt;
|}&lt;br /&gt;
Then we can change the position accessing the transform component of the GameObject:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!player.gameobject.transform.position = Vector3::Create(player.x, player.z+5, player.y);&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Parenting&amp;lt;/u&amp;gt; ====&lt;br /&gt;
In Unity, parenting is when a GameObject becomes a parent of another GameObject. The child GameObject will perform all it's transform changes in respect to the parent GameObject and not the Camera. Additionally, deleting the parent GameObject will delete all its children.&lt;br /&gt;
&lt;br /&gt;
We use it for the latter. We create the '''Empty GameObject''', which will serve as a parent for the Cubes ''(children)'' in order to delete them all, since we don't have a reference to each and every cube.&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Finding GameObjects by Name&amp;lt;/u&amp;gt; ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!GameObject::Find(&amp;quot;name&amp;quot;)&lt;br /&gt;
|}&lt;br /&gt;
We use it to find the barrel that we'll move up and down and the launcher that shoots the projectiles.&lt;br /&gt;
&lt;br /&gt;
Now to move the Turret;&lt;br /&gt;
 function onKeyPressed(keycode) {&lt;br /&gt;
   if (keycode == &amp;quot;90&amp;quot;) { // Z&lt;br /&gt;
     this.rotateangle -= 4;&lt;br /&gt;
     this.turret.transform.rotation = Quaternion::euler(0, this.rotateangle, 0); &lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   if (keycode == &amp;quot;67&amp;quot;) { // C&lt;br /&gt;
     this.rotateangle += 4;&lt;br /&gt;
     this.turret.transform.rotation = Quaternion::euler(0, this.rotateangle, 0);&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   if (keycode == &amp;quot;87&amp;quot;) { // W&lt;br /&gt;
     this.rotateangleB = this.rotateangleB &amp;lt; 300? this.rotateangleB + 4: 300;&lt;br /&gt;
     this.barrel.transform.LocalRotation = Quaternion::euler(this.rotateangleB, 0, 0);&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   if (keycode == &amp;quot;83&amp;quot;) { // S&lt;br /&gt;
     this.rotateangleB = this.rotateangleB &amp;gt; 258? this.rotateangleB - 4: 258;&lt;br /&gt;
     this.barrel.transform.LocalRotation = Quaternion::euler(this.rotateangleB, 0, 0);&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   if (keycode == &amp;quot;32, ,57&amp;quot;) { // Space&lt;br /&gt;
     if (this.start) {&lt;br /&gt;
       shoot();&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
We rotate the barrel around the X axis for it to go up and down;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Quaternion::euler(this.rotateangleB, 0, 0);&lt;br /&gt;
|}&lt;br /&gt;
And rotate the turret around the Y axis (Vertical axis);&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Quaternion::euler(0, this.rotateangle, 0);&lt;br /&gt;
|}&lt;br /&gt;
this.rotateangle for both cases starts at the initial rotation of the GameObjects and is incremented/decremented based on the direction of the rotation.&lt;br /&gt;
&lt;br /&gt;
In the last conditional block, if space is pressed and if the Game is on ('''''this.start == true'''''), the projectile is shot. Here's how it's done;&lt;br /&gt;
 function shoot() {&lt;br /&gt;
     SetTimer(9999);&lt;br /&gt;
     this.projectile = Object::Instantiate(Type::GameObject, this.projectileprefab);&lt;br /&gt;
     this.projectile.transform.parent = this.empty.transform;&lt;br /&gt;
     this.projectile.transform.position = this.launcher.transform.position;&lt;br /&gt;
     this.projectile.transform.scale = v3(1,1,1);&lt;br /&gt;
 &lt;br /&gt;
     temp.rigidBody = this.projectile.GetComponent(Type::RigidBody); &lt;br /&gt;
     temp.rigidBody.velocity = this.launcher.transform.forward.Mult(this.speed);&lt;br /&gt;
 &lt;br /&gt;
     Quattro::EventManager::AddOnCollisionHandlerTo(this.projectile, this.projectile.layer);&lt;br /&gt;
     this.catcheventobject(this.projectile, &amp;quot;onCollisionEnter&amp;quot;, &amp;quot;onProjectileCollisionEnter&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
The projectile is initialized and positioned on the launcher.&lt;br /&gt;
&lt;br /&gt;
We'll need to use physics to shoot the projectile, this is why we get the RigidBody component of the GameObject;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!temp.rigidBody = this.projectile.GetComponent(Type::RigidBody);&lt;br /&gt;
|}&lt;br /&gt;
(if the GameObject doesn't have a RigidBody by default, you'll need to add it using:  '''''gameobject.AddComponent(Type::RigidBody);''''')&lt;br /&gt;
&lt;br /&gt;
We then add velocity (which is a vector that represents speed in a certain direction). The direction is the Launcher's forward direction, it is multiplied by the desired speed;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!temp.rigidBody.velocity = this.launcher.transform.forward.Mult(this.speed);&lt;br /&gt;
|}&lt;br /&gt;
Now to detect collision, we make sure we '''''SetTimer(9999)''''' for the script to stay up and looking for events, we add the Collision Handler to the projectile;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Quattro::EventManager::AddOnCollisionHandlerTo(this.projectile, this.projectile.layer);&lt;br /&gt;
|}&lt;br /&gt;
and we wait for collisions;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.catcheventobject(this.projectile, &amp;quot;onCollisionEnter&amp;quot;, &amp;quot;onProjectileCollisionEnter&amp;quot;);&lt;br /&gt;
|}&lt;br /&gt;
 public function onProjectileCollisionEnter(gameobject, collision) {&lt;br /&gt;
   temp.radius = 4;&lt;br /&gt;
   temp.force = 5;&lt;br /&gt;
   &lt;br /&gt;
   player.chat = &amp;quot;boom=&amp;quot; @ collision.Gameobject.name;&lt;br /&gt;
   echo (&amp;quot;collision.Gameobject.name=&amp;quot; @ collision.Gameobject.name);&lt;br /&gt;
   &lt;br /&gt;
   temp.explosion = Object::Instantiate(Type::GameObject, this.explosion);&lt;br /&gt;
   temp.explosion.transform.parent = this.empty.transform;&lt;br /&gt;
   temp.explosion.transform.position = collision.Gameobject.transform.position;&lt;br /&gt;
   temp.explosion.transform.scale = v3(1,1,1);&lt;br /&gt;
   &lt;br /&gt;
   temp.affected = Physics::OverlapSphere(temp.explosion.transform.position, 5);&lt;br /&gt;
   for (temp.col: temp.affected) {&lt;br /&gt;
     if (temp.col.GetComponent(Type::RigidBody)!= NULL) {&lt;br /&gt;
       temp.col.GetComponent(Type::RigidBody).AddExplosionForce(temp.force, temp.explosion.transform.position, temp.radius, temp.force * 0.5f, ForceMode::Impulse);&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   if (collision.Gameobject.name == &amp;quot;assets/jimmyminigame/robot.prefab(CLONE)&amp;quot;) {&lt;br /&gt;
     this.wreckedrobot = Object::Instantiate(Type::GameObject, this.wreckedrobotprefab);&lt;br /&gt;
     this.wreckedrobot.transform.parent = this.empty.transform;&lt;br /&gt;
     this.wreckedrobot.transform.position = collision.Gameobject.transform.position;;&lt;br /&gt;
     Object::Destroy(collision.Gameobject);&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   if (collision.Gameobject.name.starts(&amp;quot;assets/jimmyminigame/projectile.prefab&amp;quot;)) return;&lt;br /&gt;
   &lt;br /&gt;
   Object::Destroy(gameobject);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New: Adding Explosion Force&amp;lt;/u&amp;gt; ====&lt;br /&gt;
Upon Collision, we instantiate and place the explosion. To make it seem more realistic we add an explosion force. &lt;br /&gt;
&lt;br /&gt;
We first gather the Colliders around the area of explosion with a radius of 5;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!temp.affected = Physics::OverlapSphere(temp.explosion.transform.position, 5);&lt;br /&gt;
|}&lt;br /&gt;
this will return a list of colliders in the sphere area around the explosion.&lt;br /&gt;
&lt;br /&gt;
We then make sure they have a Rigid Body component and apply explosion force to them;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!temp.col.GetComponent(Type::RigidBody).AddExplosionForce(temp.force, temp.explosion.transform.position, temp.radius, temp.force * 0.5f, ForceMode::Impulse);&lt;br /&gt;
|}&lt;br /&gt;
In this conditional block we ignore the collision if it is between two projectiles;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!if (collision.Gameobject.name.starts(&amp;quot;assets/jimmyminigame/projectile.prefab&amp;quot;)) return;&lt;br /&gt;
|}&lt;br /&gt;
 function destroy() {&lt;br /&gt;
   this.start = false;&lt;br /&gt;
   echo(&amp;quot;destroy&amp;quot;); &lt;br /&gt;
   Object::Destroy(this.turret);&lt;br /&gt;
   Object::Destroy(this.launcher);&lt;br /&gt;
   Object::Destroy(this.robot1);&lt;br /&gt;
   Object::Destroy(this.robot2);&lt;br /&gt;
   Object::Destroy(this.empty);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;u&amp;gt;New : Destroying GameObjects&amp;lt;/u&amp;gt; ====&lt;br /&gt;
Here when the player says &amp;quot;dest&amp;quot;; this function is called and&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Object::Destroy(gameobject);&lt;br /&gt;
|}&lt;br /&gt;
is used to destroy the GameObject.&lt;br /&gt;
&lt;br /&gt;
We can use this function with an added parameter that indicates the time in seconds to wait before destroying the GameObject;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Object::Destroy(gameobject, seconds);&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Getting_Started_Examples&amp;diff=20923</id>
		<title>Getting Started Examples</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Getting_Started_Examples&amp;diff=20923"/>
		<updated>2021-09-02T17:31:41Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Here are a few examples for beginners wanting to get into Graal3D. You will need to have both the '''Graal3D Client''' and '''RC''' downloaded. You will also need an authorized account to be able to login to the server.&lt;br /&gt;
#Download the build compressed file, uncompress it and run the Build application.&lt;br /&gt;
#Login with your GraalID and password, a window will open containing Worlds and Account info.&lt;br /&gt;
#Login to the erareloaded server by typing “erareloaded” in the bottom left server field and press Enter.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Once logged in, you're required to know how to use the tools that allow you to warp to different levels, debug your code... Unity tools are also available as well.&lt;br /&gt;
&lt;br /&gt;
An explanation of all the tools is available here: [[Tools]] &lt;br /&gt;
===Building a Wall Example - ''Creating prefabs and instantiating them''===&lt;br /&gt;
This example is found in the Unity Manual; We will build a wall using primitive type Cubes as Gameobjects. It will be demonstrated using Unity C# and on Graal3D using Graalscript.&lt;br /&gt;
====Using Unity====&lt;br /&gt;
Open the Unity editor with a new project.&lt;br /&gt;
&lt;br /&gt;
'''Step1: Creating an empty Gameobject to hold our Script'''&lt;br /&gt;
&lt;br /&gt;
To your scene add an empty Gameobject. To do that, right click in the Hierarchy Section (on the left) and click on '''Create Empty''', place the created Gameobject in the scene in front of the camera.&lt;br /&gt;
&lt;br /&gt;
This Gameobject will hold our script to build a wall.&lt;br /&gt;
&lt;br /&gt;
[[File:1.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
'''Step2: Creating a Prefab'''&lt;br /&gt;
&lt;br /&gt;
In the same way add a Cube Gameobject to the Hierarchy (right click in Hierarchy -&amp;gt; 3D Object -&amp;gt; Cube).&lt;br /&gt;
&lt;br /&gt;
Now drag the Cube from the Hierarchy to the Assets Section to create a prefab (it will serve as a template to instantiate cubes). Rename the Cube to block (right click on the prefab -&amp;gt; rename).&lt;br /&gt;
&lt;br /&gt;
[[File:2.png|frameless|349x349px]]&lt;br /&gt;
&lt;br /&gt;
'''Step3: Running the script'''&lt;br /&gt;
&lt;br /&gt;
Now to the empty Gameobject we’ll need to add the script that builds a wall.&lt;br /&gt;
&lt;br /&gt;
Press on the Gameobject in the Hierarchy, all its details will pop up in the Inspector Section (on the right). Press on Add Component and search for “script” to add a new script.&lt;br /&gt;
&lt;br /&gt;
[[File:3.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
To modify the script, open it in your IDE and copy the C# script below.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Make sure you name the public class the same name as your script file.&lt;br /&gt;
 using System.Collections;&lt;br /&gt;
 using System.Collections.Generic;&lt;br /&gt;
 using UnityEngine;&lt;br /&gt;
 public class wall: MonoBehaviour {&lt;br /&gt;
   public GameObject block;&lt;br /&gt;
   public int width = 10;&lt;br /&gt;
   public int height = 4;&lt;br /&gt;
   void Start(){&lt;br /&gt;
     for (int y = 0; y &amp;lt; height; ++y) {&lt;br /&gt;
       for (int x = 0; x &amp;lt; width; ++x) {&lt;br /&gt;
         Instantiate(block, new Vector3(x, y, 0), Quaternion.identity);&lt;br /&gt;
       }&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
''Building a Wall - C# Script''&lt;br /&gt;
&lt;br /&gt;
Finally, you’ll need to add the block prefab that we’ve created earlier to script component (to replace the public Gameobject variable “block” in the script).&lt;br /&gt;
&lt;br /&gt;
To do that, drag it from the assets folder to the script component.&lt;br /&gt;
&lt;br /&gt;
[[File:Prefab.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After having completed all the steps above, you should be able to start your scene, it will run all the scripts of the Gameobjects... et Voilà! A Wall![[File:WallOnUnity.png|frameless|671x671px]]&lt;br /&gt;
&lt;br /&gt;
''Wall with 10 Columns and 4 Rows''                                           &lt;br /&gt;
&lt;br /&gt;
'''Explanation:'''&lt;br /&gt;
&lt;br /&gt;
A script needs to implement a class that extends the built-in class '''MonoBehavior'''.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|public class wall: MonoBehaviour { }&lt;br /&gt;
|}The '''Start''' function is where you instantiate your Gameobjects.&lt;br /&gt;
&lt;br /&gt;
The '''Update''' function is where the gameplay updates happen (Gameobject movement, triggering actions, taking user input...). It is similar to the onTimeOut / onMouseDown / onKeyPressed... functions in Graalscript.&lt;br /&gt;
&lt;br /&gt;
'''Important Note:'''&lt;br /&gt;
&lt;br /&gt;
[[File:Coordinates.png|frameless]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Everything related to movement, direction, rotation, speed… in Unity is done using Vectors: '''''new Vector3(x, y, z)'''''&lt;br /&gt;
&lt;br /&gt;
In unity the y axis represents the vertical axis (usually referred to as z)&lt;br /&gt;
&lt;br /&gt;
'''Instantiate Function in Unity:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|Instantiate(block, new Vector3(x, y, 0), Quaternion.identity);&lt;br /&gt;
|}'''Instantiate Function in Unity:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|public static Object Instantiate(Object original, Vector3 position, Quaternion rotation);&lt;br /&gt;
|}In the example, the Object is the block and the rotation is&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|Quaternion.identity&lt;br /&gt;
|}&lt;br /&gt;
to indicate 0 rotation.&lt;br /&gt;
&lt;br /&gt;
'''Quaternions:'''&lt;br /&gt;
&lt;br /&gt;
Quaternions are used to represent rotations. The most used Quaternion functions: Quaternion.LookRotation, Quaternion.Angle, Quaternion.Euler, Quaternion.Slerp, Quaternion.FromToRotation, and Quaternion.identity.&lt;br /&gt;
&lt;br /&gt;
'''Another Way:'''&lt;br /&gt;
&lt;br /&gt;
For primitive types there’s no need to actually create a prefab since they are recognized by Unity. We could have skipped step 2 where we create the prefab and modified our code to this:&lt;br /&gt;
 using System.Collections;&lt;br /&gt;
 using System.Collections.Generic;&lt;br /&gt;
 using UnityEngine;&lt;br /&gt;
 public class wall: MonoBehaviour {&lt;br /&gt;
   public int width = 10;&lt;br /&gt;
   public int height = 4;&lt;br /&gt;
   void Start() {&lt;br /&gt;
     for (int y = 0; y &amp;lt; height; ++y) {&lt;br /&gt;
       for (int x = 0; x &amp;lt; width; ++x) {&lt;br /&gt;
         GameObject.CreatePrimitive(PrimitiveType.Cube).transform.position = new Vector3(x, y, 0);&lt;br /&gt;
       }&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
''Building a Wall - C# Script''&lt;br /&gt;
====Using Graal3D====&lt;br /&gt;
We are going to mimic the second C# script since it would be useless to upload a Cube prefab to the server, when we can simply instantiate them using PrimitiveType.&lt;br /&gt;
&lt;br /&gt;
The same script above will look like this in GraalScript: ('''''Weapon:''''' ''3D/Samples/Examples/BuildingWall'')&lt;br /&gt;
 findplayer(&amp;quot;GraalID&amp;quot;).addweapon(this.name);&lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   this.width = 10;&lt;br /&gt;
   this.height = 4;&lt;br /&gt;
   for (temp.y = 0; temp.y &amp;lt; this.height; ++temp.y) {&lt;br /&gt;
     for (temp.x = 0; temp.x &amp;lt; this.width; ++temp.x) {&lt;br /&gt;
       GameObject::CreatePrimitive(PrimitiveType::Cube).transform.position = v3(player.x - 5 + temp.x, temp.y, player.y + 1);&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
''Building a Wall - Graal Script''&lt;br /&gt;
&lt;br /&gt;
The two codes are almost the same except for:&lt;br /&gt;
*The '''''onCreated()''''' function replaces the '''''start()''''' function&lt;br /&gt;
*The “ . ” for methods is replaced by “:: ”&lt;br /&gt;
'''Function format:''' Unity C#: '''''Type.method''''' =&amp;gt; Graal Script: '''''Type::Method'''''&lt;br /&gt;
*'''''v3(x,y,z)''''' replaces '''new''' '''''Vector3(x,y,z)'''''&lt;br /&gt;
*The Gameobject is instantiated close to the player using (player.x and player.y)&lt;br /&gt;
[[File:Wall.png|frameless|695x695px]]&lt;br /&gt;
&lt;br /&gt;
''Wall with 10 Columns and 4 Rows''&lt;br /&gt;
===Circle Formation Example - Using Rotation and Mathf functions===&lt;br /&gt;
This example is similar to the one above, we’ll instantiate the Cubes in a circular shape with rotation so that they all point towards the player.&lt;br /&gt;
====Using Unity====&lt;br /&gt;
Just like in the previous example; create a new script file named “CircleFormation”, open it in you editor and copy paste this code:&lt;br /&gt;
 using UnityEngine;&lt;br /&gt;
 public class CircleFormation: MonoBehaviour {&lt;br /&gt;
   public GameObject prefab;&lt;br /&gt;
   public int numberOfObjects = 20;&lt;br /&gt;
   public float radius = 5f;&lt;br /&gt;
   void Start() {&lt;br /&gt;
     for (int i = 0; i &amp;lt; numberOfObjects; i++) {&lt;br /&gt;
       float angle = i * Mathf.PI * 2 / numberOfObjects;&lt;br /&gt;
       float x = Mathf.Cos(angle) * radius;&lt;br /&gt;
       float z = Mathf.Sin(angle) * radius;&lt;br /&gt;
       Vector3 pos = transform.position + new Vector3(x, 0, z);&lt;br /&gt;
       float angleDegrees = -angle*Mathf.Rad2Deg;&lt;br /&gt;
       Quaternion rot = Quaternion.Euler(0, angleDegrees, 0);&lt;br /&gt;
       Instantiate(prefab, pos, rot);&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
''Circle Formation - C# Script''&lt;br /&gt;
&lt;br /&gt;
Create an empty Gameobject in the Hierarchy, add the script to it (as a component).&lt;br /&gt;
&lt;br /&gt;
Add a Cube Gameobject to the Hierarchy (right click -&amp;gt; 3D Object -&amp;gt; Cube).&lt;br /&gt;
&lt;br /&gt;
Now drag the Cube from the Hierarchy to the Assets Section to create a prefab, rename it to “prefab” to be referenced by the script. Finally add it to the script on the Empty Gameobject and hit run.&lt;br /&gt;
&lt;br /&gt;
[[File:Circle formation unity.png|frameless|751x751px]]&lt;br /&gt;
&lt;br /&gt;
'''Explanation:'''&lt;br /&gt;
&lt;br /&gt;
In this example we use the '''Mathf''' collection, a struct containing all the static math methods.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;https://docs.unity3d.com/ScriptReference/Mathf.html&amp;lt;/u&amp;gt; for all the methods.&lt;br /&gt;
&lt;br /&gt;
We also use the '''''Quaternion.Euler''''' to rotate the cubes. You can rotate around whatever axis you want, in our example '''''Quaternion.Euler(0, angleDegress, 0)''''' rotates the cubes around the y axis.&lt;br /&gt;
&lt;br /&gt;
'''Another Way:'''&lt;br /&gt;
&lt;br /&gt;
Just like before we could’ve just used '''''GameObject.CreatePrimitive(PrimitiveType.Cube)''''' to create the cubes and then change the transform.position and the transform.rotation.&lt;br /&gt;
====Using Graal3D====&lt;br /&gt;
Again, since we don’t want to upload useless PrimitiveType prefabs to the server, we use this approach: ('''''Weapon:''''' ''3D/Samples/Examples/CircleFormation'')&lt;br /&gt;
 findplayer(&amp;quot;GraalID&amp;quot;).addweapon(this.name);&lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   temp.nbofobjects = 20;&lt;br /&gt;
   temp.radius = 5f;&lt;br /&gt;
   for (temp.i = 0; temp.i &amp;lt; temp.nbofobjects; ++temp.i) {&lt;br /&gt;
     temp.angle = temp.i * Mathf::PI * 2 / temp.nbofobjects;&lt;br /&gt;
     temp.x1 = cos(temp.angle) * temp.radius;&lt;br /&gt;
     temp.y1 = sin(temp.angle) * temp.radius;&lt;br /&gt;
     temp.cube = GameObject::CreatePrimitive(PrimitiveType::Cube);&lt;br /&gt;
     temp.cube.transform.position = v3(player.x + temp.x1, player.z, player.y + temp.y1);&lt;br /&gt;
     temp.angleDegrees = -temp.angle * Mathf::Rad2Deg;&lt;br /&gt;
     temp.cube.transform.rotation = Quaternion::euler(0, temp.angleDegrees, 0);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
[[File:Circle formation graal3d.png|frameless|639x639px]]&lt;br /&gt;
&lt;br /&gt;
''Circle Formation - Graal Script''&lt;br /&gt;
===Moving Cube Example - Using the Update function===&lt;br /&gt;
====Using Unity====&lt;br /&gt;
 using System.Collections;&lt;br /&gt;
 using System.Collections.Generic;&lt;br /&gt;
 using UnityEngine;&lt;br /&gt;
 public class MovingCube: MonoBehaviour {&lt;br /&gt;
   GameObject cube;&lt;br /&gt;
   public int height = 10;&lt;br /&gt;
   public float yCenter = 0f;&lt;br /&gt;
   void Start() {&lt;br /&gt;
     cube = GameObject.CreatePrimitive(PrimitiveType.Cube);&lt;br /&gt;
     cube.transform.position = new Vector3(0, 0f, 0);&lt;br /&gt;
   }&lt;br /&gt;
   void Update() {&lt;br /&gt;
     cube.transform.position = new Vector3(cube.transform.position.x, yCenter + Mathf.PingPong(Time.time * 2, height) - height / 2f,       cube.transform.position.z);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
''Moving Cube - C# Script''&lt;br /&gt;
&lt;br /&gt;
Here we use the Update function. As its name suggests, it will serve to update gameplay and move the cube up and down depending on the time.&lt;br /&gt;
====Using Graal3D====&lt;br /&gt;
('''''Weapon:''''' ''3D/Samples/Examples/MovingCube'')&lt;br /&gt;
 findplayer(&amp;quot;GraalID&amp;quot;).addweapon(this.name);&lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 function onCreated(){&lt;br /&gt;
   this.cube = GameObject::CreatePrimitive(PrimitiveType::Cube);&lt;br /&gt;
   this.cube.transform.position = v3(player.x,player.z,player.y);&lt;br /&gt;
   this.height = 10;//max height of Box's movement&lt;br /&gt;
   this.yCenter = 0.0;&lt;br /&gt;
   SetTimer(0.001);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onTimeout() {&lt;br /&gt;
   this.cube.transform.position = v3(this.cube.transform.position.x,this.yCenter + Mathf::PingPong(Time::time *2,    this.height)  - height / 2.0,this.cube.transform.position.z);&lt;br /&gt;
   SetTimer(0.001);&lt;br /&gt;
 }&lt;br /&gt;
Moving Cube - GraalScript&lt;br /&gt;
&lt;br /&gt;
Here the '''''SetTimer()''''' and '''''onTimeout()''''' functions replace the '''''Update()''''' function in Unity.&lt;br /&gt;
===Cube with Physics - Using Physics and Collision===&lt;br /&gt;
In this example we will add physics to our Gameobject, it will be subject to gravity, forces and collisions with other Gameobjects. We will also see how to detect and handle these collisions.&lt;br /&gt;
&lt;br /&gt;
('''''Weapon:''''' ''3D/Samples/Examples/SimplePhysicObject'')&lt;br /&gt;
 findplayer(&amp;quot;GraalID&amp;quot;).addweapon(this.name);&lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   SetTimer(9999);&lt;br /&gt;
   this.cube = GameObject::CreatePrimitive(PrimitiveType::Cube);&lt;br /&gt;
   this.cube.transform.position = v3(player.x + 5, player.z, player.y);&lt;br /&gt;
   this.cube.AddComponent(Type::RigidBody);&lt;br /&gt;
   Quattro::EventManager::AddOnCollisionHandlerTo(this.cube, this.cube.layer);&lt;br /&gt;
   this.catcheventobject(this.cube, &amp;quot;onCollisionEnter&amp;quot;, &amp;quot;onCubeCollisionEnter&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function onCubeCollisionEnter(gameobject, collision) {&lt;br /&gt;
   player.chat = &amp;quot;Collision!&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
''Cube with Physics - Graal Script''&lt;br /&gt;
&lt;br /&gt;
We create and place a Cube just like the examples before. &lt;br /&gt;
&lt;br /&gt;
To add physics to the GameObject, we add the '''RigidBody Component''';&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.cube.AddComponent(Type::RigidBody);&lt;br /&gt;
|}&lt;br /&gt;
Now to add a Collision Handler;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!''Quattro::EventManager::AddOnCollisionHandlerTo()''&lt;br /&gt;
|}&lt;br /&gt;
And &lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!''this.catcheventobject(GameObject, “onCollisionEnter”, “onFunctionName”)''&lt;br /&gt;
|}&lt;br /&gt;
Which will catch collision and call the function '''''onFunctionName()''''' that you have to implement;&lt;br /&gt;
 public function onCubeCollisionEnter(gameobject, collision) {&lt;br /&gt;
   player.chat = &amp;quot;Collision!&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
The two parameters:&lt;br /&gt;
&lt;br /&gt;
'''gameobject:''' it is the Gameobject that was just used to detect collision (''the cube in our example'')&lt;br /&gt;
&lt;br /&gt;
'''collision:''' describes the collider we hit, you can retrieve the GameObject collided with by using: '''''collision.GameObject'''.''&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Whenever we use collisions, the '''''SetTimer(9999)''''' is essential; it will keep the script alive and always checking for events. the Unity function OnUpdate() will be triggered for every frame.&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Graal3D_Scripting_Manual&amp;diff=20922</id>
		<title>Graal3D Scripting Manual</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Graal3D_Scripting_Manual&amp;diff=20922"/>
		<updated>2021-09-02T17:27:04Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: removed johns system&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Intro ==&lt;br /&gt;
[[File:Graal kart start.jpg|center|frame]]&lt;br /&gt;
Welcome to the Graal3D Scripting Manual!&lt;br /&gt;
&lt;br /&gt;
This Manual comes in handy for beginners wanting to learn Graal3D Scripting, and advanced developers looking to expand their knowledge, as it  contains documentation, examples, tutorials and much more...&lt;br /&gt;
&lt;br /&gt;
What we will focus on in this Manual is programming our gameplay (scripting the behavior of our GameObjects, their interactions, the components attached to them...)&lt;br /&gt;
&lt;br /&gt;
==== How things work in Unity: ====&lt;br /&gt;
Unity is the leading platform for building 2D, 3D, VR and augmented reality games. It offers a scripting API in C#, allowing us to interact with the unity editor and the games we want to build.&lt;br /&gt;
&lt;br /&gt;
In the Unity editor, we create and add GameObjects to our scene, we then attach C# scripts to each that will all run upon starting the scene. Unity sort of runs everything for you, it reads through all the lights, cameras, meshes, behaviors… and processes it for you.&lt;br /&gt;
&lt;br /&gt;
==== How things work in Graal3D: ====&lt;br /&gt;
Since we will be using the Graal Unity Binding, things will be a bit different.&lt;br /&gt;
&lt;br /&gt;
The Graal Unity Binding is a binding between GraalScript and Unity, it is actually still in alpha, but most functionalities needed are present. The goal of this binding is to mimic the Unity C# scripting system (functions and classes). So if you are familiar with Unity and C#, everything should be easy. If not, then do not worry, I will go over everything step by step and include examples done in C# and compare them to GraalScript for each topic.&lt;br /&gt;
&lt;br /&gt;
The 3D Client (which you will have to download) will serve as the Unity editor, mentioned earlier, which contains the base scene where you instantiate your GameObjects and manipulate them with your GraalScripts.&lt;br /&gt;
&lt;br /&gt;
==== Required Downloads ====&lt;br /&gt;
'''Unity 2020.2.2f1:''' https://unity3d.com/get-unity/download/archive&lt;br /&gt;
&lt;br /&gt;
'''The Graal3D Client:''' https://drive.google.com/drive/u/0/folders/1rpOli0fxnA-Q7-IpYg3rUFJ44M0PsSxd&lt;br /&gt;
&lt;br /&gt;
'''RC:''' http://fp4.ca/windows_rc3_beta.zip&lt;br /&gt;
&lt;br /&gt;
==== Tools ====&lt;br /&gt;
In-game Unity Tools (''mimic the Unity Editor)'' &amp;amp; Game Functionality Tools ''(warping, fixing graphics, starting minigames...):'' &amp;lt;u&amp;gt;[[Tools]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
&lt;br /&gt;
==== Unity ====&lt;br /&gt;
&lt;br /&gt;
* [[Overview On Unity Basics]]&lt;br /&gt;
&lt;br /&gt;
==== AssetBundles ====&lt;br /&gt;
&lt;br /&gt;
* [[Uploading and Loading AssetBundles]]&lt;br /&gt;
*[[Placing GameObjects in NPC]]&lt;br /&gt;
&lt;br /&gt;
==== Examples and Tutorials ====&lt;br /&gt;
*[[Getting Started Examples]]&lt;br /&gt;
*[[3DTutorials|Tutorials]]&lt;br /&gt;
*[[Unity UI]]&lt;br /&gt;
*[[Item Manager]]&lt;br /&gt;
&lt;br /&gt;
==== Classes, Functions and Variables ====&lt;br /&gt;
&lt;br /&gt;
* [https://quattro3d.graalonline.com/Documentation/ Quattro3D Scripting]&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Placing_GameObjects_in_NPC&amp;diff=20921</id>
		<title>Placing GameObjects in NPC</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Placing_GameObjects_in_NPC&amp;diff=20921"/>
		<updated>2021-09-02T17:22:53Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Another way to make GameObjects visible to all the Players is by placing them in NPCs. &lt;br /&gt;
&lt;br /&gt;
However, placing many NPCs may be heavy on the server, so beware of that whenever you're doing so.&lt;br /&gt;
&lt;br /&gt;
Start off by creating the NPC the normal way:&lt;br /&gt;
&lt;br /&gt;
Create a Script file in classes. You load the assets the same it was done before in weapons; under '''//#CLIENTSIDE'''&lt;br /&gt;
[[File:NPC GO.png|none|thumb|1041x1041px]]&lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;/destroy&amp;quot;) this.destroy();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 &lt;br /&gt;
 function onCreated() {&lt;br /&gt;
     Quattro::AssetManagement::LoadAssetBundle(&amp;quot;documentationexample&amp;quot;);&lt;br /&gt;
     this.prefab = GameObject::fromassetbundle(&amp;quot;documentationexample&amp;quot;, &amp;quot;assets/example/bomb.prefab&amp;quot;);&lt;br /&gt;
     this.bomb = Object::Instantiate(Type::GameObject, this.prefab);&lt;br /&gt;
     this.bomb.transform.parent = this.gameobject.transform;&lt;br /&gt;
     this.bomb.transform.localposition =v3(0,0.5,0);&lt;br /&gt;
 }&lt;br /&gt;
'''&amp;lt;u&amp;gt;Class:&amp;lt;/u&amp;gt;''' ''3d_samples_documentation_test'' &lt;br /&gt;
&lt;br /&gt;
Everything is the same when it comes to loading and instantiating the prefabs. &lt;br /&gt;
&lt;br /&gt;
The only difference is for this line of code:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.projectile.transform.parent = this.gameobject.transform;&lt;br /&gt;
|}&lt;br /&gt;
Here, '''''this.gameobject''''' is the NPC GameObject. It is an empty GameObject we attach our prefabs to. We create the prefabs and make them children of this NPC GameObject.  &lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;u&amp;gt;Destroying the NPC:&amp;lt;/u&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
* '''''this.destroy''''' will destroy the NPC and all the children as well. (''done on'' ''ServerSide'') &lt;br /&gt;
* You could also destroy the NPC and its children using the Unity Binding function: '''''Object::Destroy(this.gameobject).''''' (''done on ClientSide'')  &lt;br /&gt;
&lt;br /&gt;
Now in your other script/weapon. To place the NPC in the scene, we use '''''putnpc2(x,y,&amp;quot;&amp;quot;)'''''; &lt;br /&gt;
&lt;br /&gt;
On ClientSide we trigger server in order to place the NPC containing the prefabs, and inform all the other clients of it, by implementing '''''onActionServerSide()'''''. &lt;br /&gt;
 findplayer(&amp;quot;Graal5918039&amp;quot;).addweapon(this.name);&lt;br /&gt;
 &lt;br /&gt;
 function onActionServerside(cmd,x,y) {&lt;br /&gt;
   if (cmd == &amp;quot;bomb&amp;quot;) {&lt;br /&gt;
     temp.bombernpc = putnpc2(x,y,&amp;quot;&amp;quot;);&lt;br /&gt;
     temp.bombernpc.join(&amp;quot;3d_samples_documentation_test&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 &lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   triggerserver(&amp;quot;gui&amp;quot;, this.name, &amp;quot;bomb&amp;quot;, player.x, player.y);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;u&amp;gt;'''Weapon:'''&amp;lt;/u&amp;gt; ''3D/Samples/Examples/DocumentationTest''&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=File:NPC_GO.png&amp;diff=20920</id>
		<title>File:NPC GO.png</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=File:NPC_GO.png&amp;diff=20920"/>
		<updated>2021-09-02T17:21:26Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;NPC GO&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Placing_GameObjects_in_NPC&amp;diff=20919</id>
		<title>Placing GameObjects in NPC</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Placing_GameObjects_in_NPC&amp;diff=20919"/>
		<updated>2021-09-02T17:06:47Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Another way to make GameObjects visible to all the Players is by placing them in NPCs. &lt;br /&gt;
&lt;br /&gt;
However, placing many NPCs may be heavy on the server, so beware of that whenever you're doing so.&lt;br /&gt;
&lt;br /&gt;
Start off by creating the NPC the normal way:&lt;br /&gt;
&lt;br /&gt;
Create a Script file in classes. You load the assets the same it was done before in weapons; under '''//#CLIENTSIDE'''&lt;br /&gt;
&lt;br /&gt;
[[File:Placing GO in npcs.png|frameless|1048x1048px]]&lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;/destroy&amp;quot;) this.destroy();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 &lt;br /&gt;
 function onCreated() {&lt;br /&gt;
     Quattro::AssetManagement::LoadAssetBundle(&amp;quot;documentationexample&amp;quot;);&lt;br /&gt;
     this.prefab = GameObject::fromassetbundle(&amp;quot;documentationexample&amp;quot;, &amp;quot;assets/example/bomb.prefab&amp;quot;);&lt;br /&gt;
     this.bomb = Object::Instantiate(Type::GameObject, this.prefab);&lt;br /&gt;
     this.bomb.transform.parent = this.gameobject.transform;&lt;br /&gt;
     this.bomb.transform.localposition =v3(0,0.5,0);&lt;br /&gt;
 }&lt;br /&gt;
'''&amp;lt;u&amp;gt;Class:&amp;lt;/u&amp;gt;''' ''3d_samples_documentation_test'' &lt;br /&gt;
&lt;br /&gt;
Everything is the same when it comes to loading and instantiating the prefabs. &lt;br /&gt;
&lt;br /&gt;
The only difference is for this line of code:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.projectile.transform.parent = this.gameobject.transform;&lt;br /&gt;
|}&lt;br /&gt;
Here, '''''this.gameobject''''' is the NPC GameObject. It is an empty GameObject we attach our prefabs to. We create the prefabs and make them children of this NPC GameObject.  &lt;br /&gt;
&lt;br /&gt;
===== &amp;lt;u&amp;gt;Destroying the NPC:&amp;lt;/u&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
* '''''this.destroy''''' will destroy the NPC and all the children as well. (''done on'' ''ServerSide'') &lt;br /&gt;
* You could also destroy the NPC and its children using the Unity Binding function: '''''Object::Destroy(this.gameobject).''''' (''done on ClientSide'')  &lt;br /&gt;
&lt;br /&gt;
Now in your other script/weapon. To place the NPC in the scene, we use '''''putnpc2(x,y,&amp;quot;&amp;quot;)'''''; &lt;br /&gt;
&lt;br /&gt;
On ClientSide we trigger server in order to place the NPC containing the prefabs, and inform all the other clients of it, by implementing '''''onActionServerSide()'''''. &lt;br /&gt;
 findplayer(&amp;quot;Graal5918039&amp;quot;).addweapon(this.name);&lt;br /&gt;
 &lt;br /&gt;
 function onActionServerside(cmd,x,y) {&lt;br /&gt;
   if (cmd == &amp;quot;bomb&amp;quot;) {&lt;br /&gt;
     temp.bombernpc = putnpc2(x,y,&amp;quot;&amp;quot;);&lt;br /&gt;
     temp.bombernpc.join(&amp;quot;3d_samples_documentation_test&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 &lt;br /&gt;
 function onCreated() {&lt;br /&gt;
   triggerserver(&amp;quot;gui&amp;quot;, this.name, &amp;quot;bomb&amp;quot;, player.x, player.y);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;u&amp;gt;'''Weapon:'''&amp;lt;/u&amp;gt; ''3D/Samples/Examples/DocumentationTest''&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Uploading_and_Loading_AssetBundles&amp;diff=20918</id>
		<title>Uploading and Loading AssetBundles</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Uploading_and_Loading_AssetBundles&amp;diff=20918"/>
		<updated>2021-09-02T17:05:30Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Up until now, we have been using PrimitiveTypes for our GameObjects.&lt;br /&gt;
&lt;br /&gt;
In this section, we will start using different GameObjects. I will go over how to upload your assetbundles containing all your customized prefabs to the server. How to load, instantiate, and manipulate them.&lt;br /&gt;
===Uploading AssetBundles===&lt;br /&gt;
You will need to have Unity installed for this part.&lt;br /&gt;
&lt;br /&gt;
You will also need to have the “Quattro3D- Unity Project for bundle asset creation.7z&amp;quot; Unity project installed from the google drive.&lt;br /&gt;
&lt;br /&gt;
I will be going through an example, demonstrating how it’s done.&lt;br /&gt;
&lt;br /&gt;
Begin by choosing what prefabs you want to upload. In our case, I will upload a bomb and a character prefab, which I already have ready in a different project.&lt;br /&gt;
&lt;br /&gt;
Note: Remember you cant put scripts in your asset bundles.&lt;br /&gt;
&lt;br /&gt;
Open the Unity project downloaded (“Quattro3D- Unity Project for bundle asset creation.7z&amp;quot;). This project contains a script that builds the assetbundles and puts them in the Assets/StreamingAssets folder, which will hold all our uploadable files.&lt;br /&gt;
&lt;br /&gt;
In the Assets folder, I will create a new folder and name it Example.&lt;br /&gt;
&lt;br /&gt;
Next I will import my prefabs;&lt;br /&gt;
&lt;br /&gt;
In the top left menu hit (Assets&amp;gt;Import New Asset/Import Package). Go to the location of your prefabs and select them and press Import.&lt;br /&gt;
&lt;br /&gt;
[[File:Uploading assetbundles.png|frameless|371x371px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Prefabs.png|frameless|476x476px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Imported prefabs.png|frameless|773x773px]]&lt;br /&gt;
&lt;br /&gt;
Now that we’ve imported our assets, we’ll create an assetbundle to be uploaded to the server;&lt;br /&gt;
&lt;br /&gt;
Using the Unity way of creating assetbundles by flagging the prefabs:&lt;br /&gt;
&lt;br /&gt;
Select all the prefabs in the asset folder, the Inspector Window should open. At the bottom right of your screen, in the Inspector Window, create or select an existing name for your assetbundle.&lt;br /&gt;
&lt;br /&gt;
The bundle will embed all the assets/prefabs under that flagged directory. You can of course put multiple prefabs/files/subdir...etc inside an asset bundle.&lt;br /&gt;
&lt;br /&gt;
[[File:Adding a tag to the prefabs.png|frameless|541x541px]]    [[File:Tagging prefabs.png|frameless|541x541px]]&lt;br /&gt;
&lt;br /&gt;
Now build your asset by pressing on BuildAssetBundles&amp;gt;PackagesBuilder&amp;gt;buildAssetBundles in that project.&lt;br /&gt;
&lt;br /&gt;
The built asset will be stored in the downloaded Unity Project in “Quattro3D- Unity Project for bundle asset creation\Assets\StreamingAssets”&lt;br /&gt;
&lt;br /&gt;
[[File:Uploading assets to the server.png|frameless|712x712px]]&lt;br /&gt;
&lt;br /&gt;
The file that we’ll use to upload to graal should end with “.txt”&lt;br /&gt;
&lt;br /&gt;
[[File:Uploading to the server.png|frameless|800x800px]]&lt;br /&gt;
&lt;br /&gt;
Finally to upload the asset to the server, login on rc, go to levels/assetbundles and drop the “.txt” file there.&lt;br /&gt;
&lt;br /&gt;
It should be automatically downloaded to /Users/”yourusername”/AppData/LocalLow/Graal Worlds/Levels3d/assetbundles[[File:Uploading assets through rc.png|center|frameless|477x477px]]''You’re strongly advised to generate a unitypackage too when you generate an asset bundle and upload it to the server, so that everyone can rebuild the bundle on every platform.''&lt;br /&gt;
&lt;br /&gt;
To view your asset and your prefabs, login to the Client, hit F10 to open the Bundle Explorer and search for your asset name.[[File:Bundle explorer.png|center|frameless|768x768px]]&lt;br /&gt;
===ClientSide Loading Assets===&lt;br /&gt;
Now to load your prefabs using GraalScript; to your code add the following:&lt;br /&gt;
&lt;br /&gt;
You can use the Bundle Explorer (F10) to copy the path of the AssetBundle.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|findplayer(&amp;quot;Graal5918039&amp;quot;).addweapon(this.name);&lt;br /&gt;
//#CLIENTSIDE&lt;br /&gt;
&lt;br /&gt;
function onCreated() {&lt;br /&gt;
&lt;br /&gt;
  Quattro::AssetManagement::LoadAssetBundle(&amp;quot;documentationexample&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function onAssetBundleDownloaded(bundlename) {&lt;br /&gt;
&lt;br /&gt;
  if (bundlename == &amp;quot;documentationexample&amp;quot;) {&lt;br /&gt;
&lt;br /&gt;
    player.chat = &amp;quot;example loaded&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
    temp.prefab = GameObject::fromassetbundle(&amp;quot;documentationexample&amp;quot;, &amp;quot;assets/example/bomb.prefab&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    this.bomb = Object::Instantiate(Type::GameObject, temp.prefab);&lt;br /&gt;
&lt;br /&gt;
    this.bomb.transform.position = v3(player.x + 5, player.z, player.y);&lt;br /&gt;
&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
|}[[File:Loading prefabs.png|center|frameless|406x406px]]&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!  Quattro::AssetManagement::LoadAssetBundle(&amp;quot;documentationexample&amp;quot;);&lt;br /&gt;
|}&lt;br /&gt;
The above method loads and downloads the AssetBundle.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! function onAssetBundleDownloaded(bundlename) &lt;br /&gt;
|}&lt;br /&gt;
And Implementing the '''''onAssetBundleDownloaded''''' will make sure the Assetbundle has been loaded. We could've skipped this step and directly created the prefab, but best is to make sure the Asset has been loaded.&lt;br /&gt;
&lt;br /&gt;
We then create a prefab:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!temp.prefab = GameObject::fromassetbundle(&amp;quot;documentationexample&amp;quot;, &amp;quot;assets/example/bomb.prefab&amp;quot;);&lt;br /&gt;
|}&lt;br /&gt;
instantiate it,&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.bomb = Object::Instantiate(Type::GameObject, temp.prefab);&lt;br /&gt;
|}&lt;br /&gt;
and give it a position in the scene:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.bomb.transform.position = v3(player.x + 5, player.z, player.y);&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Uploading_and_Loading_AssetBundles&amp;diff=20917</id>
		<title>Uploading and Loading AssetBundles</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Uploading_and_Loading_AssetBundles&amp;diff=20917"/>
		<updated>2021-09-02T17:04:34Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Up until now, we have been using PrimitiveTypes for our GameObjects.&lt;br /&gt;
&lt;br /&gt;
In this section, we will start using different GameObjects. I will go over how to upload your assetbundles containing all your customized prefabs to the server. How to load, instantiate, and manipulate them.&lt;br /&gt;
===Uploading AssetBundles===&lt;br /&gt;
You will need to have Unity installed for this part.&lt;br /&gt;
&lt;br /&gt;
You will also need to have the “Quattro3D- Unity Project for bundle asset creation.7z&amp;quot; Unity project installed from the google drive.&lt;br /&gt;
&lt;br /&gt;
I will be going through an example, demonstrating how it’s done.&lt;br /&gt;
&lt;br /&gt;
Begin by choosing what prefabs you want to upload. In our case, I will upload a bomb and a character prefab, which I already have ready in a different project.&lt;br /&gt;
&lt;br /&gt;
Note: Remember you cant put scripts in your asset bundles.&lt;br /&gt;
&lt;br /&gt;
Open the Unity project downloaded (“Quattro3D- Unity Project for bundle asset creation.7z&amp;quot;). This project contains a script that builds the assetbundles and puts them in the Assets/StreamingAssets folder, which will hold all our uploadable files.&lt;br /&gt;
&lt;br /&gt;
In the Assets folder, I will create a new folder and name it Example.&lt;br /&gt;
&lt;br /&gt;
Next I will import my prefabs;&lt;br /&gt;
&lt;br /&gt;
In the top left menu hit (Assets&amp;gt;Import New Asset/Import Package). Go to the location of your prefabs and select them and press Import.&lt;br /&gt;
&lt;br /&gt;
[[File:Uploading assetbundles.png|frameless|371x371px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Prefabs.png|frameless|476x476px]]&lt;br /&gt;
&lt;br /&gt;
[[File:Imported prefabs.png|frameless|773x773px]]&lt;br /&gt;
&lt;br /&gt;
Now that we’ve imported our assets, we’ll create an assetbundle to be uploaded to the server;&lt;br /&gt;
&lt;br /&gt;
Using the Unity way of creating assetbundles by flagging the prefabs:&lt;br /&gt;
&lt;br /&gt;
Select all the prefabs in the asset folder, the Inspector Window should open. At the bottom right of your screen, in the Inspector Window, create or select an existing name for your assetbundle.&lt;br /&gt;
&lt;br /&gt;
The bundle will embed all the assets/prefabs under that flagged directory. You can of course put multiple prefabs/files/subdir...etc inside an asset bundle.&lt;br /&gt;
&lt;br /&gt;
[[File:Adding a tag to the prefabs.png|frameless|541x541px]]    [[File:Tagging prefabs.png|frameless|541x541px]]&lt;br /&gt;
&lt;br /&gt;
Now build your asset by pressing on BuildAssetBundles&amp;gt;PackagesBuilder&amp;gt;buildAssetBundles in that project.&lt;br /&gt;
&lt;br /&gt;
The built asset will be stored in the downloaded Unity Project in “Quattro3D- Unity Project for bundle asset creation\Assets\StreamingAssets”&lt;br /&gt;
&lt;br /&gt;
[[File:Uploading assets to the server.png|frameless|712x712px]]&lt;br /&gt;
&lt;br /&gt;
The file that we’ll use to upload to graal should end with “.txt”&lt;br /&gt;
&lt;br /&gt;
[[File:Uploading to the server.png|frameless|800x800px]]&lt;br /&gt;
&lt;br /&gt;
Finally to upload the asset to the server, login on rc, go to levels/assetbundles and drop the “.txt” file there.&lt;br /&gt;
&lt;br /&gt;
It should be automatically downloaded to /Users/”yourusername”/AppData/LocalLow/Graal Worlds/Levels3d/assetbundles[[File:Uploading assets through rc.png|center|frameless|477x477px]]''You’re strongly advised to generate a unitypackage too when you generate an asset bundle and upload it to the server, so that everyone can rebuild the bundle on every platform.''&lt;br /&gt;
&lt;br /&gt;
To view your asset and your prefabs, login to the Client, hit F10 to open the Bundle Explorer and search for your asset name.[[File:Bundle explorer.png|center|frameless|768x768px]]&lt;br /&gt;
===ClientSide Loading Assets===&lt;br /&gt;
Now to load your prefabs using GraalScript; to your code add the following:&lt;br /&gt;
&lt;br /&gt;
You can use the Bundle Explorer (F10) to copy the path of the AssetBundle.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|findplayer(&amp;quot;Graal5918039&amp;quot;).addweapon(this.name);&lt;br /&gt;
//#CLIENTSIDE&lt;br /&gt;
&lt;br /&gt;
function onCreated() {&lt;br /&gt;
&lt;br /&gt;
  Quattro::AssetManagement::LoadAssetBundle(&amp;quot;documentationexample&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function onAssetBundleDownloaded(bundlename) {&lt;br /&gt;
&lt;br /&gt;
  if (bundlename == &amp;quot;documentationexample&amp;quot;) {&lt;br /&gt;
&lt;br /&gt;
    player.chat = &amp;quot;example loaded&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
    temp.prefab = GameObject::fromassetbundle(&amp;quot;documentationexample&amp;quot;, &amp;quot;assets/example/bomb.prefab&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    this.bomb = Object::Instantiate(Type::GameObject, temp.prefab);&lt;br /&gt;
&lt;br /&gt;
    this.bomb.transform.position = Vector3::Create(player.x + 5, player.z, player.y);&lt;br /&gt;
&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
|}[[File:Loading prefabs.png|center|frameless|406x406px]]&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!  Quattro::AssetManagement::LoadAssetBundle(&amp;quot;documentationexample&amp;quot;);&lt;br /&gt;
|}&lt;br /&gt;
The above method loads and downloads the AssetBundle.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! function onAssetBundleDownloaded(bundlename) &lt;br /&gt;
|}&lt;br /&gt;
And Implementing the '''''onAssetBundleDownloaded''''' will make sure the Assetbundle has been loaded. We could've skipped this step and directly created the prefab, but best is to make sure the Asset has been loaded.&lt;br /&gt;
&lt;br /&gt;
We then create a prefab:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!temp.prefab = GameObject::fromassetbundle(&amp;quot;documentationexample&amp;quot;, &amp;quot;assets/example/bomb.prefab&amp;quot;);&lt;br /&gt;
|}&lt;br /&gt;
instantiate it,&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.bomb = Object::Instantiate(Type::GameObject, temp.prefab);&lt;br /&gt;
|}&lt;br /&gt;
and give it a position in the scene:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!this.bomb.transform.position = Vector3::Create(player.x + 5, player.z, player.y);&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Graal3D_Scripting_Manual&amp;diff=20916</id>
		<title>Graal3D Scripting Manual</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Graal3D_Scripting_Manual&amp;diff=20916"/>
		<updated>2021-08-29T19:04:45Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: /* Tools */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Intro ==&lt;br /&gt;
[[File:Graal kart start.jpg|center|frame]]&lt;br /&gt;
Welcome to the Graal3D Scripting Manual!&lt;br /&gt;
&lt;br /&gt;
This Manual comes in handy for beginners wanting to learn Graal3D Scripting, and advanced developers looking to expand their knowledge, as it  contains documentation, examples, tutorials and much more...&lt;br /&gt;
&lt;br /&gt;
What we will focus on in this Manual is programming our gameplay (scripting the behavior of our GameObjects, their interactions, the components attached to them...)&lt;br /&gt;
&lt;br /&gt;
==== How things work in Unity: ====&lt;br /&gt;
Unity is the leading platform for building 2D, 3D, VR and augmented reality games. It offers a scripting API in C#, allowing us to interact with the unity editor and the games we want to build.&lt;br /&gt;
&lt;br /&gt;
In the Unity editor, we create and add GameObjects to our scene, we then attach C# scripts to each that will all run upon starting the scene. Unity sort of runs everything for you, it reads through all the lights, cameras, meshes, behaviors… and processes it for you.&lt;br /&gt;
&lt;br /&gt;
==== How things work in Graal3D: ====&lt;br /&gt;
Since we will be using the Graal Unity Binding, things will be a bit different.&lt;br /&gt;
&lt;br /&gt;
The Graal Unity Binding is a binding between GraalScript and Unity, it is actually still in alpha, but most functionalities needed are present. The goal of this binding is to mimic the Unity C# scripting system (functions and classes). So if you are familiar with Unity and C#, everything should be easy. If not, then do not worry, I will go over everything step by step and include examples done in C# and compare them to GraalScript for each topic.&lt;br /&gt;
&lt;br /&gt;
The 3D Client (which you will have to download) will serve as the Unity editor, mentioned earlier, which contains the base scene where you instantiate your GameObjects and manipulate them with your GraalScripts.&lt;br /&gt;
&lt;br /&gt;
==== Required Downloads ====&lt;br /&gt;
'''Unity 2020.2.2f1:''' https://unity3d.com/get-unity/download/archive&lt;br /&gt;
&lt;br /&gt;
'''The Graal3D Client:''' https://drive.google.com/drive/u/0/folders/1rpOli0fxnA-Q7-IpYg3rUFJ44M0PsSxd&lt;br /&gt;
&lt;br /&gt;
'''RC:''' http://fp4.ca/windows_rc3_beta.zip&lt;br /&gt;
&lt;br /&gt;
==== Tools ====&lt;br /&gt;
In-game Unity Tools (''mimic the Unity Editor)'' &amp;amp; Game Functionality Tools ''(warping, fixing graphics, starting minigames...):'' &amp;lt;u&amp;gt;[[Tools]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
&lt;br /&gt;
==== Unity ====&lt;br /&gt;
&lt;br /&gt;
* [[Overview On Unity Basics]]&lt;br /&gt;
&lt;br /&gt;
==== AssetBundles ====&lt;br /&gt;
&lt;br /&gt;
* [[Uploading and Loading AssetBundles]]&lt;br /&gt;
*[[Placing GameObjects in NPC]]&lt;br /&gt;
* [[Syncing GameObjects]]&lt;br /&gt;
&lt;br /&gt;
==== Examples and Tutorials ====&lt;br /&gt;
*[[Getting Started Examples]]&lt;br /&gt;
*[[3DTutorials|Tutorials]]&lt;br /&gt;
*[[Unity UI]]&lt;br /&gt;
*[[Item Manager]]&lt;br /&gt;
&lt;br /&gt;
==== Classes, Functions and Variables ====&lt;br /&gt;
&lt;br /&gt;
* [https://quattro3d.graalonline.com/Documentation/ Quattro3D Scripting]&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Unity_UI&amp;diff=20915</id>
		<title>Unity UI</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Unity_UI&amp;diff=20915"/>
		<updated>2021-08-28T12:56:01Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:UnityUI.png|thumb|889x889px|none]]In this section we will go over an example of making a UI on unity and uploading and coding it on Client3D in graalscript.&lt;br /&gt;
&lt;br /&gt;
'''Unity Part:'''&lt;br /&gt;
&lt;br /&gt;
Open the “Quattro3D- Unity Project for bundle asset creation” folder using unity hub.&lt;br /&gt;
&lt;br /&gt;
To the assets folder, add we add a folder that will hold all the prefabs of the assetbundle.&lt;br /&gt;
&lt;br /&gt;
To the scene, add a Canvas (in the Hierarchy, right click -&amp;gt; UI -&amp;gt; Canvas). The Canvas will hold all the elements of our UI (buttons, text, scrollbar, images…).&lt;br /&gt;
&lt;br /&gt;
Select the Canvas and in the Inspector go to '''Canvas Scaler''' and select '''Scale With Screen''' for '''UI Scale Mode'''. This will allow the canvas Canvas to expand to full screen on all screens.&lt;br /&gt;
&lt;br /&gt;
Now to build the UI you see above (devtools). Start by adding Text elements (right click on Canvas -&amp;gt; UI -&amp;gt; Text).&lt;br /&gt;
&lt;br /&gt;
For each element, change the name and the text according to its function, change the color to white, add a button component and add a animation component. In the '''Rect Transform''' component, in the Anchor Presets, hold Alt and select top left to position your element.&lt;br /&gt;
&lt;br /&gt;
Add all the Text elements and position them (Inspector, Bundle Explorer, Console, Camera, Rendering).&lt;br /&gt;
&lt;br /&gt;
Now, to add the back button. Add an Image element to the UI, change its name to “back”, and in the image component add the source of the image (drop down in our case). Rotate it -90 deg on the Z axis for it to face left. Add a button component to turn it to a back button that closes the devtools.&lt;br /&gt;
&lt;br /&gt;
For the grey background you see, add and image just like before, change its color to black and change the A field in RGBA to 48 to make it transparent. Add an '''Outline''' component and change the '''Effect Color''' to white to add an outline to the image.&lt;br /&gt;
[[File:Unity UI.png|none|thumb|1006x1006px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now that we’ve added all our elements to the Canvas, it’s time to create our animations.&lt;br /&gt;
&lt;br /&gt;
To create an animation, in the top menu (next to Files, Edit, Assets…) go to Window -&amp;gt; Animation -&amp;gt; Animation.&lt;br /&gt;
&lt;br /&gt;
The animation tab should open in the bottom. Select the component you want to create an animation for and create and name the animation.&lt;br /&gt;
&lt;br /&gt;
We will be doing the sliding background image example for the animation. &lt;br /&gt;
&lt;br /&gt;
To record the animation, press on the record button. We want the image to slide in. So put the cursor on time 0s, and change the Pos X to -65 (outside of the screen) then move the cursor to 4s and change the Pos X back to 65. Press the record button again to save the recording. &lt;br /&gt;
[[File:Unity UI anim.png|none|thumb|1032x1032px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can press play to view your animation in action. To add the animation to the element; simply add an animation component and add the source of the animation you just created.&lt;br /&gt;
&lt;br /&gt;
Same thing goes for all the other animations.&lt;br /&gt;
&lt;br /&gt;
'''Graal Script Part:'''&lt;br /&gt;
&lt;br /&gt;
Now that we’ve created our prefabs and added the animations, our canvas is ready to be uploaded on the server and scripted. Save the AssetBundle and upload it to the server ([[Uploading and Loading AssetBundles]] for more info).&lt;br /&gt;
  findplayer(&amp;quot;Graal5918039&amp;quot;).addweapon(this.name);&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 &lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;dev&amp;quot;) toggle();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function toggle() {&lt;br /&gt;
   Quattro::AssetManagement::LoadAssetBundle(&amp;quot;devtoolsui&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onAssetBundleDownloaded(bundlename) {&lt;br /&gt;
   if (bundlename == &amp;quot;devtoolsui&amp;quot;) {&lt;br /&gt;
     SetTimer(9999);&lt;br /&gt;
     this.btns = {&amp;quot;inscpector&amp;quot;, &amp;quot;bundleexpl&amp;quot;, &amp;quot;console&amp;quot;, &amp;quot;camera&amp;quot;, &amp;quot;rendering&amp;quot;, &amp;quot;back&amp;quot;};&lt;br /&gt;
     this.devuiprefab = GameObject::createfromassetbundle(&amp;quot;devtoolsui&amp;quot;, &amp;quot;assets/menuui/canvasdevtools.prefab&amp;quot;);&lt;br /&gt;
     this.devui = Object::Instantiate(Type::GameObject, this.devuiprefab);&lt;br /&gt;
 &lt;br /&gt;
     for (btn : this.btns) {&lt;br /&gt;
       temp.btn = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, btn);&lt;br /&gt;
       Quattro::EventManager::AddEventHandlerTo(temp.btn.gameobject.GetComponent(Type::UI::Button));&lt;br /&gt;
       this.catcheventobject(temp.btn.gameobject, &amp;quot;onClick&amp;quot;, &amp;quot;onDevToolClick&amp;quot;);&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     Object::Destroy(this.devui, 4);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function onDevToolClick(go) {&lt;br /&gt;
   if (go.name == &amp;quot;inscpector&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;bundleexpl&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;console&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;camera&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;rendering&amp;quot;) player.chat = go.name;&lt;br /&gt;
   &lt;br /&gt;
   if (go.name == &amp;quot;back&amp;quot;) close();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function close() {&lt;br /&gt;
   for (btn : this.btns) {&lt;br /&gt;
     temp.btn = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, btn);&lt;br /&gt;
     Object::Destroy(temp.btn.gameobject);&lt;br /&gt;
   } &lt;br /&gt;
   &lt;br /&gt;
   temp.img = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, &amp;quot;Image&amp;quot;);&lt;br /&gt;
   temp.anim = temp.img.gameobject.GetComponent(Type::Animation);&lt;br /&gt;
   temp.anim.play(&amp;quot;devtools2&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
We load the assetbundle the usual way: &lt;br /&gt;
 Quattro::AssetManagement::LoadAssetBundle(&amp;quot;devtoolsui&amp;quot;);&lt;br /&gt;
 function onAssetBundleDownloaded(bundlename) {&lt;br /&gt;
   if (bundlename == &amp;quot;devtoolsui&amp;quot;) {&lt;br /&gt;
'''''Settimer(9999);''''' is necessary for the weapon to keep checking for button clicks.&lt;br /&gt;
&lt;br /&gt;
We create and instantiate the canvas prefab.&lt;br /&gt;
 this.devuiprefab = GameObject::createfromassetbundle(&amp;quot;devtoolsui&amp;quot;, &amp;quot;assets/menuui/canvasdevtools.prefab&amp;quot;);&lt;br /&gt;
 this.devui = Object::Instantiate(Type::GameObject, this.devuiprefab);&lt;br /&gt;
this will display the canvas on the client screen.&lt;br /&gt;
&lt;br /&gt;
To detect button clicks;&lt;br /&gt;
 temp.btn = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, btn);&lt;br /&gt;
 Quattro::EventManager::AddEventHandlerTo(temp.btn.gameobject.GetComponent(Type::UI::Button));&lt;br /&gt;
 this.catcheventobject(temp.btn.gameobject, &amp;quot;onClick&amp;quot;, &amp;quot;onDevToolClick&amp;quot;);&lt;br /&gt;
we first find the button GameObject by name ('''this.devui.transform''' being the transform component of the canvas, and '''btn''' is the button name we want to find).&lt;br /&gt;
&lt;br /&gt;
Next, we add an EventManager to the button component of the gameobject we just found ('''temp.btn.gameobject.GetComponent(Type::UI::Button)''').&lt;br /&gt;
&lt;br /&gt;
And '''this.catcheventobject(temp.btn.gameobject, &amp;quot;onClick&amp;quot;, &amp;quot;onDevToolClick&amp;quot;)''' to catch all the onClick events.&lt;br /&gt;
&lt;br /&gt;
Finally, we implement '''public function onDevToolClick(go)''' to add functionalities after button is pressed (with '''go''' the gameobject being pressed).&lt;br /&gt;
&lt;br /&gt;
For animations, to add or play an animation, you will need to get the animation component of the GameObject first. (using: '''temp.img.gameobject.GetComponent(Type::Animation)''')&lt;br /&gt;
 temp.img = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, &amp;quot;Image&amp;quot;);&lt;br /&gt;
 temp.anim = temp.img.gameobject.GetComponent(Type::Animation);&lt;br /&gt;
 temp.anim.play(&amp;quot;devtools2&amp;quot;);&lt;br /&gt;
(more script functionalities for animations available here: https://docs.unity3d.com/ScriptReference/Animation.html).&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=File:Unity_UI_anim.png&amp;diff=20914</id>
		<title>File:Unity UI anim.png</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=File:Unity_UI_anim.png&amp;diff=20914"/>
		<updated>2021-08-28T12:53:16Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;unity ui anim&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=File:Unity_UI.png&amp;diff=20913</id>
		<title>File:Unity UI.png</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=File:Unity_UI.png&amp;diff=20913"/>
		<updated>2021-08-28T12:51:00Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;unity UI&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=File:UI1.png&amp;diff=20912</id>
		<title>File:UI1.png</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=File:UI1.png&amp;diff=20912"/>
		<updated>2021-08-28T12:47:24Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;unity ui&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Unity_UI&amp;diff=20911</id>
		<title>Unity UI</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Unity_UI&amp;diff=20911"/>
		<updated>2021-08-22T18:51:02Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:UnityUI.png|thumb|889x889px|none]]&lt;br /&gt;
&lt;br /&gt;
In this section, we will go over an example of creating Unity UI and coding it in GraalScript.&lt;br /&gt;
&lt;br /&gt;
UNITY&lt;br /&gt;
&lt;br /&gt;
In your scene create a canvas (right click -&amp;gt; UI -&amp;gt; Canvas). The canvas will hold all your components (buttons, text, images...). Select the Canvas you created, and in the inspector go to '''Canvas Scaler''' and in the '''UI Scale Mode''' select &amp;quot;'''Scale with Screen'''&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Now you can start adding UI elements to your Canvas. To do so, right click on the Canvas -&amp;gt; UI -&amp;gt; text (example).&lt;br /&gt;
&lt;br /&gt;
To create the Canvas in the image above. Start by adding t&lt;br /&gt;
 findplayer(&amp;quot;Graal5918039&amp;quot;).addweapon(this.name);&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 &lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;dev&amp;quot;) toggle();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function toggle() {&lt;br /&gt;
   Quattro::AssetManagement::LoadAssetBundle(&amp;quot;devtoolsui&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onAssetBundleDownloaded(bundlename) {&lt;br /&gt;
   if (bundlename == &amp;quot;devtoolsui&amp;quot;) {&lt;br /&gt;
     SetTimer(9999);&lt;br /&gt;
     this.btns = {&amp;quot;inscpector&amp;quot;, &amp;quot;bundleexpl&amp;quot;, &amp;quot;console&amp;quot;, &amp;quot;camera&amp;quot;, &amp;quot;rendering&amp;quot;, &amp;quot;back&amp;quot;};&lt;br /&gt;
     this.devuiprefab = GameObject::createfromassetbundle(&amp;quot;devtoolsui&amp;quot;, &amp;quot;assets/menuui/canvasdevtools.prefab&amp;quot;);&lt;br /&gt;
     this.devui = Object::Instantiate(Type::GameObject, this.devuiprefab);&lt;br /&gt;
 &lt;br /&gt;
     for (btn : this.btns) {&lt;br /&gt;
       temp.btn = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, btn);&lt;br /&gt;
       Quattro::EventManager::AddEventHandlerTo(temp.btn.gameobject.GetComponent(Type::UI::Button));&lt;br /&gt;
       this.catcheventobject(temp.btn.gameobject, &amp;quot;onClick&amp;quot;, &amp;quot;onDevToolClick&amp;quot;);&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     Object::Destroy(this.devui, 4);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function onDevToolClick(go) {&lt;br /&gt;
   if (go.name == &amp;quot;inscpector&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;bundleexpl&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;console&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;camera&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;rendering&amp;quot;) player.chat = go.name;&lt;br /&gt;
   &lt;br /&gt;
   if (go.name == &amp;quot;back&amp;quot;) close();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function close() {&lt;br /&gt;
   for (btn : this.btns) {&lt;br /&gt;
     temp.btn = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, btn);&lt;br /&gt;
     Object::Destroy(temp.btn.gameobject);&lt;br /&gt;
   } &lt;br /&gt;
   &lt;br /&gt;
   temp.img = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, &amp;quot;Image&amp;quot;);&lt;br /&gt;
   temp.anim = temp.img.gameobject.GetComponent(Type::Animation);&lt;br /&gt;
   temp.anim.play(&amp;quot;devtools2&amp;quot;);&lt;br /&gt;
 }&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Unity_UI&amp;diff=20910</id>
		<title>Unity UI</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Unity_UI&amp;diff=20910"/>
		<updated>2021-08-22T17:37:18Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:UnityUI.png|thumb|889x889px|none]]&lt;br /&gt;
&lt;br /&gt;
In this section, we will go over an example of creating Unity UI and coding it in graalscript&lt;br /&gt;
 findplayer(&amp;quot;Graal5918039&amp;quot;).addweapon(this.name);&lt;br /&gt;
 &lt;br /&gt;
 //#CLIENTSIDE&lt;br /&gt;
 &lt;br /&gt;
 function onPlayerChats() {&lt;br /&gt;
   if (player.chat == &amp;quot;dev&amp;quot;) toggle();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function toggle() {&lt;br /&gt;
   Quattro::AssetManagement::LoadAssetBundle(&amp;quot;devtoolsui&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 function onAssetBundleDownloaded(bundlename) {&lt;br /&gt;
   if (bundlename == &amp;quot;devtoolsui&amp;quot;) {&lt;br /&gt;
     SetTimer(9999);&lt;br /&gt;
     this.btns = {&amp;quot;inscpector&amp;quot;, &amp;quot;bundleexpl&amp;quot;, &amp;quot;console&amp;quot;, &amp;quot;camera&amp;quot;, &amp;quot;rendering&amp;quot;, &amp;quot;back&amp;quot;};&lt;br /&gt;
     this.devuiprefab = GameObject::createfromassetbundle(&amp;quot;devtoolsui&amp;quot;, &amp;quot;assets/menuui/canvasdevtools.prefab&amp;quot;);&lt;br /&gt;
     this.devui = Object::Instantiate(Type::GameObject, this.devuiprefab);&lt;br /&gt;
 &lt;br /&gt;
     for (btn : this.btns) {&lt;br /&gt;
       temp.btn = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, btn);&lt;br /&gt;
       Quattro::EventManager::AddEventHandlerTo(temp.btn.gameobject.GetComponent(Type::UI::Button));&lt;br /&gt;
       this.catcheventobject(temp.btn.gameobject, &amp;quot;onClick&amp;quot;, &amp;quot;onDevToolClick&amp;quot;);&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     Object::Destroy(this.devui, 4);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function onDevToolClick(go) {&lt;br /&gt;
   if (go.name == &amp;quot;inscpector&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;bundleexpl&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;console&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;camera&amp;quot;) player.chat = go.name;&lt;br /&gt;
   if (go.name == &amp;quot;rendering&amp;quot;) player.chat = go.name;&lt;br /&gt;
   &lt;br /&gt;
   if (go.name == &amp;quot;back&amp;quot;) close();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 public function close() {&lt;br /&gt;
   for (btn : this.btns) {&lt;br /&gt;
     temp.btn = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, btn);&lt;br /&gt;
     Object::Destroy(temp.btn.gameobject);&lt;br /&gt;
   } &lt;br /&gt;
   &lt;br /&gt;
   temp.img = Quattro::TransformExtensions::FindDeepChild(this.devui.transform, &amp;quot;Image&amp;quot;);&lt;br /&gt;
   temp.anim = temp.img.gameobject.GetComponent(Type::Animation);&lt;br /&gt;
   temp.anim.play(&amp;quot;devtools2&amp;quot;);&lt;br /&gt;
 }&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Graal3D_Scripting_Manual&amp;diff=20909</id>
		<title>Graal3D Scripting Manual</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Graal3D_Scripting_Manual&amp;diff=20909"/>
		<updated>2021-08-22T17:35:42Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: /* Examples and Tutorials */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Intro ==&lt;br /&gt;
[[File:Graal kart start.jpg|center|frame]]&lt;br /&gt;
Welcome to the Graal3D Scripting Manual!&lt;br /&gt;
&lt;br /&gt;
This Manual comes in handy for beginners wanting to learn Graal3D Scripting, and advanced developers looking to expand their knowledge, as it  contains documentation, examples, tutorials and much more...&lt;br /&gt;
&lt;br /&gt;
What we will focus on in this Manual is programming our gameplay (scripting the behavior of our GameObjects, their interactions, the components attached to them...)&lt;br /&gt;
&lt;br /&gt;
==== How things work in Unity: ====&lt;br /&gt;
Unity is the leading platform for building 2D, 3D, VR and augmented reality games. It offers a scripting API in C#, allowing us to interact with the unity editor and the games we want to build.&lt;br /&gt;
&lt;br /&gt;
In the Unity editor, we create and add GameObjects to our scene, we then attach C# scripts to each that will all run upon starting the scene. Unity sort of runs everything for you, it reads through all the lights, cameras, meshes, behaviors… and processes it for you.&lt;br /&gt;
&lt;br /&gt;
==== How things work in Graal3D: ====&lt;br /&gt;
Since we will be using the Graal Unity Binding, things will be a bit different.&lt;br /&gt;
&lt;br /&gt;
The Graal Unity Binding is a binding between GraalScript and Unity, it is actually still in alpha, but most functionalities needed are present. The goal of this binding is to mimic the Unity C# scripting system (functions and classes). So if you are familiar with Unity and C#, everything should be easy. If not, then do not worry, I will go over everything step by step and include examples done in C# and compare them to GraalScript for each topic.&lt;br /&gt;
&lt;br /&gt;
The 3D Client (which you will have to download) will serve as the Unity editor, mentioned earlier, which contains the base scene where you instantiate your GameObjects and manipulate them with your GraalScripts.&lt;br /&gt;
&lt;br /&gt;
==== Required Downloads ====&lt;br /&gt;
'''Unity 2020.2.2f1:''' https://unity3d.com/get-unity/download/archive&lt;br /&gt;
&lt;br /&gt;
'''The Graal3D Client:''' https://drive.google.com/drive/u/0/folders/1rpOli0fxnA-Q7-IpYg3rUFJ44M0PsSxd&lt;br /&gt;
&lt;br /&gt;
'''RC:''' http://fp4.ca/windows_rc3_beta.zip&lt;br /&gt;
&lt;br /&gt;
==== Tools ====&lt;br /&gt;
In game Unity Tools (''mimic the Unity Editor)'' &amp;amp; Game Functionality Tools ''(warping, fixing graphics, starting minigames...):'' &amp;lt;u&amp;gt;[[Tools]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
&lt;br /&gt;
==== Unity ====&lt;br /&gt;
&lt;br /&gt;
* [[Overview On Unity Basics]]&lt;br /&gt;
&lt;br /&gt;
==== AssetBundles ====&lt;br /&gt;
&lt;br /&gt;
* [[Uploading and Loading AssetBundles]]&lt;br /&gt;
*[[Placing GameObjects in NPC]]&lt;br /&gt;
* [[Syncing GameObjects]]&lt;br /&gt;
&lt;br /&gt;
==== Examples and Tutorials ====&lt;br /&gt;
*[[Getting Started Examples]]&lt;br /&gt;
*[[3DTutorials|Tutorials]]&lt;br /&gt;
*[[Unity UI]]&lt;br /&gt;
*[[Item Manager]]&lt;br /&gt;
&lt;br /&gt;
==== Classes, Functions and Variables ====&lt;br /&gt;
&lt;br /&gt;
* [https://quattro3d.graalonline.com/Documentation/ Quattro3D Scripting]&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Unity_UI&amp;diff=20908</id>
		<title>Unity UI</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Unity_UI&amp;diff=20908"/>
		<updated>2021-08-21T16:37:23Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:UnityUI.png|thumb|889x889px|none]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In this section, we will go over an example of creating Unity UI and coding it in graalscript&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Unity_UI&amp;diff=20907</id>
		<title>Unity UI</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Unity_UI&amp;diff=20907"/>
		<updated>2021-08-21T15:49:18Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: Created page with &amp;quot;889x889px&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:UnityUI.png|left|thumb|889x889px]]&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=File:UnityUI.png&amp;diff=20906</id>
		<title>File:UnityUI.png</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=File:UnityUI.png&amp;diff=20906"/>
		<updated>2021-08-21T15:47:41Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;unity ui image&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
	<entry>
		<id>https://graalonline.net/index.php?title=Graal3D_Scripting_Manual&amp;diff=20905</id>
		<title>Graal3D Scripting Manual</title>
		<link rel="alternate" type="text/html" href="https://graalonline.net/index.php?title=Graal3D_Scripting_Manual&amp;diff=20905"/>
		<updated>2021-08-20T16:26:54Z</updated>

		<summary type="html">&lt;p&gt;JimmyAkl: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Intro ==&lt;br /&gt;
[[File:Graal kart start.jpg|center|frame]]&lt;br /&gt;
Welcome to the Graal3D Scripting Manual!&lt;br /&gt;
&lt;br /&gt;
This Manual comes in handy for beginners wanting to learn Graal3D Scripting, and advanced developers looking to expand their knowledge, as it  contains documentation, examples, tutorials and much more...&lt;br /&gt;
&lt;br /&gt;
What we will focus on in this Manual is programming our gameplay (scripting the behavior of our GameObjects, their interactions, the components attached to them...)&lt;br /&gt;
&lt;br /&gt;
==== How things work in Unity: ====&lt;br /&gt;
Unity is the leading platform for building 2D, 3D, VR and augmented reality games. It offers a scripting API in C#, allowing us to interact with the unity editor and the games we want to build.&lt;br /&gt;
&lt;br /&gt;
In the Unity editor, we create and add GameObjects to our scene, we then attach C# scripts to each that will all run upon starting the scene. Unity sort of runs everything for you, it reads through all the lights, cameras, meshes, behaviors… and processes it for you.&lt;br /&gt;
&lt;br /&gt;
==== How things work in Graal3D: ====&lt;br /&gt;
Since we will be using the Graal Unity Binding, things will be a bit different.&lt;br /&gt;
&lt;br /&gt;
The Graal Unity Binding is a binding between GraalScript and Unity, it is actually still in alpha, but most functionalities needed are present. The goal of this binding is to mimic the Unity C# scripting system (functions and classes). So if you are familiar with Unity and C#, everything should be easy. If not, then do not worry, I will go over everything step by step and include examples done in C# and compare them to GraalScript for each topic.&lt;br /&gt;
&lt;br /&gt;
The 3D Client (which you will have to download) will serve as the Unity editor, mentioned earlier, which contains the base scene where you instantiate your GameObjects and manipulate them with your GraalScripts.&lt;br /&gt;
&lt;br /&gt;
==== Required Downloads ====&lt;br /&gt;
'''Unity 2020.2.2f1:''' https://unity3d.com/get-unity/download/archive&lt;br /&gt;
&lt;br /&gt;
'''The Graal3D Client:''' https://drive.google.com/drive/u/0/folders/1rpOli0fxnA-Q7-IpYg3rUFJ44M0PsSxd&lt;br /&gt;
&lt;br /&gt;
'''RC:''' http://fp4.ca/windows_rc3_beta.zip&lt;br /&gt;
&lt;br /&gt;
==== Tools ====&lt;br /&gt;
In game Unity Tools (''mimic the Unity Editor)'' &amp;amp; Game Functionality Tools ''(warping, fixing graphics, starting minigames...):'' &amp;lt;u&amp;gt;[[Tools]]&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
&lt;br /&gt;
==== Unity ====&lt;br /&gt;
&lt;br /&gt;
* [[Overview On Unity Basics]]&lt;br /&gt;
&lt;br /&gt;
==== AssetBundles ====&lt;br /&gt;
&lt;br /&gt;
* [[Uploading and Loading AssetBundles]]&lt;br /&gt;
*[[Placing GameObjects in NPC]]&lt;br /&gt;
* [[Syncing GameObjects]]&lt;br /&gt;
&lt;br /&gt;
==== Examples and Tutorials ====&lt;br /&gt;
*[[Getting Started Examples]]&lt;br /&gt;
*[[3DTutorials|Tutorials]]&lt;br /&gt;
*[[Item Manager]]&lt;br /&gt;
&lt;br /&gt;
==== Classes, Functions and Variables ====&lt;br /&gt;
&lt;br /&gt;
* [https://quattro3d.graalonline.com/Documentation/ Quattro3D Scripting]&lt;/div&gt;</summary>
		<author><name>JimmyAkl</name></author>
	</entry>
</feed>