Menu

22 Temmuz 2013 Pazartesi

Unity, Dropbox and BitBucket



Story Behind

 

In this post,i will talk about how we have moved our project from DropBox to BitBucket.You might have questions popping in your mind asking whats the common point of BitBucket and DropBox ? The very first reason why we wanted to use DropBox was having backups and able to always be in sync.And we were lazy create a Version management system.

When we have first started this project with my team we didn't put a lot of thought on how much space it would require to maintain a Game project on DropBox.Me and my Graphic designer had a lot of space on DropBox,so It seemed like a good idea.Well it wasn't ! The current size of the project for a 35mb game is more than 24gb with all of its backups,builds etc.We might have deleted some of our old Source Codes and Builds but i am a bit emotional about that.I do like to see how this project moved on from the very beginning untill the 0.8g which is the current version(Here is the Twitter page if you are interested.We are coming Soon !. Link)

After struggling a long time with the limited space and conflict issues on DropBox (Which is normal,it was a Cloud service not a Version Control tool after all.) we decided to move on to a better system.That's where i started make a research about how ?

After a little bit of research i found that BitBucket to be a treasure.Free up to 5 people, no size limitations...I thought they should be crazy to offer that stuff for free.I started installing GIT,KDIFF and other stuff to make the system working.And luckily i have created a small Guide for my team mates which i will share with you too.

How to Start Using BitBucket 


As i said I'm not an expert on GIT or BitBucket.Those are the notes that i have been taking while i was preparing the system.And they have worked fine so far for me and my team mates.By following the below steps you can easily(wasn't very easy for me tho) prepare your own version management system.

First things first,download the following software and get an account from BitBucket(There are other services such as GitHub etc too but im not going to talk bout them.Process should be similiar.)

BitBucket : www.bitbucket.com

Configuring Your Machine

  1. Open up your Unity Project.
  2. Click Edit/Project Settings/Editor.
  3. Change Version Control to Meta Files.
  4. Change Asset Serialization to Mixed.
  5. Sign Up to BitBucket.
  6. Create a Repository.(BitBucket will guid you its pretty easy.)
  7. Install GIT with the default parameters.
  8. Install Kdiff with the default parameters.
  9. Open Git GUI (search in windows search.)
  10. Click on Clone Existing Project button.
    1. Type  https://< -username- >@bitbucket.org/< -username- >/< -project name- >.git into Source field.This can be found on BitBucket overview page near HTTPS button.
    2.  For Target field choose a local folder to be synced with the BitBucket repository.(You might want to create structure like "Repositories/Project-name" to be able to add future Projects without cluttering.)
  11. Click Clone Button.
  12. It will take a while,take a Coffee !
  13. Bonn Appetite ! Now click on Edit/Options from the top menu bar.
  14. Enter your BitBucket user name and E-mail to the appropriate fields.
  15. Type kdiff3 into the Merge Tool fields.
  16. Save and Close.
  17. Navigate to your local Repository folder from Windows Explorer.
  18. Show hidden files from the settings.
  19. You will see a Folder named .git.Open that folder.
  20. Edit config file and add following lines to it;
    1. [mergetool "kdiff3"]
       path = C:/Program Files (x86)/KDiff3/kdiff3.exe
       keepBackup = false
       trustExitCode = false
    2. [http]
      postBuffer = 524288000 
  1. Replace path with the Installation folder of Kdiff.
  2. Done ! You Git is Ready to Use !

Push,Pull... ?

 

Don't worry we don't have to do actual pushing and pulling ! But you have to get used to those terms to able to use GIT.
  • Push : Means you are sending your changes to the server.
  • Pull : Means you are downloading changes from the server and merging them with your local project.
  • Fetch : Means you are downloading changes from the server but not merging them yet.
  • Branch : Hmm... Think your BitBucket as a Tree.The main project is Master.Then as you progress in your project you may want to create Branches to develop new Features independently.Then at the end you can merge those branches back in to the Tree.

