Friday, 25 April 2014

Summary

7. Summary and final touches.

To make the game more realistic, player and enemies objects has an attached sound effects triggered in different cases. Player object has attached sounds like: "PistolFire", "ShotgunFire" in case we shoot, "DryClick" in case we want to shoot but we don't have ammunition and "PlayerHit" in case we received damage. On the enemies side we have: "EnemyHit" in case enemy received damage and "EnemyDie" played when enemy dies. Prefabs for ammunition has also attached sounds e.g. "PistolReload" in case when we collect ammunition.

In this blog I tried to describe main functionalities of this project supported with examples. It was really big fun to create something unique, something what actually can give you a lot of satisfaction.

Building my project from scratch helped me to understand how Unity2D works, fundamental Unity interface functions, scripts structure and fundamental C# syntax, relations between game objects and scripts. On graphics side I learned a loot about "Tiled" and "Photoshop".  

In the future, I would like to implement few more functions like: story line, machine gun weapon, health packs, more new enemies with different features and abilities, bosses and more levels.

Complete project available at:
https://github.com/Adammdit/Unity

Screenshot of the game:

  

Thursday, 17 April 2014

User interface, memory leaks

6. User interface objects and memory leaks.

User interface consist of:

- player icon
- health bar
- two icons of weapon
- number of ammunition available
- score

All those elements are represented by objects GUI Texture and GUI Text. Each object has attached script to set optimal position on screen relying on current screen resolution e.g. transform.position = new Vector3(posX, posY, 1); where posX = 0.4f, posY = 0.03f.

Main menu of the game can be recalled by pressing "Esc" key and consists of three options "Resume", "Restart" and "Quit". When "Esc" key is pressed game time is stopped and position of menu is changed to centre of the screen . Menu is drawn on GUI whole time but in different positions. When we want to access the game menu then it position is set to centre of the screen, when we want to close it, its sets it position outside of the screen. If we press "Resume" button, game time is set back to one: Time.timeScale = 1;. For "Restart" option, when the button is pressed, I load scene one and reset global game variables e.g. Application.LoadLevel(1);. For "Quit" option I'm using: Application.Quit(); which will close the game. Last element placed on GUI is screen frame which is a PNG file scaled and position exactly in the centre of screen.
As I progressed with my game I noticed that when the game is running it's constantly consuming computers memory (RAM) until it's full and computer crashed. To fix that I used: Resources.UnloadUnusedAssets(); and I placed it in Update() function.

Game menu:


Screen shoot of my user interface and frame:

Tuesday, 1 April 2014

Enemies

5. Enemies and ammunition as a prefabs.

Ideally in the game I'm going to use three different types of enemies and two different types of ammo as a different prefabs. Prefabs are game objects combining all functions and preferences of particular object e.g. ''Prefab_Enemy1" (prefab of first enemy in the game) prefab will consist of c# script, sounds, animations, translate, rigidbody 2D and all components we attached to particular object. All prefabs are connected to their original object - they are clones. In order to create a prefab simply drag a game object that you created in the scene and drop it in project view. The name of this object will turn blue to show that is a prefab. Now we can rename our prefabs and delete blue objects in hierarchy view (note that if you're going to make any further changes to animations you will have to reverse above order - drag prefab from project view and drop it in hierarchy view apply changes and make the prefab again).  
All enemies are using the same algorithm representing their artificial intelligence. Basically enemy ray-casting against player, if player is in the range then enemy starts walking towards player. Each collision between the player and enemies decreases player's life. To detect collisions between different enemies I used tags, so each enemy has unique name and can deal different damage.

Three types of enemies:

Tuesday, 18 March 2014

Shooting and few gadgets

4. Shooting bullets, Laser Scope and Aiming Icon

To shoot bullets I created bullet prefab which contains bullet script and bullet object. Bullet script encapsulates bullet speed. In function Update() single line of code represents movement transform.Translate"Vector2.up * bulletSpeed * Time.deltaTime" and after short amount of time bullet gets destroyed. I would like to add that it's not efficient to put any collision detection inside the bullet class (we might have hundreds of bullets and if each one will check for collisions it will consume lot of computer resources). In game object each bullet have Sprite Renderer and Bullet script attached. Each time when player shoots "Input.GetMouseButtonDown(0)" Player script will instantiate bullet prefab with player position and rotation creating clone of bullet "tempBullet = (Instantiate(bullet, transform.position, transform.rotation)) as GameObject".
To detect collision of bullet there are two ways. First which I used is suitable for fast moving objects (depends how fast do you want your bullets to move). For fast moving objects (speed > 50) function "OnCollisionEnter2D()" is unreliable so my enemies are using "RaycastHit2D". It is function to draw invisible line between two objects and return true if something is on its way, I also used layer mask so line will collide only with objects placed on that layer e.g. walls or other enemies. My collision detection is if mouse over object and left mouse button pressed and ammo greater than zero and no collisions on the way - enemy was hit (you can also add range condition).
Second way to detect collisions is to use "OnCollisionEnter2D()" function for slow moving objects. In that case our bullet object needs extra elements like Rigidbody 2D() and Circle Collider 2D so we can add some physics to our object. This function also returns many useful information about collision like object tag we collide with or position of collision. I'm going to use it for ammo or if enemy will touch you.
In my game player have useful gadget Laser Scope attached to his guns. To do that I used Line Renderer. Line Renderer has many options like color, number of points line consist of, and shader. Starting point is player rotation and position transformed by some offset (so laser coming out of gun instead of center of player). End point is a returned vector of Raycasting against layer mask. Layer mask consists of three layers (walls, furniture and enemies) or together in binary values and convert to decimal e.g. layers 12, 13 and 14 or together as binary numbers will give us decimal 14336. To get nice laser effect I used material "Default-Particle" for both points. To set end point I used "lineRenderer.SetPosition(1, endPoint)" syntax where 1 is second point (0 is start point) and endPoint is returned vector of Raycasting collision.    
To replace standard mouse cursor first I disabled it with "Screen.showCursor = false" and in FixedUpdate() function I transformed it position to mouse position with "Camera.main.ScreenToWorldPoint(Input.mousePosition)". In Unity we need new cursor object with desired sprite and cursor script attached.

