Tuesday, April 22, 2014

Android Signing - Just before you upload to Google Store you need a keytool - sign your apk file

For development you dont need but for for publishing (i.e. Android Market) you have to sign in your  apk file.

1) Locate the Publishing Settings under PlayerSettings
2) Create a new keystore by selecting a keystore name and password (confirm the password)
3) Select "Create a new key" under Key Alias
4) A new window opens; enter the necessary information.
5) Select the newly created key.
6) Build ( & Run); your app is now signed.

Dont forget your password. That is important. If you ever forget your password you cant upload your apk file later! Always remember the passwords; they are not stored with the project (for security reasons).


Big List of Indie Game Earnings - Success stories.

Found a good webpage, which has lots of indie gamer earnings. A real good list of success stories. Be sure to read on http://www.pixelprospector.com/the-big-list-of-game-revenue-sales.


Here are the links, (I wanted to archieve this if orijinal post will somehow dissapear in the future)

---


Wednesday, April 9, 2014

Unity3d - MiniJSON - Facebook SDK for Unity

MiniJSON knowledge

1) Anything that is wrapped in curly brackets {}  converts to "Dictionary<string, object>"
2) all the keys are sthe strings on the left side of the colon (:)
3) values are on the right side of the colon (:)
4) anything wrapped in square brackets [] convert to a List<object>
5) all values converts to System.String which then be converted to whatever type you want with the system string convert functions.

Some examples to serialize / deserialize facebook sdk output in Unity3D:


void OnLoggedIn()                                                                        
{                                                                                        
//Debug.Log("Logged in. ID: " + FB.UserId);
// Reqest player info and profile picture                                                                        
FB.API("/me?fields=id,first_name,last_name,picture,friends.limit(10).fields(first_name,id,last_name,picture)", Facebook.HttpMethod.GET, APICallback);
//LoadPicture(GetPictureURL("me", 128, 128),MyPictureCallback);
}

void APICallback(FBResult result)                                                                                            
{                                                                                                                            
Debug.Log("APICallback");                                                                                              
if (result.Error != null)                                                                                                
{                                                                                                                        
Debug.LogError(result.Error);                                                                                          
return;                                                                                                              
}              

myFacebookProfile = DeserializeJSONProfile(result.Text);
// Debug.Log("+++++++++++ facebook profile :" +
//          "firname: " + myFacebookProfile.first_name +
//          ", lastname:" + myFacebookProfile.last_name +
//          ",id: " + myFacebookProfile.id +
//          "picture: " + myFacebookProfile.profile_image_url+
//          ",is_silhoutte" + myFacebookProfile.Profile_image_is_silhoutte);


myFacebookFriends =  DeserializeJSONFriends(result.Text);
int i = 0;
foreach (FacebookProfile fd in myFacebookFriends) {
i++;
Debug.Log("+++++++++++" + i +") nolufriend:" +
         "firname: " + fd.first_name +
         ", lastname:" + fd.last_name +
         ",id: " + fd.id +
         "picture: " + fd.profile_image_url+
         ",is_silhoutte" + fd.Profile_image_is_silhoutte);
}
}


public FacebookProfile DeserializeJSONProfile(string response)
{
FacebookProfile profile = new FacebookProfile();
Dictionary<string, object> responseObject = Json.Deserialize(response) as Dictionary<string, object>;
object nameH;
Dictionary<string,object> tempDictionary;

if (responseObject.TryGetValue("first_name", out nameH))
{
profile.first_name = (string)nameH;
}
if (responseObject.TryGetValue("last_name", out nameH))
{
profile.last_name = (string)nameH;
}
if (responseObject.TryGetValue ("id", out nameH)) {
profile.id = (string)nameH;
}

if (responseObject.TryGetValue ("picture", out nameH)) {
tempDictionary = (Dictionary<string,object>) nameH;
if (tempDictionary.TryGetValue ("data", out nameH)) {
tempDictionary = (Dictionary<string,object>) nameH;
profile.profile_image_url = (string) tempDictionary["url"];
profile.Profile_image_is_silhoutte = (bool) tempDictionary["is_silhouette"];
//resim bilgisi gönderilmiş ise, resmi download edelim arka planda:
if(profile.Profile_image_is_silhoutte == false) {
StartCoroutine(LoadProfilePictureEnumerator(profile));
}
}

//Dictionary<string,object> friendPictureData = (Dictionary<string,object>)((Dictionary<string,object>)responseObject["picture"])["data"];
//profile.profile_image_url = (string) friendPictureData["url"];
//profile.Profile_image_is_silhoutte = (bool) friendPictureData["is_silhouette"];
}

return profile;
}