How to Commit Your Changes ?

  1. Open Git GUI.
  2. Click On Commit/Rescan from the top menu.(This will detect changes from the last time.)
  3. Now, Click on Commit/Stage Changed Files.(This will mark your changes to be Committed.
  4. Fill out the Description box below.Git GUI will warn you anyway.
  5. Click the Commit button near the Description box.
  6. Click on the Push button to actually send your changes to the sever.(For now just say ok the dialog box.)

How to Get Changes From the Server?

  1. Open Git GUI.
  2. Click on Remote/Fetch to download changes to your local Repository.
  3. Waiting is a virtue!
  4. After Fetching is completed Click on Local Merge.
  5. Select Tracking Branch.
  6. And find the branch that you want to merge with.
  7. This operation will open kdiff3 if any conflicts has been found.
    1. You should solve the conflicts by using kdiff tool to select correct one or merge the files manually by hand.
  8. That’s it you are done !

Create a New Branch ?

  1. Open GIT GUI.
  2. Click Branch/Create.
  3. Fill in the name field.
  4. Select Tracking Branch and Select the Branch which you want to create sub Branch from.(Probably master/origin)
  5. Click Branch/Checkout and Select the new Branch from the List.(This will switch your current branch to that.)
  6. Make your changes.
  7. Click Commit/Rescan
  8. Click Commit/Stage Changed Files To Commit
  9. Fill the description as explained before.
  10. Commit from the bottom of the window.
  11. Push the changes.
  12. From now on any changes you are making here will take a different path from the main project. And at one point we will merge those to branches into one.

How to Request a Pull to Merge the Branch ?

  1. Login into BitBucket website.
  2. Click on Pull Request button from the Project page.
  3. Select the Branch you have finished working on, on the left side.
  4. Select the branch which you want your work to merge into, on the right side.
  5. Enter a title and brief description of what you changed. As detailed as possible.
  6. Click Create Pull Request
  7. After that, Team Members will check this Pull Request and if it does not create any further problems they will approve it to merge with the Main Project.
  8. To approve a Pull Request you need to have Admin rights on the BitBucket.Than you can navigate to Pull Requests page select the new Pull Request and accept or decline it.




11 Aralık 2012 Salı

Pack It Up !

Draw Calls! We all hate it,we all have problems with it and it makes our games slow!

As you know there are lot of variables which might affect your games performance which i have explained in my earlier post.But even if you apply all those fixes,tricks whatever you call them,sometimes it's still not enough.So here it is another great way of optimizing performance.

First things first,What will you learn from that arcticle ?

I will explain Texture Atlases,Material sharing and a little bit about UV mapping.I will not go into detail of eveything,but you can ask in comments if you have any questions.

Texture Atlases


They are basicly a bunch of textures put in to a single big texture.But why do it ?First reason is preventing little hickups caused by loading textures.The catch is,when you put some textures together into one big image,vram only loads 1 texture and uses that for multiple objects in your game.This saves you from loading and unloading multiple textures all the time and with Material Sharing which i will explain later you will even save a lot of Draw Calls.
But how to do it ? I need to talk about a few more things before i can explain that.

 

 

 

 

Material Sharing

Imagine you have 5 objects,lets call them planets.They all need a different texture and a different material to hold this texture.And lets say all those planets will use the same shader.Well normally you would create 5 materials and assign 5 different textures to those materials.But that will cause 5 draw calls to draw all those planets.This is where material sharing becomes usefull,It reduces Draw Calls to 1 and also reduces the texture loading hickups with the help of Texture Atlases.

After explaining UV maps i can finally explain how to do it step by step.Because understanding those parts are quite important.


UV Mapping

Well,what is that UV thing ?Pretty straight forward,It maps your texture into your model.In the exmaple you can see a monkey texture mapped onto a head model.













 

 

But,How to do it ?

We will be using our planets again as an example.
  1. We have 5 planets and 5 textures in our hands.
  2. First we have to convert them into a Texture Atlas.
  3. You can use Texture Packer for that job.It works quite good and has a lot of options for different needs.
  4. To create a basic Texture Atlas.

    1. Run the program.
    2. Drag your textures to the right pane.
    3. Choose a place to save your file by filling Texture file box.
    4. After that you should play with the settings and choose what is best for your file.Sometimes the best atlas is when there is minimal empty spaces left or sometimes its best when all the textures are at the same size.Depends on your needs.
    5. Then you have to assign your new texture into a single material in Unity.
    6. Untill here we have created our Texture Atlas and material which will be shared across multiple objects.
      After this part we need to make a little bit coding.
      Read the code below carefully.It divides a single texture into defined rows and columns,then maps the UV to the desired part of that Texture.
      This script only works for planes which has 4 UV points.But it can be extended very easily.(As an example the one i'm using in my project can work with any model and also can animate the textures on them).
      I just didn't wanted to give you everything for free(No i'm not talking about money:)).Read the code,understand and make some simple changes to make it work with any model.Trust me just a few lines will make it work with any model !
      using UnityEngine;
      using System.Collections;
      
      public class TextureAtlasReader : MonoBehaviour
      {
      
          public int totalColumns = 3;
          public int totalRows = 3;
          public int row;
          public int column;
          Mesh _mesh;
          Vector2[] _uvs;
          Vector2 _dimensions;
          void Awake()
          {
              _mesh = gameObject.GetComponent<meshfilter>().mesh;
              Texture _texture = renderer.sharedMaterial.mainTexture;
              _dimensions = new Vector2((_texture.width / totalColumns) / (float)_texture.width,
                                       -((_texture.height / totalRows) / (float)_texture.height));
              Vector2[] _uvs = new Vector2[_mesh.uv.Length];
      
              Vector2 offset = new Vector2(column * _dimensions.x, 1 - (-_dimensions.y * row));
              _uvs[0] = offset + new Vector2(_dimensions.x * 0.0f, _dimensions.y * 1.0f);
              _uvs[1] = offset + new Vector2(_dimensions.x * 1.0f, _dimensions.y * 1.0f);
              _uvs[2] = offset + new Vector2(_dimensions.x * 0.0f, _dimensions.y * 0.0f);
              _uvs[3] = offset + new Vector2(_dimensions.x * 1.0f, _dimensions.y * 0.0f);
              _mesh.uv = _uvs;
          }
      }
      
    7. The last step ! 
      1. Just attach this script to the "Plane" which you want to use Texture Atlasing.
      2. From Editor GUI;Enter total row and column count.
      3. From Editor GUI;Enter the row and column  which you want to use for each object.
    8. And thats all ! Now you are sharing Material between multiple objects and drawing them in just a single Draw Call.

 Things to be aware of:

  • Sometimes it can be better not to use Texture Atlases.
  • You can use this code wherever you want.But if you use in your game it would be good drop by and leave me a message.So i can check you game :)
  • If you have made a better version,i would be glad to see it.
  • I'm not saying this is the best method.
  • My english is not the best. :)
  • For further Performance Optimization read Draw Call Batching from Unity website.
