{"id":195,"date":"2023-06-06T16:05:05","date_gmt":"2023-06-06T20:05:05","guid":{"rendered":"https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/?p=195"},"modified":"2023-06-06T16:05:17","modified_gmt":"2023-06-06T20:05:17","slug":"day-16-2d-physics","status":"publish","type":"post","link":"https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/?p=195","title":{"rendered":"Day 16: 2D Physics"},"content":{"rendered":"\n<p>Today we started into our new Side Scroller project with an overview of the 2D configuration of the Unity Editor, as well as an introduction to sorting layers and 2D Physics, creating a simple &#8220;top-down&#8221; character controller.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h2 class=\"wp-block-heading\">Part 1: 2D Basics<\/h2>\n\n\n\n<p>An important distinction to make about building a 2D game in Unity is that it is all the same Unity game engine.  There are 2D and 3D capabilities built into the engine, but up to now we have dealt exclusively in the 3D realm.  To make development (and the file-size of a project) efficient, many of the packages that are specific to 2D are turned off in the 3D templates.   The best way for us to activate these packages is to launch a new project, but use the built-in <strong>2D Template <\/strong>instead.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1013\" height=\"595\" src=\"https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/wp-content\/uploads\/2022\/06\/image-5.png\" alt=\"\" class=\"wp-image-94\" srcset=\"https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/wp-content\/uploads\/2022\/06\/image-5.png 1013w, https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/wp-content\/uploads\/2022\/06\/image-5-300x176.png 300w, https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/wp-content\/uploads\/2022\/06\/image-5-768x451.png 768w\" sizes=\"(max-width: 1013px) 100vw, 1013px\" \/><figcaption class=\"wp-element-caption\">f <\/figcaption><\/figure><\/div>\n\n\n<p>When we launch this, our editor will look mostly the same, with a few small, but significant differences.  First, you will notice that our Scene window is set to &#8220;2D&#8221; mode, with our camera facing the XY plane.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1022\" height=\"618\" src=\"https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/wp-content\/uploads\/2022\/06\/image-6.png\" alt=\"\" class=\"wp-image-95\" srcset=\"https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/wp-content\/uploads\/2022\/06\/image-6.png 1022w, https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/wp-content\/uploads\/2022\/06\/image-6-300x181.png 300w, https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/wp-content\/uploads\/2022\/06\/image-6-768x464.png 768w\" sizes=\"(max-width: 1022px) 100vw, 1022px\" \/><\/figure><\/div>\n\n\n<p>You will also notice that our scene only include a camera &#8211; by default there is no directional light, because we will be using <strong>sprite rendering<\/strong> in this project instead.   Also, our <strong>Main Camera<\/strong> is a little different &#8211; our <strong>Projection<\/strong> is set to <strong>Orthographic<\/strong>, and there is no <strong>Skybox<\/strong>.  (There can be a skybox, but none is included by default, so the <strong>Clear Flags<\/strong> option falls back to the <strong>Solid Color<\/strong> designation.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img decoding=\"async\" src=\"https:\/\/courses.ideate.cmu.edu\/53-353\/f2020\/wp-content\/uploads\/2020\/11\/image-3.png\" alt=\"\" class=\"wp-image-131\"\/><\/figure><\/div>\n\n\n<p>While the 2D \/ Orthographic camera <em>can<\/em> be used to render 3D content &#8211; remember, we did this with our Pong game &#8211; the primary method of drawing objects on the screen for 2D content is to use <strong>Sprites<\/strong>.<\/p>\n\n\n\n<p>\u201cSprite\u201d is a term that has been used in the video game industry almost since it\u2019s inception. In the beginning, it referred to an image of a specific size and type that could be drawn directly to the the screen without having to be processed by the CPU, and was used to improve the performance of a game. These days, the term refers to any bitmap (or image) that is used primarily as a 2D object in a game.<\/p>\n\n\n\n<p>For now, we will use Unity&#8217;s built-in sprites which are simple shapes that we can use to explore layers and physics. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Part 2: Sorting Layers<\/h3>\n\n\n\n<p>Sprite rendering works differently than 3D rendering &#8211; there are no polygons to receive and reflect light, and so the images used for sprites are simply presented (and rendered) as-is.  The <strong>Sprite Renderer<\/strong> has different properties than the <strong>Mesh Renderer<\/strong> that we have previously used, including two very important ones &#8211; the <strong>Sorting Layer<\/strong> and the <strong>Order in Layer<\/strong>, and Unity&#8217;s rendering engine uses these values to determine which object to draw on top of another.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"439\" height=\"230\" src=\"https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/wp-content\/uploads\/2023\/06\/image.png\" alt=\"\" class=\"wp-image-196\" srcset=\"https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/wp-content\/uploads\/2023\/06\/image.png 439w, https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/wp-content\/uploads\/2023\/06\/image-300x157.png 300w\" sizes=\"(max-width: 439px) 100vw, 439px\" \/><\/figure><\/div>\n\n\n<p>The <strong>Sorting Layer<\/strong> is given top priority in rendering.  The higher the Sorting Layer&#8217;s index (as defined in the <strong>Tags &amp; Layers<\/strong> panel that we&#8217;ve used before), the closer to the camera this layer will render, regardless of other attributes like distance (unless the sprite is behind the camera, and thus outside of the view frustrum).    These are especially useful as we set up rules for our tilemaps, so that we can generate proper layers without having to worry about actual z-depths.<\/p>\n\n\n\n<p>The next level of sorting priority when drawing is the <strong>Order in Layer<\/strong> setting.  Overlapping objects that are contained within the same layer will use this numeric value to determine which should draw on top of the other &#8211; the higher number sprite drawing over top of the lower numbered sprite.  (These numbers can also be negative, and these values can be changed programmatically if need be).<\/p>\n\n\n\n<p>In the event that overlapping sprites do not have different layers or layer orders, then there are a few other comparisons such as distance from camera (as determined by the pivot point).  But if you have overlapping sprites, it&#8217;s best to use these systems.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Part 3: 2D Physics &amp; a Top-Down Controller<\/h3>\n\n\n\n<p>Unity&#8217;s 2D physics system relies on a different physics library than the 3D system, and so the sprites that we create will use a separate set of components when operating in the 2D physics world.  There is a <strong>Rigidbody2D<\/strong> type component that performs the same task as the 3D Rigidbody, but only operates on the XY plane with the only possible rotation happening on the Z axis, towards the camera).<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"758\" height=\"408\" src=\"https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/wp-content\/uploads\/2023\/06\/image-1.png\" alt=\"\" class=\"wp-image-197\" srcset=\"https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/wp-content\/uploads\/2023\/06\/image-1.png 758w, https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/wp-content\/uploads\/2023\/06\/image-1-300x161.png 300w\" sizes=\"(max-width: 758px) 100vw, 758px\" \/><\/figure><\/div>\n\n\n<p>There are also a set of <strong>2D Colliders<\/strong> which work with this system, including a <strong>BoxCollider2D<\/strong>, a <strong>CircleCollider2D<\/strong> and a <strong>CapsuleCollider2D<\/strong>.  It is important to note that collision detection also relies upon its own method, <strong>OnCollisionEnter2D(Collision2D collision)<\/strong>.<\/p>\n\n\n\n<p>As a demo today, we built a simple environment using multiple square sprites (stretched to form rectangles), plus a few sprites with the Rigidbody controller attached.  We used the <strong>Rigidbody2D.MovePosition( ) <\/strong>function to move our sprite towards a location that we defined as the current position + a directional offset (using the <strong>Input.GetAxis( )<\/strong> for horizontal and vertical dimensions).<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<pre class=\"wp-block-preformatted\">TopDownCharacterController.cs<\/pre>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">using System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\n\npublic class TopDownCharacterController : MonoBehaviour\n{\n    public float speed = 1.0f;\n\n    private Rigidbody2D rb;\n    private Vector2 direction;\n\n\n    \/\/ Start is called before the first frame update\n    void Start()\n    {\n        rb = GetComponent&lt;Rigidbody2D>(); \/\/ get the rigidbody for this object\n        direction = new Vector2();\n    }\n\n    \/\/ Update is called once per frame\n    void Update()\n    {\n        \/\/ get the movement inputs\n        direction.x = Input.GetAxisRaw(\"Horizontal\");\n        direction.y = Input.GetAxisRaw(\"Vertical\");\n\n    }\n\n    private void FixedUpdate()\n    {\n        if (rb)\n        {\n            \/\/ move the controller\n            rb.MovePosition(rb.position + (direction.normalized * speed * Time.fixedDeltaTime));\n        } else\n        {\n            Debug.Log(\"Missing a Rigidbody 2D component\");\n        }\n    }\n}\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p><a class=\"more-link\"  href=\"https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/?p=195\"><span class=\"more-text\"><\/span><\/a><\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"greenlet_layout":[]},"categories":[6],"tags":[],"_links":{"self":[{"href":"https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/index.php?rest_route=\/wp\/v2\/posts\/195"}],"collection":[{"href":"https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/index.php?rest_route=\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=195"}],"version-history":[{"count":1,"href":"https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/index.php?rest_route=\/wp\/v2\/posts\/195\/revisions"}],"predecessor-version":[{"id":198,"href":"https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/index.php?rest_route=\/wp\/v2\/posts\/195\/revisions\/198"}],"wp:attachment":[{"href":"https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=195"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=195"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/courses.ideate.cmu.edu\/53-353\/m2023\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=195"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}