{"id":1049,"date":"2015-01-03T11:11:35","date_gmt":"2015-01-03T11:11:35","guid":{"rendered":"http:\/\/www.nikola-breznjak.com\/blog\/?p=1049"},"modified":"2015-08-10T07:10:13","modified_gmt":"2015-08-10T07:10:13","slug":"unity3d-ball-roller","status":"publish","type":"post","link":"https:\/\/nikola-breznjak.com\/blog\/codeproject\/unity3d-ball-roller\/","title":{"rendered":"How to make a Unity3D Ball Roller game"},"content":{"rendered":"<p>I followed\u00a0<a href=\"http:\/\/unity3d.com\/learn\/tutorials\/projects\/roll-a-ball\">http:\/\/unity3d.com\/learn\/tutorials\/projects\/roll-a-ball<\/a>, and updated the steps for the newest Unity3D currently available (4.5). You can <a href=\"http:\/\/nikola-breznjak.com\/_testings\/Unity\/Ball\/\">try the game<\/a> and<a href=\"https:\/\/github.com\/Hitman666\/BallRollerUnity3D\"> download the project<\/a> on GitHub.<\/p>\n<ol>\n<li>Create a new 3D project and save a scene in a <strong>Assets\/Scenes<\/strong> folder<\/li>\n<li>Game object &#8211; 3d object &#8211; Plane, and rename to <em>Ground<\/em><\/li>\n<li>Transform &#8211; Reset -&gt; sets to 0,0,0 origin point of the world<\/li>\n<li>Edit &#8211; Frame selected or character F<\/li>\n<li>Hierarchy -&gt; Create -&gt; 3D object -&gt; Sphere, and again Transform &#8211; Reset and again Edit &#8211; Frame selected, rename it to <em>Player<\/em><\/li>\n<li>Hierarchy -&gt; Create -&gt; Light -&gt; Directional light (name it <em>Main Light<\/em>)\n<ol>\n<li>Rotation x 30, y 60<\/li>\n<li>Shadow &#8211; Soft<\/li>\n<li>Very high resolution<\/li>\n<\/ol>\n<\/li>\n<li><span style=\"line-height: 1.5;\">Duplicate <em>Main Light<\/em>\u00a0and reverse the\u00a0Rotation x -30, y -60<\/span><\/li>\n<li><span style=\"line-height: 1.5;\">Color &#8211; some blue, intensity 0.1, no shadows<\/span><\/li>\n<li><em>We use Folders in Project tab to organize stuff and Empty game objects in Hierarchy tab<\/em><\/li>\n<li><span style=\"line-height: 1.5;\">Create empty object and rename to <em>Lighting<\/em><\/span>\n<ol>\n<li><span style=\"line-height: 1.5;\">reset transform origin, drag other lighting related object in here<\/span><\/li>\n<li>set the y position to 100 so that you move the lighting up (<em>they are based on rotation and not position so that if you place it high up it&#8217;s just a matter of &#8220;not getting in the way&#8221; and they will still work as expected<\/em>)<\/li>\n<\/ol>\n<\/li>\n<li><span style=\"line-height: 1.5;\"><em>Player<\/em> object -&gt; add Component -&gt; Physics\u00a0<\/span>-&gt; Rigidbody<\/li>\n<li>[<strong>Moving the player<\/strong>] Create a <strong>Scripts<\/strong> folder. Create a script (on the Player object add Component -&gt; New Script) and place it in this folder\n<ol>\n<li>Update() &#8211; here goes the game code (before rendering the frame)<\/li>\n<li>FixedUpdate() &#8211; here goes the physics code (before performing any physics calculation)<\/li>\n<li>To read an axis use Input.GetAxis with one of the following default axes: &#8220;Horizontal&#8221; and &#8220;Vertical&#8221; are mapped to joystick, A, W, S, D and the arrow keys. &#8220;Mouse X&#8221; and &#8220;Mouse Y&#8221; are mapped to the mouse delta. &#8220;Fire1&#8221;, &#8220;Fire2&#8221; &#8220;Fire3&#8221; are mapped to Ctrl, Alt, Cmd keys and three mouse or joystick buttons.<\/li>\n<li>Add this script:\n<pre class=\"lang:default decode:true\">var speed : float;\r\nfunction FixedUpdate () {\r\n\tvar moveHorizontal = Input.GetAxis(\"Horizontal\");\r\n\tvar moveVertical = Input.GetAxis(\"Vertical\");\r\n\t\r\n\tvar movement = Vector3(moveHorizontal, 0.0f, moveVertical);\r\n\t\r\n\trigidbody.AddForce(movement * speed * Time.deltaTime);\r\n}<\/pre>\n<\/li>\n<\/ol>\n<\/li>\n<li>[<strong>Moving the camera<\/strong>] Raise the camera a little and tilt it by setting the rotation. Make it the child of the player (drag the <em>Main Camera\u00a0<\/em>to <em>Player<\/em> object). If you run the game at this point you will see all went bazinga. So, we can&#8217;t have it as a child &#8211; detach it. What we can do however is attach a script to the camera and offset it based on the position of the player object:\n<ol>\n<li>Add script to <em><em>Main Camera:<br \/>\n<\/em><\/em><\/p>\n<pre class=\"lang:default decode:true\">var player : GameObject;\r\nprivate var offset : Vector3;\r\nfunction Start () {\r\n    offset = transform.position;\r\n}\r\n\r\nfunction LateUpdate () {   \r\n    transform.position = player.transform.position + offset;\r\n}<\/pre>\n<\/li>\n<\/ol>\n<\/li>\n<li>[<strong>Adding the walls<\/strong>] &#8211; Add new empty object <em>Walls<\/em>\n<ol>\n<li>Create -&gt; 3D object -&gt;\u00a0Cube (rename to\u00a0<em>West Wall<\/em>) and add it as a child to <em>Walls<\/em><\/li>\n<li>repeat for other 3 walls<\/li>\n<\/ol>\n<\/li>\n<li>[<strong>Adding collectible objects<\/strong>]\n<ol>\n<li>Create -&gt; 3D object -&gt; Cube (rename to <em>Pickup<\/em>)<\/li>\n<li>Reset transform origin<\/li>\n<li>Scale to 0.5 on all axes<\/li>\n<li>Rotate 45\u00b0 on all axes<\/li>\n<li>Add a script (<em>Rotator<\/em>):\n<pre class=\"lang:default decode:true\">function Update () {\r\n\ttransform.Rotate(Vector3(15,30,45) * Time.deltaTime);\r\n}<\/pre>\n<\/li>\n<li>Create a new folder called <strong>Prefabs<\/strong>\u00a0in the root directory and drag the <em>Pickup<\/em>\u00a0object inside it in order to, well, create a <em>Prefab\u00a0<\/em>which you can think of as a variable which you can then access with all its parameters. So, when you clone the prefab object, it will have all the behavior that the cloned prefab has.<\/li>\n<li>Create an empty object and drag the prefab inside it<\/li>\n<li>Set orientation to global mode and duplicate a few of the collectibles<\/li>\n<\/ol>\n<\/li>\n<li>[<strong>Collision detection<\/strong>]\n<ol>\n<li>Add the tag &#8216;PickUp&#8217; to the <em>Pickup<\/em> <strong>prefab<\/strong><\/li>\n<li>Add the following function to the <em>Player<\/em> object script:\n<pre class=\"lang:default decode:true\">function OnTriggerEnter(other : Collider){\r\n    if(other.gameObject.tag == 'PickUp')\r\n        other.gameObject.setActive(false);\r\n}<\/pre>\n<\/li>\n<li>Set Box collider <strong>Is Trigger<\/strong>\u00a0to true in the\u00a0Pickup prefab and this gives you OnTrigger function<\/li>\n<li>Unity caches all the static colliders &#8211; everytime we move, rotate or scale the static colliders, the Unity will recalculate the cache &#8211; takes resources!\u00a0We can move, rotate or scale dynamic colliders and Unity will not cache them.\u00a0Any game object with a collider and a rigid body is considered a <strong>dynamic<\/strong>\u00a0object.\u00a0Any game object with a collider and no rigid body is considered a static\u00a0object<\/li>\n<li>Add a rigidbody to the <strong><em>Pickup<\/em> prefab<\/strong>. If you start the game now, the Pickup object will fall to the ground because of the <strong>Gravity<\/strong>. You can uncheck the Gravity option, but a better solution is to keep it and check the <strong>Is Kinematic <\/strong>option.<\/li>\n<li>Static colliders shouldn&#8217;t move &#8211; walls and floors<\/li>\n<li>Dynamic colliders can move and have a rigidbody attached<\/li>\n<li>Standard rigid bodies are moved using physics forces and Kinematic rigid bodies are moved using transform object<\/li>\n<\/ol>\n<\/li>\n<li>[<strong>Counting picked up object<\/strong>]\n<ol>\n<li>Add a new variable to the PlayerController script and increment it in the OnTriggerEnter function<\/li>\n<li>Add a new empty game object<\/li>\n<li>Choose &#8220;Add Component&#8221; -&gt;\u00a0&#8220;Rendering&#8221; -&gt;\u00a0&#8220;GUIText&#8221;<\/li>\n<li>Transform position (x,y,z) = (0,1,0)<\/li>\n<li>Anchor &#8211; upper left<\/li>\n<li>Alignment &#8211; center<\/li>\n<li>Pixel offset &#8211; 5,5<\/li>\n<li>Font size &#8211; 20<\/li>\n<li>Add the GUIText variable to the PlayerController script:\n<pre class=\"lang:default decode:true\">public var scoreText : GUIText;\r\nfunction SetCountText(){\r\n\tscoreText.text = 'Score: ' + score.ToString();\r\n}<\/pre>\n<\/li>\n<li>Do the same with the winText (create object, add the public variable in PlayerController script) and drag it to the Player object<\/li>\n<\/ol>\n<\/li>\n<li>[<strong>Publishing the game<\/strong>]\n<ol>\n<li>File -&gt; Build Settings<\/li>\n<li>Select the target platform<\/li>\n<li>Click on the Switch platform button<\/li>\n<li>Click on the Buildbutton<\/li>\n<\/ol>\n<\/li>\n<li>[<strong>Added bonus<\/strong>]\n<ol>\n<li>To create a Physics Material select Assets-&gt;Create-&gt;Physics Material from the menu bar. Then drag the Physics Material from the Project View onto a Collider in the scene.<\/li>\n<li>This way you can make the walls bounce the ball<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>I followed\u00a0http:\/\/unity3d.com\/learn\/tutorials\/projects\/roll-a-ball, and updated the steps for the newest Unity3D currently available (4.5). You can try the game and download the project on GitHub. Create a new 3D&hellip;<\/p>\n","protected":false},"author":1,"featured_media":1059,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8,41],"tags":[],"class_list":["post-1049","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codeproject","category-unity3d"],"_links":{"self":[{"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/posts\/1049","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/comments?post=1049"}],"version-history":[{"count":7,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/posts\/1049\/revisions"}],"predecessor-version":[{"id":2039,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/posts\/1049\/revisions\/2039"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/media\/1059"}],"wp:attachment":[{"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/media?parent=1049"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/categories?post=1049"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nikola-breznjak.com\/blog\/wp-json\/wp\/v2\/tags?post=1049"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}