It took great amount of time to learn it when i was just beginning game development.So i hope it will save you a little bit of time.

26 Kasım 2012 Pazartesi

The Other Ideas

When developing games and probably all the creative stuff that requires team work,you will face some moments that you think that your idea is the best but the other people in your team just can't understand you.

Well,we all have those moments.But what i've learned from all those projects  and teams is sometimes you just have to stop for second ,clear your mind and take look at your self from their eyes.I know it sounds so cliche,but hey,it works.I have been in so many arguments that i thought my idea was better.But after really thinking about their idea and considering it "seriously",i realized sometimes their ideas are just better or sometimes we can even find a new idea by mixing our ideas together.

Sometimes we care more for ourselves than the product we are trying to build.We do this by knowing our unconsciously.But when you take a breath and see yourself from far,you will understand you are a team and you should discuss everything,but you should respect others ideas as much as yours.When you don't do that,the decisions on the project will be quite hard to finalize and you will start to lose the team spirit.

So whatever you do,if you want a publish a good game,remember that you are not the sole developer on that project and it's always good to hear out what other people had to say.They can see the points your are missing or find a better alternative.

Always trust in your team !


4 Kasım 2012 Pazar

Spikes Everywhere !

I'm sure when you start developing a new you are seeing those nasty spikes on your profiler.(If you are not using it, better start now :) )Those spikes are very important especially if you are developing for mobile.There are a lot of reasons for those spikes,unoptimized code,oversized textures etc.
I will try to cover solutions for those problems,

Cache,Cach,Cache
If you are a researcher type or read some artciles about optimization you already now that you should Cache everything you can.
So what does it mean caching anyways ?

using UnityEngine;
using UnityEngine;
using System.Collections;

public class example : MonoBehaviour 
{ 
    //Create the variable to hold our cached transform.
    private Transform _transform;
 
    void Awake() 
    {
        //Cache the Transform in the _transform variable.
        _transform = transform;
    }

    void Update()
    {
        _transform.position = Vector3.Zero;
    } 

} 

Lets interpret the code together.
First we have created a new variable with the type of Transform.Then at the Awake() method we  have cached our transform object into _transform variable.After that whenever we need to access the Transform object we can just use the _transform variable and save a lot of processing power.If you don't do this whenever you call transform component,Unity will have to make an expensive component lookup.

And another great thing,you can this for all the objects you will have to acces a lot of times.

Spike when using GetComponent Method
Whatever you do,try to avoid this and similiar methods that can cause Component Lookups.Everytime you use this methods Unity will have to search all the components to find what you are looking for.And it can be a really slow and expensive process.Try to cache that kind of items at the Awake() or your Start() methods which will be little bit slower to initiate but a lot more faster to use in game.

Instantiating Objects
Well instantiating objects can really be an expensive process.There are a couple ways to avoid this problem.One of them is using a Pool Manager.A Pool Manager basicly instantiates the objects that will be used in game at the loading screen and keeps them in memory for later use.And this saves us lot of cpu and gpu power when we actually need the game objects.We only have to enable and reposition the objects we have instantiated and kept in memory at the beginning.

