Customizable Navigation Bar

Monday, March 28, 2011

The Factory Design Pattern

Hey guys, to hold you off I am going to do a small article on the factory design pattern. It makes instantiating multiple objects very easy and painless so it is definitely something that you want to keep in mind while you are coding away.

The easiest way for you to see what the factory does is for me to just show it to you. I am going to mostly code in C#, but as long as you can grasp the concept, it shouldn't matter what language this is in.

What we need to do is create a base class that all of the "manufactured" classes will extend from. In most cases this is already done for you:
        In flash this could be your Sprite class
        In C# or UnrealScript this could be your object class
        Unity has the GameObject class

Saturday, March 19, 2011

Delayed Post (Again!)

GAAAH! Alright, so I am sorry guys. I am moving this weekend so I have to pack like crazy, and I don't think that I will be able to get those videos and posts done, which sucks. So what I plan on doing, instead of doing a triple post next week, is to write up a quick article on some sort of design pattern or an approach to programming this week and next week I will do the double post that was planned for this weekend. This problem with doing these videos is the fact that it takes so long to cut and compress them, then upload to YouTube, I quite literally have to dedicate a day to a tutorial, which is why I can't just throw a whole whack of them together really quickly.

So, like I said, I will write an article, most likely on the factory design pattern, since it is pretty useful, and I will definitely try and get the rest of these top down shooter tutorials finished.

Also, by the looks of it, the RTS won the poll, so tutorials based on RTS mechanics will be coming soon. In between the top down shooter and RTS tutorials, there will be multiple posts based on making your code more efficient, and I will give you guys a heads up on my latests projects. Maybe fill in my two pages for the top down shooter I was working on and the Fly Game, since they are more or less empty right at this moment.

Sorry guys, but I will have more free time to make these posts in the short future, so these delays should happen very often

Tuesday, March 15, 2011

Next Game To Make

So guys, I see by the poll so far, you guys want me to either make a puzzle platformer or an RTS. We still have a week and a half left to vote, but so far these two sound like fun. RTS mechanics would be a fun tutorial to make, as there are really no tutorials out there that I have seen myself, and a puzzle platformer is always fun to make.

Ideas are already starting to pour into this skull of mine, but I shouldn't get carried away. A week and a half of voting can change things around quite a bit.

Saturday, March 12, 2011

Building A Game In Unity Part 4: Projectiles and The Particle Editor

This week's tutorial covers how to create a few projectiles for your player to shoot. There will also be a few empty classes that we create for the next tutorial on enemies and the animation editor. The particle effects tutorial is located in the videos posted, only because it is much easier not only for me to explain, but for you to understand if I just show your how to use it visually.

Also, follow me on twitter at http://twitter.com/#!/purdyjo!

If you just want to skip to the in depth look at the Particle Editor, skip to the last half of the video.





So before we begin  with the real coding, we need to create two empty classes that extend BaseEntity called Player and Enemy. These are empty because we aren't adding any functionality this week, that is next week's lesson, but we need them for our TrackingRocket script to compile properly.

So just to get them ready create two C# scripts and add the following code to the on you name Enemy:

using UnityEngine;
using System.Collections;

public class Enemy : BaseEntity
{
}

Then add the following code to the one you name Player:


using UnityEngine;
using System.Collections;

public class Player : BaseEntity
{
}


That's all we need for now. Just the empty classes.

OK, so now that we have those two classes out of the way, open up your Projectile class from the last tutorial. There's a quick change that we need to make to the Start() function and the Update() function.

This is what you should have at the declaration of each function:

 void Start () 
 void Update () 
Now what we are going to change this to is:
protected virtual void Start () 
protected virtual void Update () 
Now what this does is make it so that in any class that we extend from Projectile can gain the functionality of the Start and Update functions, while adding their own, with very little extra typing.


Now that we have that out of the way, let's get to filling in two new classes, Rocket and TrackingRocket.
The Rocket class is fairly basic, it just adds a few new properties to the Projectile class.

