Saturday, January 16, 2016

Unity 2D Platformer Tutorial - Part 5a - Combat Player Health

See the previous parts here:
Check out the code below the videos




In part 5a of this Unity3D tutorial we add Player Damage and Death. The player will take damage from touching enemies but become invincible for a short time afterwards. If the player takes 3 hits, then the player dies and the level restarts.
Google+ Community: https://plus.google.com/communities/108584850180626452949
Twitter: https://twitter.com/Devination3D
Facebook: https://www.facebook.com/unity3Dtutorialsbydevin

Time Breakdown:
0:55 - Fixing a couple of issues with the enemy
3:00 - Setting up the damage animation for our player
4:56 - Setting up the script for player damage
9:16 - Adding our level to the build settings so we can restart the game on death
10:12 - Playing the hurt animation when we take damage
16:12 - Making the player ignore collision with the enemy after getting hurt
19:50 - Demonstration of player damage working as intended



Support Further Tutorial Development
Comments?
Check out the videos above to hear the explanation and see the code in action
/*/
* Script by Devin Curry
* www.Devination.com
* www.youtube.com/user/curryboy001
* Please like and subscribe if you found my tutorials helpful :D
* Google+ Community: https://plus.google.com/communities/108584850180626452949
* Twitter: https://twitter.com/Devination3D
* Facebook Page: https://www.facebook.com/unity3Dtutorialsbydevin
/*/
using UnityEngine;
using System.Collections;

public class PlayerController : MonoBehaviour
{
	public static PlayerController instance;

	//Movement
	public float speed = 10, jumpVelocity = 10;
	public LayerMask playerMask;
	public bool canMoveInAir = true;

	//Combat
	public int health = 3;
	public float invincibleTimeAfterHurt = 2;

	[HideInInspector]
	public Collider2D[] myColls;

	Transform myTrans, tagGround;
	Rigidbody2D myBody;
	bool isGrounded = false;
	float hInput;
	AnimatorController myAnim;

	void Start ()
	{
		instance = this;
		myColls = this.GetComponents<Collider2D>();
		myBody = this.GetComponent<Rigidbody2D>();
		myTrans = this.transform;
		tagGround = GameObject.Find (this.name + "/tag_ground").transform;
		myAnim = AnimatorController.instance;
	}
	void FixedUpdate ()
	{
		isGrounded = Physics2D.Linecast (myTrans.position, tagGround.position, playerMask);
		myAnim.UpdateIsGrounded (isGrounded);
		#if !UNITY_ANDROID && !UNITY_IPHONE && !UNITY_BLACKBERRY && !UNITY_WINRT || UNITY_EDITOR
		hInput = Input.GetAxisRaw("Horizontal");
		myAnim.UpdateSpeed(hInput);
		if(Input.GetButtonDown("Jump"))
			Jump();
		#endif
		
		Move(hInput);
	}
	void Move(float horizonalInput)
	{
		if(!canMoveInAir && !isGrounded)
			return;
		Vector2 moveVel = myBody.velocity;
		moveVel.x = horizonalInput * speed;
		myBody.velocity = moveVel;
	}
	public void Jump()
	{
		if(isGrounded)
			myBody.velocity += jumpVelocity * Vector2.up;
	}
	public void StartMoving(float horizonalInput)
	{
		hInput = horizonalInput;
		myAnim.UpdateSpeed(horizonalInput);
	}

	void Hurt()
	{
		health--;
		if (health <= 0)
			Application.LoadLevel(Application.loadedLevel);
		else
			myAnim.TriggerHurt(invincibleTimeAfterHurt);
	}
	void OnCollisionEnter2D(Collision2D collision)
	{
		Enemy enemy = collision.collider.GetComponent<Enemy>();
		if(enemy != null)
		{
			foreach(ContactPoint2D point in collision.contacts)
			{
				Debug.Log(point.normal);
				Debug.DrawLine(point.point, point.point + point.normal, Color.red, 10);
				if( point.normal.y >= 0.9f )
				{
					Vector2 velocity = myBody.velocity;
					velocity.y = jumpVelocity;
					myBody.velocity = velocity;
                    enemy.Hurt();
				}
				else
				{
					Hurt();
				}
			}
		}
	}
}

Sunday, September 6, 2015

Unity Touch Joysticks Tutorial - Touch Input 2D Spaceship Controller

In this Unity C# Touch Tutorial we create a touch joystick and button in Unity 5 and use it to control a floaty spaceship.

Download the project below the video