Destroying Objects
Destroying objects are actually a hidden cost.Destroying a couple of objects usually won't create an instant spike.But everything starts when the Garbage Collector comes to clean around.This will create a spike if you have Destroyed a lot of objects.The reason behind this is Garbage Collector got called from time to time automatically to free up the unnessecary memory(Destroyed objects etc...).

There are 2 solutions i know for this problem.First one is triggering GC.Collect() method with short intervals to force Garbage Collector to clean memory more frequently which can make garbage collecting faster due to cleaning less memory each time.But i don't usually use this method since it can also create spikes sometimes.Another method is Object Pooling which i have explained before.When u are done with an object just disable it and wait for the time when u will need it.That way there is no objects destroyed and there wont be much job for garbage collector to do.And it also saves time when enabling that object instead of instantiating new one.

Big Spike On The Obcects First Appearance
This problem is one of the most common problems and it can be solved pretty easy with preloading objects.

Preloading is actually a simple yet very effective idea.The idea is showing each object to the camera at loading screen and let the camera render the each object.This way all your objcets will already be rendered and loaded into vram and thanks to that,Loading the texture etc. won't be necesary when the object is actually needed.

Note that preloading objects and Pool Manager methods are solutions for two different problems.Preloading is to save from first rendering time.Object Pooling wont make any visual preloading into memory.

Use Correct Shader
Shaders are very important for performance.And sometimes choosing wrong shader can cost you a lot of fps.First step is to check if you really need all the features of the shader you are using.If not find another shader which can fit better for your needs.For example if you are developing for Mobile you should always use shaders under the Mobile category in Unity.Those shaders are highly optimized for Mobile.But if you still have performance problems caused by shaders you even write your own to save even more performance.

Correct Compression Method
Choosing correct compression method for images and other media is also very important.For example using a 1024x1024 texture for an object that would look the same with 256x256 makes your game use a lot more memory then needed.And if you are using advanced mode for texture compression carefully decide which compression method you are using.Not all platforms support all of the compression methods.You will have to do a little research and experiment with compression methods the find the best fit for your needs.
Also for sounds and other media try to use ogv and ogg extensions which is natively supported by Unity.

Coroutines Are Your Friend
Using Corotuines for big loops or a method with lot of calculations etc. can be a great performance saver since it will not block other objects from doing their job.You can inspect the below example which is quite self explanatory.

using UnityEngine;
using System.Collections;

public class example : MonoBehaviour {
    //This method will take 1000 frames to finish its job but will not block other scripts or methods from running.
    //And it will let other object to their job each frame due to yield method WaitForEndOfFrame().
    IEnumerator Routine() 
    {
 for(i = 0;i < 1000;i++)
 {
  Debug.Log(i);
  yield return new WaitForEndOfFrame();
 }
    }
    //This will take less time to finish but it will block everything else till it finishes its job.
    void Normal()
    {
 for(i = 0;i < 1000;i++)
 {
  Debug.Log(i);
 }
    }
    void Start() 
    {
        StartCorotuine(Routine());
 Normal();
    }
}

Stop Animating Invisible Objects
Animating an invisible object is not a very logical thing to do.Stopping animation and other complex calculations while the object is not visible can save a lot of performance.In below example the Animation is Stopped when the object became invisible and Played when the object is visible again.

using UnityEngine;
using System.Collections;

public class example : MonoBehaviour{
    void OnBecameVisible() 
    {
        animation.Play();
    }
    void OnBecameInvisible() 
    {
        animation.Stop();
    }
} 

It's pretty much the basic and most important stuff for optimizing your game.I will try to keep you updated when i will have more time to share more with you !

If you have questions feel free to ask.I will try to answer them all.

Also check out those great pages by Unity team,
- www.docs.unity3d.com/Documentation/Manual/iphone-PracticalGuide.html
- www.blogs.unity3d.com/.../shadowgun-optimizing-for-mobile-sample-level/

3 Kasım 2012 Cumartesi

Changing The Topic

Sorry !
Sorry for not posting anything for longtime from everyone who was following this blog.I was quite busy at these last months(i know almost a year after my last post.).

The Change ?
OK,my working area has been changed a little bit since the last time i have posted.Well,I'm not a student anymore and started developing games for mobile and desktop platforms.So from now on i will try to post articles about game development.Mostly about the problems we have experienced with our team,the solutions we have found and some know-hows and best practices.

Since I'm a developer,the content will be highly focused on coding.But since I'm also an old designer and a little bit inside of the project management stuff,you will see posts about them as well.
For our new cross platform project(sssh its secret) with our team,we are using Unity3d Game Engine,which works quite well with most paltforms.

I hope it will be helpfull for those who want to start game developed or those having problems with game development.

Stay tuned !