using UnityEngine;
using System.Collections;

public class Rocket : Projectile
{

        /*Here we declare a public game object. It is what will be instantiated when the rocket collides with something*/

         public GameObject rocketExplosion;

 
        /*We need to override Start() so that we can gain the functionality from Projectile, but at the same time add our own*/

         override protected void Start ()
         {
                 mDamage *= 2;
                 if(rocketExplosion == null)
                 {
                         Debug.LogError("Hey there is no rocket explosion attached to Rocket");
                 }
        /*In order to add the functionality from Projectile we need to call base.Start()*/

                  base.Start();
         }
        /*We need do rewrite the OnTriggerEnter function from Projectile to spawn the rocketExplosion when it hits something*/

         protected virtual void OnTriggerEnter(Collider other)
         {
                  BaseEntity otherObject = other.gameObject.GetComponent<BaseEntity>();
                  if(otherObject != null)
                  {
                          if(otherObject.GetType() != mInstigatorType)
                          {
                                  otherObject.takeDamage(mDamage);

                                /*There it is*/
                                  Instantiate(rocketExplosion, transform.position, Quaternion.identity);
                                  Destroy(gameObject);
                         }
                  }
         }
}

That's literally it for the Rocket class. 

The TrackingRocket class is similar. Basically all we have to do is make the rocket rotate towards it's target.

using UnityEngine;
using System.Collections;

public class TrackingRocket : Rocket
{

        /*So here we create a private transform to hold our target in*/

         private Transform target;
        /*We then override the Start function once more to add a little bit more functionality to the class*/

         override protected void Start()
         {

        /*We set a shorter lifespan because Vector3.Normalize is somewhat expensive, and having dozens of these on the screen at once is just asking from trouble*/

                 mLifeSpan = 4.0f;
                /*We then start two new coroutines that will check for the target's destruction and rotate the projectile towards the target if it exists*/

                 StartCoroutine(checkIfTargetDestroyed());
                 StartCoroutine(rotateTowardsEnemy());
                  base.Start();
         }
        /*Our checkIfTargetIsDestroyed function just checks to see if target is set to null. If it doesn't exist, we call a function called findTarget*/

         private IEnumerator checkIfTargetDestroyed()
         {
                  yield return new WaitForSeconds(0.5f);
                  while (true)
                 {
                          if(target == null)
                         {
                                  findTarget();
                          }
                          yield return new WaitForSeconds(1.0f);
                 }
         }

        /*Our findTarget function is conditional depending on what the instigator of this projectile is*/

         void findTarget()
         {
                  BaseEntity newTarget;
                /*If the instigator is the player, we find all enemies that are alive, and then target a random one*/

                 if(mInstigatorType == typeof(Player))
                  {
                          object[] enemyList = GameObject.FindObjectsOfType(typeof(Enemy));
                         newTarget = enemyList[Random.Range(0, enemyList.Length)] as Enemy;
                  }

                /*If the instigator is an enemy, we find the player and target it*/
                 else
                  {
                          newTarget = GameObject.FindObjectOfType(typeof(Player)) as Player;
                 }
                /*If a target was found we stop the checkIfTargetIsDestroyedCoroutine and set our target*/

                 if(newTarget != null)
                  {
                         target = newTarget.transform;
                         StopCoroutine("checkIfTargetIsDestroyed");
                  }
         }
        /*rotateTowardsEnemy could technically be done in the Update function but square roots are an expensive operation, and we should use them sparingly*/

         private IEnumerator rotateTowardsEnemy()
         {
                 while(true)
                 {
                          yield return new WaitForSeconds(0.2f);
                        /*So if the target exists we rotate towards it, if not we check to see if it is null and find another target*/
                          if(target != null)
                          {
                                  mMovementDirection = Vector3.Normalize(target.position - transform.position);
                          }
                          else
                          {
                                  StartCoroutine(checkIfTargetDestroyed());
                         }
                  }
         }
}