Time Breakdown:
1:07 - Importing CrossPlatformInput from the Standard Assets
2:23 - Adding the joystick to our scene and setting up all the other requirements
3:20 - Fixing the Joystick start position so it doesn't snap to the bottom corner of the screen
4:13 - Clamping our joystick movement to a circle rather than a square
6:45 - Setting up the player spaceship in Unity
8:25 - Starting the spaceship player controller script
9:53 - How to read the joystick data from the CrossPlatformInputManager
13:10 - Using a conditional operator to apply boost speed
14:45 - Adding linear drag to slow down like Asteroids
15:45 - Adding Canvas Scalar component so the GUI stays on screen
16:20 - Build and demonstration on Android



Support Further Tutorial Development
Comments?
Check out the video above to hear the explanation and see the code in action
You can download a package for this project from Google Drive: https://drive.google.com/file/d/0Bwiz0Tss2NSqaGxrRXd0RFY2QUE/view?pli=1

Sunday, July 12, 2015

Unity 2D Platformer Tutorial - Part 4 - Enemy Movment

See the previous parts here:
Check out the code below the videos




In part 4 of this Unity3D tutorial we add Enemy AI. The enemy will walk from edge to edge of a platform as long as it's alive. This sort of enemy movement can be seen in many 2D Platformer games like Mario.

Google+ Community: https://plus.google.com/communities/108584850180626452949
Twitter: https://twitter.com/Devination3D
Facebook: https://www.facebook.com/unity3Dtutorialsbydevin

Time Breakdown:
0:30 - Updating API from Unity 4.6 to Unity 5
1:45 - Setting up the enemy sprites
2:38 - Locking Layers to avoid accidentally selecting the Canvas
3:40 - Setting up the Enemy walk anim
4:38 - Begin Enemy script
6:56 - Explanation of why we need myWidth for Linecast
9:10 - Setting up isGrounded Linecast check
12:35 - Use isGrounded check to flip the enemy if he gets to an edge
15:52 - Changing move direction to be in local space to the enemy
16:45 - Adding an isBlocked check for hitting walls
17:21 - Using ExtensionMethod .toVector2() to add a Vector2 and a Vector3: https://www.youtube.com/watch?v=D3_r7088dJ4
20:20 - Using myHeight to Linecast from middle left of enemy instead of bottom left corner
22:24 - Demonstration of enemy movement fully working



Support Further Tutorial Development
Comments?
Check out the videos above to hear the explanation and see the code in action
/*/
* Script by Devin Curry
* www.Devination.com
* www.youtube.com/user/curryboy001
* Please like and subscribe if you found my tutorials helpful :D
* Google+ Community: https://plus.google.com/communities/108584850180626452949
* Twitter: https://twitter.com/Devination3D
* Facebook Page: https://www.facebook.com/unity3Dtutorialsbydevin
/*/
using UnityEngine;
using System.Collections;

public class Enemy : MonoBehaviour
{
 public LayerMask enemyMask;
 public float speed = 1;
 Rigidbody2D myBody;
 Transform myTrans;
 float myWidth, myHeight;

 void Start ()
 {
  myTrans = this.transform;
  myBody = this.GetComponent<Rigidbody2D>();
  SpriteRenderer mySprite = this.GetComponent<SpriteRenderer>();
  myWidth = mySprite.bounds.extents.x;
  myHeight = mySprite.bounds.extents.y;
 }
 
 void FixedUpdate ()
 {
  //NOTE: This script makes use of the .toVector2() extension method.
  //Be sure you have the following script in your project to avoid errors
  //http://www.devination.com/2015/07/unity-extension-method-tutorial.html

  //Use this position to cast the isGrounded/isBlocked lines from
  Vector2 lineCastPos = myTrans.position.toVector2() - myTrans.right.toVector2() * myWidth + Vector2.up * myHeight;
  //Check to see if there's ground in front of us before moving forward
  //NOTE: Unity 4.6 and below use "- Vector2.up" instead of "+ Vector2.down"
  Debug.DrawLine(lineCastPos, lineCastPos + Vector2.down);
  bool isGrounded = Physics2D.Linecast(lineCastPos, lineCastPos + Vector2.down, enemyMask);
  //Check to see if there's a wall in front of us before moving forward
  Debug.DrawLine(lineCastPos, lineCastPos - myTrans.right.toVector2() * .05f);
  bool isBlocked = Physics2D.Linecast(lineCastPos, lineCastPos - myTrans.right.toVector2() * .05f, enemyMask);

  //If theres no ground, turn around. Or if I hit a wall, turn around
  if(!isGrounded || isBlocked)
  {
   Vector3 currRot = myTrans.eulerAngles;
   currRot.y += 180;
   myTrans.eulerAngles = currRot;
  }

  //Always move forward
  Vector2 myVel = myBody.velocity;
  myVel.x = -myTrans.right.x * speed;
  myBody.velocity = myVel;
 }
}