====== Unity3D environtment (2D) ====== ===== Basic tasks ===== ==== Assets folder structure ==== * animations * plugins * prefabs * scenes * scripts * sounds * sprites ==== Sprites ==== * To **add an sprite** add it to the folder using windows explorer. To add it to the scene drag it from Project window to hierarchy or Scene window. * To **create multiple sprites from one** you need to change the sprite mode property from Single to Multiple. Then you can slice your sprite using the Sprite Editor tool. * If you drag a set of sprites to the scene, Unity will create an animation with them. * You can use a sorting layer for the background. It's composed by sub-layers which will be arranged and could be locked with the aim of not edit them by accident. ===== Scripting ===== ==== Basic ==== === Inherited functions === * Lifetime functions: * ''Awake()'', it's called while the script is loaded. Used to initialize instances. At this point it can not interact with other GameObjects. * ''Start()'', it's called after Awake(). The difference is that this method won't be called if the script is not enabled. * ''Update()'', update funcition, one by frame. * ''FixedUpdate()'', update function to be used for physic operations. It will be called so many times as needed before drawing a frame. * ''Destroy()'', called when the object is destroyed. * ''LateUpdate()'' * ''OnDisable()'' * ''OnGUI()'' Properties * ''transform'', contains the methods and objects to move the object. === Interact with objects === * ''DontDestroyOnLoad(object)'', the object can be this, :!: * ''Instantiate(GameObject)'' * ''Invoke(name, time)'' * ''GameObject.Find(name)'' * ''gameObject.GetComponent()'' gets the first component (script, whatever...) from a GameObject object. There is also ''GetComponents()'' that retrieves a list. The GameObject must be active. * ''GetComponentInChildren()'', retrieves from children object. * ''Destroy(gameObject, time)'', will destroy an instatiated prefab on 20secs. * ''Destroy(gameObject)'', destroys the object now. * ''SendMessage'', calls a method on each script which have it inside the GameObject. // Calls the function ApplyDamage with a value of 5 gameObject.SendMessage ("ApplyDamage", 5.0); ... // Every script attached to the game object // that has an ApplyDamage function will be called. function ApplyDamage (damage : float) {... * Propiedades: * ''gameObject.active'', to activate or deactivate the gameObject. === Input === * ''OnMouseDown()'' function is called when there is a mouse click on a collider. * ''Input.GetButtonDown(str)'', where the string is... * Fire1, control key. * Fire2, left mouse button. === Animations === * ''Animation.SetFloat(float)'' sets the velocity of the animation. === Maths === * ''Mathf.Lerp'' * ''Mathf.Clamp'' === Time === * ''Time.fixedDeltaTime()'' * ''Time.deltaTime()'' * ''Time.time'' === Interact with the scene === * ''Application.LoadLevel(number)'', where the number is the scene identifier given on build preferences. :!: * ''Application.levelLoaded'', tells the current level. === Persistence === * ''Application.persistentDataPath'', returns a path where it's possible to save data. * ''PlayersPrefs.SetXXX(strIdentifier, value)'', where XXX is Int, String, Float... It saves user preferences in a plain text file. ''PlayersPrefs.GetXXX(strIdentifier)'' obtains the saved value. === Debug functions === * ''Debug.Log()'', shows a message in console. * ''Debug.Break()'', stops the game. === Camera === The static object ''Camera.main'' contains the main camera for the scene. * ''ViewportToWorldPoint'' and ''WorldToViewportPoint'' to transform coordinates. === Useful functions === * ''Application.OpenURL(url)'' ==== How to do... ==== === Move elements === :!: // Directly transform.position = new Vector3 (x, y, 0); // Using transformations transform.Translate (...) // By physics if(h * rigidbody2D.velocity.x < maxSpeed) rigidbody2D.AddForce(Vector2.right * h * moveForce); === Know which direction keys are we facing === float h = Input.GetAxis("Horizontal"); if(h > 0 && !facingRight) ... === Flip a character === Vector3 theScale = transform.localScale; theScale.x *= -1; transform.localScale = theScale; === Follow with effect === public float xMargin = 1f; // Distance in the x axis the player can move before the camera follows. public float yMargin = 1f; // Distance in the y axis the player can move before the camera follows. public float xSmooth = 8f; // How smoothly the camera catches up with it's target movement in the x axis. public float ySmooth = 8f; // How smoothly the camera catches up with it's target movement in the y axis. public Vector2 maxXAndY; // The maximum x and y coordinates the camera can have. public Vector2 minXAndY; // The minimum x and y coordinates the camera can have. // ----- float targetX = transform.position.x; float targetY = transform.position.y; // If the player has moved beyond the x margin... if(CheckXMargin()) // ... the target x coordinate should be a Lerp between the camera's current x position and the player's current x position. targetX = Mathf.Lerp(transform.position.x, player.position.x, xSmooth * Time.deltaTime); // If the player has moved beyond the y margin... if(CheckYMargin()) // ... the target y coordinate should be a Lerp between the camera's current y position and the player's current y position. targetY = Mathf.Lerp(transform.position.y, player.position.y, ySmooth * Time.deltaTime); // The target x and y coordinates should not be larger than the maximum or smaller than the minimum. targetX = Mathf.Clamp(targetX, minXAndY.x, maxXAndY.x); targetY = Mathf.Clamp(targetY, minXAndY.y, maxXAndY.y); // Set the camera's position to the target position with the same z component. transform.position = new Vector3(targetX, targetY, transform.position.z); === Scale interactively === healthBar.transform.localScale = new Vector3(healthScale.x * health * 0.01f, 1, 1); === Change an sprite color === healthBar.material.color = Color.Lerp(Color.green, Color.red, 1 - health * 0.01f); === Change an element to a foreground layer === go.sortingLayerName = "UI"; === Disable an script === ... Called PlayerControl.cs. GetComponent.enabled = false; === Wait two secs and reload the level === StartCorroutine ("ReloadLevel"); //--- IEnumerator ReloadLevel () { yield return new WaitForSeconds (2); Application.LoadLevel(Application.levelLoaded); } === Detect all enemies in a range === Collider2D[] enemies = Physics2D.OverlapCircleAll(transform.position, bombRadius, 1 << LayerMask.NameToLayer("Enemies")); foreach(Collider2D en in enemies) { Rigidbody2D rb = en.rigidbody2D; if(rb != null && rb.tag == "Enemy") { rb.gameObject.GetComponent().HP = 0; === Make a gameObject invisible === Disabling its MeshRenderer component... GetComponent(MeshRenderer).enabled = false; === Make blink a gameObject === For a finite amount of time... StartCoroutine(Blink(2.0)); function Blink(waitTime : float) { var endTime=Time.time + waitTime; while(Time.time To make it blink always, immiately, and repeat every 0.4 seconds... InvokeRepeating("Blink", 0, 0.4); function Blink() { renderer.enabled = false; yield WaitForSeconds(0.2); renderer.enabled = true; } ==== Notes ==== === Constants === #if UNITY_IOS && !UNITY_EDITOR banner = new ADBannerView(ADBannerView.Type.Banner, ADBannerView.Layout.Top); #endif * [[https://docs.unity3d.com/Documentation/Manual/PlatformDependentCompilation.html|List of constants]] ===== Physics ===== * ''RigidBody2D'' component enables properties useful for game physics. * ''Is kinematic'' makes the object not physically modifiable. * ''Fixed Angle'' disables rotation transformations. * ''Gravity Scale'', if it's 0 the object won't move. * ''Linear Drag'' is the air resistence. * ''Angular Drag'' affects to the rotation velocity. * To change physics properties (like gravity direction, default material...), go to Edit menu, Project Settings, Physics 2d. ==== Scripting physics ==== * ''rigidbody2D.velocity'' returns the velocity vector from one rigidbody2D attached to a GameObject. ==== Physics functions ==== * ''OnCollisionEnter2D(CollisionInfo2D info)'' when another collider is touching this object collider. * ''OnCollisionExit2D(CollisionInfo2D info)'' when another collider is not touching this object collider anymore. * ''OnTriggerEnter2D(Collider2D otherCollider)'' when another collider marked as a "Trigger" is touching this object collider. * ''OnTriggerExit2D(Collider2D otherCollider)'' when another collider marked as a "Trigger" is not touching this object collider anymore. ==== Colliders ==== * When a collider is market as ''Is Trigger'' won't cause physical collisions, however it will call ''OnTriggerEnter2D()'' function. ==== Materials ==== You can create a material to give a collider bouncingness or friction in Assets menu, Create and Physics 2D Material. It will have to be assigned to a collider. ==== How to... ==== === ... Detect a sprite collision by code === * We will create a GameObject and add to it a Sprite. Add a Rigidbody 2D. * We'll add a new empty GameObject to the previous GameObject and name it ''groundCheck'' (To view it you can give it an icon on the editor). * We will add a layer named Ground to the scene and add to it some sprites. We will add Collider to those sprites. // Awake function groundCheck = transform.Find("groundCheck"); // FixedUpdate grounded = Physics2D.Linecast(transform.position, groundCheck.position, 1 << LayerMask.NameToLayer("Ground")); === Detect it collides with === void OnCollisionEnter2D (Collision2D col) { // If the colliding gameobject is an Enemy... if(col.gameObject.tag == "Enemy") === Apply force === Vector3 hurtVector = transform.position - enemy.position + Vector3.up * 5f; rigidbody2D.AddForce(hurtVector * hurtForce); === Disable colliders === Collider2D[] colliders = GetComponents(); foreach (var c in colliders) c.isTrigger = true; === Move an element === float inputX = Input.GetAxis("Horizontal"); float inputY = Input.GetAxis("Vertical"); movement = new Vector2(speed.x * inputX, speed.y * inputY); ===== Other stuff... ===== ==== Working with mobile phones ==== There's an app to test mobile input named Unity Remote. * ''Input.touches'' is an array of Touch objects. * When something happens on input (''OnGUI()'' function) we can iterate over ''touches''. * ''Input.touchCount'' tells the number of touches. * ''Input.GetTouch(0)'' obtains the first touch which was done. * Sometimes you'll need to refresh the editor to see the changes, you can do it with ''CTRL+R''. * To focus a gameobject you'll do in the GameObject menu, option Align View to Selected. ==== GUI elements ==== GUI.Label(new Rect(), message); if (GUI.Button()) { To make a property which won't be shown in the editor: [HideInInspector] public float mAngle = 0f; To create a option menu you will add a class of the next style: using UnityEngine; using UnityEditor; using System.Collections; public class FunWindow : EditorWindow { [MenuItem("Tools/Fun Window")] public static void ShowWindow() { EditorWindow.GetWindow("Fun Window"); } void OnGUI() { if(GUILayout.Button("Clear PlayerPrefs")) { PreferencesManager.DeleteAll(); } if(GUILayout.Button("Clear Store")) { Unibiller.clearTransactions(); } } } ==== Coroutines ==== Wait for seconds requires a couple things in order to work properly and chances are if it's not working you're probably just missing on of the requirements. Here's an example: IEnumerator MyMethod() { Debug.Log("Before Waiting 2 seconds"); yield return new WaitForSeconds(2); Debug.Log("After Waiting 2 Seconds"); } Simple right? The only trick here is to make sure the return type of the method using the `WaitForSeconds` call is `IEnumerator`. Okay, so now we're half done but the next thing is to call this `MyMethod` and that looks like: StartCoroutine(MyMethod()); And there's the 2nd trick. You need to call the method as a coroutine otherwise you're not going to have it work. Now that you get how it works, jump back to the yield statement. Anything you want to happen after the wait goes after the yield statement and everything you want to happen before, goes before the yield statement. Hope this helps! ==== Social API ==== * [[http://docs.unity3d.com/Documentation/Components/net-SocialAPI.html]]