public List<FacebookProfile> DeserializeJSONFriends(string response)
{
List<FacebookProfile> facebookFriends = new List<FacebookProfile>();
var responseObject = Json.Deserialize(response) as Dictionary<string, object>;
object friendsH;
Dictionary<string,object> tempDictionary;

bool runned_once = false;
do {
if (!responseObject.TryGetValue("friends", out friendsH))
{
break;
}

List<object> friendsDataContainer = (List<object>)(((Dictionary<string, object>)friendsH)["data"]);
foreach (Dictionary<string,object> friendData in friendsDataContainer) {
FacebookProfile friend = new FacebookProfile();

if (friendData.TryGetValue("first_name", out friendsH))
{
friend.first_name = (string)friendsH;
}
if (friendData.TryGetValue("last_name", out friendsH))
{
friend.last_name = (string)friendsH;
}
if (friendData.TryGetValue ("id", out friendsH)) {
friend.id = (string)friendsH;
}


//resimleri bulmak için bir tur daha aşagı inecegiz

if (friendData.TryGetValue ("picture", out friendsH)) {
tempDictionary = (Dictionary<string,object>) friendsH;
if (tempDictionary.TryGetValue ("data", out friendsH)) {
tempDictionary = (Dictionary<string,object>) friendsH;
friend.profile_image_url = (string) tempDictionary["url"];
friend.Profile_image_is_silhoutte = (bool) tempDictionary["is_silhouette"];
//resim bilgisi gönderilmiş ise, resmi download edelim arka planda:
if(friend.Profile_image_is_silhoutte == false) {
StartCoroutine(LoadProfilePictureEnumerator(friend));
}
}

//Dictionary<string,object> friendPictureData = (Dictionary<string,object>)((Dictionary<string,object>)responseObject["picture"])["data"];
//profile.profile_image_url = (string) friendPictureData["url"];
//profile.Profile_image_is_silhoutte = (bool) friendPictureData["is_silhouette"];
}


//
// //var friendPictureDataContainer = friendData ["picture"] as Dictionary<string,object>;
// //var friendPictureData = friendPictureDataContainer["data"] as Dictionary<string,object>;
// Dictionary<string,object> friendPictureData = (Dictionary<string,object>)((Dictionary<string,object>)friendData["picture"])["data"];
//
// friend.profile_image_url = (string) friendPictureData["url"];
// friend.Profile_image_is_silhoutte = (bool) friendPictureData["is_silhouette"];
//
// //profile resmini arka planda download et ve profile classına yükle
// StartCoroutine(LoadProfilePictureEnumerator(friend));

//friend bilgilerini listeye ekle
facebookFriends.Add(friend);
}
runned_once = true;
} while (!runned_once);
return facebookFriends;
}


How to invite friends using Facebook SDK for Unity3D

Yıu can call this code for inviting your facebook friends using Unity3D facebook SDK.


if(FB.IsLoggedIn)
{
    FB.AppRequest(
        message: "Come and Play This Game!",
        title: "My Game Invitation For Facebook Friend",
        callback: InviteCallback
    );
}

// ...

void InviteCallback(FBResult response)
{
Debug.Log("facebook invitation from Unity3D sent");
}



if(FB.IsLoggedIn)
{
    FB.AppRequest(
        message: "Come and Play This Game!",
        title: "My Game Invitation For Facebook Friend",
        callback: InviteCallback
    );
}

// ...

void InviteCallback(FBResult response)
{
Debug.Log("facebook invitation from Unity3D sent");
}



If your app is in sandbox mode, people won't get notified when the request is sent. So change your facebook application settings to "public"  in https://developers.facebook.com/apps page, goto "Status & Review" tab on le menu on the left. On the right you will see "Do you want to make this app and all its live features available to the general public?" question. Set its value to "YES" . If you cant modify YES/NO section then you have to give your application a contact email  on "Settings" tab on left menu.



Look for the request in https://www.facebook.com/appcenter/requests as the recipient and see if the request shows up there.



How to check facebok invitations: 

If you want you can also check invitation from FBResult response object, maybe even call how many people does this invitation is sent. An example code:

private void InviteCallback(FBResult result)
    {
        if (result != null)
        {
            var responseObject = Json.Deserialize(result.Text) as Dictionary<string, object>;
            IEnumerable<object> objectArray = (IEnumerable<object>)responseObject["to"];

            if (objectArray.Count() >= 3)
            {
                // 3 facebook invitations send. Give user a free item or bonus etc.
            }
        }
    }