Note that in the video, we did not test the TrackingRocket. I forgot to say something about it but it was because the Player and Enemy classes have not been filled in, and it would have been more trouble than what it's worth to try and get it working. So next week we will see the rockets in actions.

That's it projectile wise. If you were coming here to check out the particle effect walkthrough, check out the last two videos in this post. Next week we are adding the functionality to the Player and Enemy classes, while also looking at the Animation editor. Keep coding!




Saturday, March 5, 2011

Building A Game In Unity Part 3: Weapons and Gizmos in Unity

This week's tutorial covers how to create a weapon and using something called gizmos in Unity. We also set up some base scripts for later tutorials. There is a video that goes along with this tutorial posted here:

Also, follow me on twitter at http://twitter.com/#!/purdyjo!



The first script that we are going to make is called BaseEntity. This script will be the building blocks for our enemies, the main character and any other characters that you wish to add. It contains the properties that all of the objects will share.


using UnityEngine;
using System.Collections;

public class BaseEntity : MonoBehaviour
{

/*Here we make protected variables for health and make them read only, so that this is the only class that can change their values. This just keeps us from accidentally making a change somewhere and killing the player with an unrelated script.*/

        protected float mHealth = 100.0f;
        public float currentHealth{get{return mHealth;}}

        protected float mMaxHealth = 100.0f;
        public float maxHealth{get{return mMaxHealth;}}

/*Make a generic take damage function for when this object gets attacked etc*/

        public virtual void takeDamage(float amount)
        {
                mHealth -= amount;

                if(mHealth <= 0)
                {
                        die();
                }
        }

/*We should also make a healing function for potions or powerups etc*/

        public virtual void healDamage(float amount)
        {
                mHealth = Mathf.Min(mHealth + amount, mMaxHealth);
        }

/*We also need some sort of die function, so that we can have this object do something before it is destroyed*/

        protected virtual void die()
        {
                Destroy(gameObject);
        }
}


Our next script is a base class for all projectiles, because we need something for the weapon to shoot. This class also checks to see if what it collides with is friendly or not.


using UnityEngine;
using System.Collections;

/*We are also going to include System since we need to use Types for this class*/

using System;


/*This also requires a sphere collider to work, so we force unity to add one when this script is attached*/

[RequireComponent(typeof(SphereCollider))]
public class Projectile : MonoBehaviour
 {

/*Our generic variables that all projectiles will be using*/

        protected float mSpeed = 20.0f;
        public float speed{get{return mSpeed;}}
        protected float mMaxSpeed = 25.0f;
        public float maxSpeed{get{return mMaxSpeed;}}
        protected Vector3 mMovementDirection;
        public Vector3 movementDirection{get{return mMovementDirection;}}
        protected float mAcceleration = 1.0f;
        public float acceleration{get{return mAcceleration;}}
        protected float mDamage = 10.0f;
        public float damage{get{return mDamage;}}
        protected float mLifeSpan = 10.0f;
        public float lifeSpan{get{return mLifeSpan;}}
/*The instigator type is the type of the object that fired this projectile. Useful for checking if the player shot an enemy or not*/

        protected Type mInstigatorType;
        public Type instigatorType{get{return mInstigatorType;}}
        void Start () 
        {
                mMovementDirection = transform.forward;
                gameObject.GetComponent<SphereCollider>().isTrigger = true;
                StartCoroutine(kill());
        }
        void Update () 
        {

/*In the update function we just want our projectiles to move forward. Nothing fancy here*/

                transform.position += (mMovementDirection * mSpeed * Time.deltaTime);
                if(mSpeed < mMaxSpeed)
                {
                        mSpeed += mAcceleration * Time.deltaTime;
                }
/*We should also check to see if the object is on the screen or not. There is no reason to have this object still active if it's not on the screen*/

                if(!renderer.isVisible)
                {
                        Destroy(gameObject);
                }
        }
/*We should also kill the projectile after the lifespan, so that it isn't constantly taking up memory*/

        protected IEnumerator kill()
        {
                yield return new WaitForSeconds(mLifeSpan);
                Destroy(gameObject);
        }
/*This is to set the instigator of this projectile. The weapon firing this calls this function*/

        public void setInstigator(BaseEntity instigator)
        {
                mInstigatorType = instigator.GetType();
        }
/*Here we check to see if a base entity was hit, and if it was we check the type against the instigator type and do damage if applicable*/

        void OnTriggerEnter(Collider other)
        {
                BaseEntity otherObject = other.gameObject.GetComponent<BaseEntity>();
                if(otherObject != null)
                {
                        if(otherObject.GetType() != mInstigatorType)
                        {
                                otherObject.takeDamage(mDamage);
                                Destroy(gameObject);
                        }
                }
        }
}