Laser and cursor:
  

Monday, 3 March 2014

Animations and first coding

3. Player animations and movement

To apply simple animations e.g. for character in move I used tile sheets which contain player sprites captured frame by frame. At this stage I used three types of animations: Idle, Walk and Shoot but I'm going to include one more for Player hit. Each animation needs a condition which will trigger it. In Unity each PNG file containing tile sheet for animation needs to be prepared. I set: Sprite Mode - Multiple, Pixels To Units - 32 then in Sprite Editor I used grid to divide picture into frames, each frame needs to have the same size in pixels. Next I created new object for player called Animator, each animator needs Controller. In Animation Window for player I added: Idle with Sample Rate - 3, Walk with Sample Rate - 12 and Shoot with Sample Rate - 20. Sample Rates are set how fast animation will be displayed. In Animator Window I set transition between animations and conditions as follow: if speed of player is greater than 0.01 switch to Walk animation, if speed of player is less than 0.01 go back to default Idle animation. Reason why I used values 0.01 is if we use e.g. 1 switching animations will be delayed as player has to reach speed of 1 first. For shooting I created new variable called 'Trigger' and I set it to true in Update function in PlayerControl scrip using Input.GetMouseButtonDown(0). Animation will end after 1 second - Exit Time variable.
For movement I created new C# script called PlayerControl. I included two variables: maxSpeed for player speed set it to 3.0f and Animator type variable called anim to be able to access animations. In update function I included another variables for speedX and speedY assigning them values: "Input.GetAxis("Horizontal")" and "Input.GetAxis("Vertical")". I also created new object called rigidbody2D for my player as i I will need it to change velocity of it "Vector2(moveX * maxSpeed, moveY * maxSpeed)", detect any collisions or to apply any physics.

Example of "Animator" tab for my player:


Picture above clearly represents bunch of different animations. We have two different sets of animations, animations for player holding pistol and for player holding shoot gun.

Wednesday, 26 February 2014

Tiles, tiles, tiles

2. Graphics processing and collisions

Game graphic is mostly based on 32x32 pixels tiles. By default size of first two levels are 32x24 blocks (1024x768) with Pixels to Units set to 32. The last two levels are 64x48 blocks (2048x1536). To make the game "lighter" all huge static surfaces like walls and floors was exported by Tiled Map Editor to PNG files. Tiled Map Editor is a very useful free software to build whole levels out of tiles. Program has few really useful options like layers and export to PNG which I needed the most. Created PNG file are used in 2D Unity Project as sprites, instead of surfaces build out of hundreds of small objects. Each object is traced by our CPU and if game will get bigger we can easily overload processor. To prepare the tiles I mostly used Photoshop and another really good free feature called Sprite Splitter but Paint.NET or Gimp are sufficient enough.
For collisions I used Box Colliders 2D drawing them around walls and other objects that I want to collide with.
Really important is to center camera and all sprites, put them on numbered layers and set values to them in order from bottom up. That allowed me to manipulate what will be drawn on top of what in easy way.
I strongly recommend using tools like Tiled Map Editor. I saved a lot of time producing whole levels graphics using this small program.

Example of PNG graphic representing walls of of my ground level building; assembled out of 32x32 small blocks using "Tiled" program:

Another PNG graphic for floors:

When you join then together:

The only thing you have to keep in mind is layers (what is displayed on top of what) and to add "Polygon collider 2D" for walls.

Sunday, 16 February 2014

Basic ideas

1. Ideas and some technical details

For my assignment I would like to do 2D shooting game using Unity. I believe that most challenging part are the good sprites, so it is worth to spend some time and prepare really good graphics. Unity it self is a very powerful tool combining elements of Photoshop and Visual Studio. Currently I am going over number of Unity tutorials and preparing my player sprites which are going to be animated.

Game functionality:
- 2D game
- controls: keyboard + mouse (recommended)
- single player
- two types of weapons (pistol and shotgun) - can be extended
- laser scope attached to guns
- three different types of enemies (can be extended) - randomly spawned
- four levels (ascending difficulty) - can be extended
- ammo
- player interface (image of player, health, ammo for pistol, ammo for shotgun, score)
- lift (move from ground to basement level)