Btw, facebook also gives us nice shiny login buttons, which can be downloaded from this address: https://developers.facebook.com/docs/facebook-login/checklist .






Tuesday, April 8, 2014

How to download content or picture image in the background using WWW class?

 Unity3D has a utility module for retrieving the contents of URLs named as WWW class. WWW class can also download a picture image,  so that you can assign that picture on the internet as a Texture in your Unity3D project.



Remember, WWW class is a Coroutine and runs background.

I can recommend two different ways of implementing background downloading in Unity3D.

First way; You can just yield it until it is completed. For example:

void IEnumerator Start() {
    WWW www = new WWW( url );
    yield return www;
   Texture2D myPicture = www.texture;  //this is how you download and image from web in untiy3d.
}


Second Way;  you can inspect the isDone property of WWW class to see if the download has completed or not. Here is an example of using the isDone and progress properties:

float progress = 0.0f;
void IEnumerator Start() {
    WWW myW = new WWW( url );
    while( !myW.isDone )
    {
        progress = myW.progress;
        yield return null;
    }
    progress = 1.0f;
}

Tip: You can create a progress bar with that progress property in OnGUI function.



Thursday, April 3, 2014

Unity3D and facebook SDK login problem for android devices

So you created you Unity3D game, integrated with Facebook's shining plugin. But still you are not able to login right? Infact nothing happens when you click that login button.

here is the problem: key_store hash!

I know you installed openssl and put your key on your facebook page.

well the thing is your key_hash is not valid.

When you debug your application with adb logcat, you can see a row like this:

"W/fb4a(:<default>):BlueServiceQueue(19773): com.facebook.http.protocol.ApiException: Key hash ******* does not match any stored key hashes."

**** = a key hash which I masked for privacy reasons.

well use that key_hash on your facebook app page.

go https://developers.facebook.com/apps  and select your aplication, choose "Settings" from the menu on the left and write that key hash which you see on the adb logcat log on facebooks key hashes part.  Save and update facebook.

that is it.

If you dont know how to use adb log cat, read my article on this url:

---

Here is a quick how to use adb :

1) goto your sdk installation directory, (adt\sdk\platform-tools) and run this command:
adb logcat  > mylog.txt

this command will dump all logs to mylog.txt file. open that file and search for key hash keyword on the log.  To Search adn solve your login problem ,  do these:

i) open mylog.txt in your favourite text editor.
ii) search this word: ApiException
you will find some rows like this: 

W/fb4a(:<default>):BlueServiceQueue(26232): com.facebook.http.protocol.ApiException: [code] 404 [message]: Key hash yd13SdjudjDdwdwedWsdddcwVJW  does not match any stored key hashes. [extra]: null
( there you will find your real key hash: yd13SdjudjDdwdwedWsdddcwVJW) 

iii) put  an extra = sign at the end and key hash become like this: yd13SdjudjDdwdwedWsdddcwVJW=

iv) copy paste this keyhash into your facebook developer page. all your facebook sdk login problems will be gone. 
 ----

These steps also valid for macbook - macos unity - fcebook login sdk problems. 


There you will find your real key hash. Use this key hash on facebook key hashes form. The one unity creates is false.


------

btw Isearched a lot on internet and find these solutions below. But I did not try any of them. so you can also try these ones:

1) Some people say openssl which you install really matters and recommends to install a spesific version. Maybe with that openssl unity panel will give you the real key hash, I did not try try that.

2) Also create two key hashes one for debug one for release with these commands:

keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64

keytool -exportcert -alias yourappreleasekeyalias -keystore ~/.your/path/release.keystore | openssl sha1 -binary | openssl base64

some urls you may invetigate further:
http://stackoverflow.com/questions/13894006/android-facebook-sdk-3-0-gives-remote-app-id-does-not-match-stored-id-while-lo/16059786#16059786

http://answers.unity3d.com/questions/576088/facebook-sdk-simple-login.html

http://stackoverflow.com/questions/13894006/android-facebook-sdk-3-0-gives-remote-app-id-does-not-match-stored-id-while-lo

http://stackoverflow.com/questions/19051361/facebook-unity-sdk-on-android-login-fails-when-fb-app-installed/19091114#19091114

http://stackoverflow.com/tags/facebook-unity-sdk/hot

http://answers.unity3d.com/questions/609810/using-facebook-api-with-android-says-login-is-canc.html


Wednesday, April 2, 2014

how to debug unity3d with adb logcat