So the projectile class is fairly simple, and it gets the job done. Now that we have a base entity class and a projectile class, lets get to the weapon class. Keep in mind that a weapon is just a point in world space that projectiles spawn from


using UnityEngine;
using System.Collections;

public class Weapon : MonoBehaviour 
{

/*here we have a public Projectile so that we can choose the projectile type that will be fired in the editor*/

        public Projectile bulletType;
        public float fireRate = 1.0f;
       
/*here we have a bool to check if the weapon's rotation should remain constant. This is to keep the projectiles moving in the same direction no matter which way the enemy or player rotates during animations*/

        public bool lockRotation;
        private Quaternion mStartingRotation;

/*then we create a variable to hold the owner of the weapon*/

        private BaseEntity mOwner;
/*Now since the weapon is an empty object, we need some easy way to see the weapon in the editor. Gizmos solve this problem. In the OnDrawGizmos function we can tell unity to draw spheres, lines, icons etc that will only appear in the editor.*/

        void OnDrawGizmos()
        {

/*Do show where the weapon is we draw a sphere at it's position and a line showing you what direction it is facing*/

                Gizmos.DrawSphere(transform.position, 0.1f);
                Gizmos.DrawLine(transform.position, transform.position + transform.forward * 0.5f);
        }
        void Start () 
        {

/*In start we more or less just check if bulletType has been set to something. If not we throw an error and break*/

                if(bulletType == null)
                {
                        Debug.LogError("bulletType is set to null");
                        Debug.Break();
                }
                mStartingRotation = transform.rotation;
                enableWeapon();
        }
/*Our fire weapon function is a coroutine that gets called once every few seconds depending on the fire rate chosen*/

        IEnumerator fireWeapon()
        {
                mOwner = transform.parent.gameObject.GetComponent<BaseEntity>();

                while(true)
                {

/*We also only fire the weapon if the object is on the screen, theres no point on firing if the projectiles get destroyed off screen*/

                        if(mOwner.renderer.isVisible)
                        {
                                if(lockRotation)
                                {
                                        transform.rotation = mStartingRotation;
                                }
                                Projectile newBullet = (Projectile)GameObject.Instantiate(bulletType, transform.position, transform.rotation);
                                newBullet.setInstigator(mOwner);
                                yield return new WaitForSeconds(fireRate);
                        }
                        else
                        {

/*if the weapon is off screen we just wait until the end of the frame and check again*/

                                yield return new WaitForEndOfFrame();
                        }
                }
        }
/*Now that we've completed this much we can create public functions for enabling and disabling the weapon*/

        public void enableWeapon()
        {
                StartCoroutine(fireWeapon());
                this.enabled = true;
        }
        public void disableWeapon()
        {
                StopCoroutine("fireWeapon");
                this.enabled = false;
        }
}

Alright, so now we have a working weapon and some base scripts for the player, enemies and projectiles, and this tutorial is complete. The next part in this series will be covering the particle effect editor and we will be filling in more projectile classes. So have a good one guys and keep coding!