There is something called the logcat, which is a combined message pipe from all applications. To read it you first need to locate the adb tool that comes with the Android SDK. Depending on which version you have of the SDK the adb is located either under<sdk>/tools or<sdk>/platform-tools.

Simply start it like this:

$ adb logcat

and it will start printing out everything that is going on on the device. To limit it to only show the output from inside Unity, you can try this:

$ adb logcat -s Unity

or, to get a little bit more info about what's going on:

$ adb logcat -s Unity ActivityManager PackageManager dalvikvm DEBUG

If you wish to report a bug or otherwise 'quote' the logcat, you can dump the complete logcat to a file like this:

$ adb logcat -d > logcat.txt

unity3d and facebook sdk problem - Error building Player: Win32Exception: ApplicationName='C:\Program Files (x86)\Java\jre7\bin\javac.exe',

If you are going to use facebook SDK for unity3d, then you will get these problems.

If you come across with this error: 
Error building Player: Win32Exception: ApplicationName='C:\Program Files (x86)\Java\jre7\bin\javac.exe',

then you only have Java JRE which does not come with javac.exe. You must install JAVA JDK from java website . Also be sure to read about  PATH Environment Variable (Optional) on java documentation page.  

You need JAVA JDK ! Not JRE !



here is the way to set environment table for java path: 
C:\> "C:\Program Files\Java\jdk1.7.0\bin\javac" MyClass.java
It is useful to set the PATH variable permanently so it will persist after rebooting.
To set the PATH variable permanently, add the full path of the jdk1.7.0\bin directory to the PATH variable. Typically, this full path looks something like C:\Program Files\Java\jdk1.7.0\bin. Set the PATH variable as follows on Microsoft Windows:
  1. Click Start, then Control Panel, then System.
  2. Click Advanced, then Environment Variables.
  3. Add the location of the bin folder of the JDK installation for the PATH variable in System Variables. The following is a typical value for the PATH variable:
    C:\WINDOWS\system32;C:\WINDOWS;C:\Program Files\Java\jdk1.7.0\bin
Note:
  • The PATH environment variable is a series of directories separated by semicolons (;) and is not case-sensitive. Microsoft Windows looks for programs in the PATH directories in order, from left to right.
  • You should only have one bin directory for a JDK in the path at a time. Those following the first instance are ignored.
  • If you are not sure where to add the path, add it to the right of the value of the PATH variable.
  • The new path takes effect in each new command window you open after setting the PATH variable.


also you may have to set JAVA_HOME to the directory on your machine that does have JDK (and javac.exe) installed.


here is a step by step how to change JAVA_HOME directory:

Set the JAVA_HOME Variable
Once you have the JDK installation path:
  1. Right-click the My Computer icon on
  2. your desktop and select Properties.
  3. Click the Advanced tab. Click the
  4. Environment Variables button. Under System Variables, click New.
  5. Enter the variable name as JAVA_HOME.
  6. Enter the variable value as the installation path for the Java Development Kit.
  7. Click OK.
  8. Click Apply Changes.
You might need to restart windows.
NOTE: You have to put the path to the jdk without /bin in the end.
For example:  C:\Java\jdk1.6.0_44 , NOT C:\Java\jdk1.6.0_44\bin.

You have to restart Unity3D so that unity can read the new java home path. After this you can build your unity3d game with facebook sdk without any problems.



Btw, if you need openssl for windows to create keystore for facebook sdk for unity3d, you must first download openssl and extrac its bin folder content to C:\Program Files\Java\jdk1.8.0\bin (or whereever you java install dir is) then add C:\Program Files\Java\jdk1.8.0\bin to enviroment path.

and to create keystore: 

keytool -exportcert -alias androiddebugkey -keystore %HOMEPATH%\.android\debug.keystore | penssl.exe sha1 -binary | openssl.exe base64



and the SECOND common problem is this error: 
... your android debug keystore file is missing ...

This second problem is  EASY  to fix. 
This happens when your your Unity project is on another drive than C: drive. Anyway this is not a problem. You need to fix a c# script in facebook directory in your unity project panel. Locate Facebook>Android>FacebookAndroidUtil cd file.  Open file. Find this row: 
System.Environment.GetEnvironmentVariable("HOMEPATH") + @"\.android\debug.keystore" : 
and change it with this one: 
System.Environment.GetEnvironmentVariable("HOMEDRIVE") + System.Environment.GetEnvironmentVariable("HOMEPATH") + @"\.android\debug.keystore" :

save the file. and restart unity3d. you will see that your problems will go away :)