viernes, 25 de octubre de 2013



/* Some arduino experiments */


I´m working with some friends to make a portable videogame console, based on OMAP4 (arm cortex-a9 and SGX540 gpu), with Arduino as input, and Android as SO ( I would like to use linux arm, but Unity it´s not available for this platform).

The first test are playing with the arduino, we have two arduino UNO and a ESPLORA board. We would like to make our own PCB with gyro/accel two joysticks and other things like vibrator, but the ESPLORA board is a really good one to start with.

There are three phases:
a) program Arduino board
b) program a SerialPort library
c) program a Unity plugin for using the arduino.

The work is done, but it was more difficult than expected...

a) You have to program the arduino board to spit all sensor states (joystick and switches for example), while program the arduino to receive commands, both things from serialPort.

b) You can write a small C/C++ for desktop platform (windows/linux/mac x86) program to ensure you arduino sketch works as spected; ok, the terminal is showing the arduino´s vomit (I mean, the input values).

Now, encapusle the library into dll file, and create some static functions and variable in order to use on c# (Unity3d)

c)StringBuilder works in editor, not in builds...

After learning how to connect a in/out variable (the buffer of the serialPort, char* ) from c to c#, we have unity showing the arduino´s vomit too (cool). But it shows corrupt data.
casting from byte[] and char[] solve the corrupt data (uff).

Now all work is a joke:

Connect/Disconnect the serial port, if you don´t release the serail port correctly, you will have problems

SerialPort has some errors, we have to imlement some kind of checksum to ensure the line you are reading from buffer is complete and valid.
Sync arduio output with unity it´s not easy, and it´s not good, because I would like to make the library FPS indpenent, so, modify the code to read much quickly than arduino, and much slowly than arduino.
Lag appears, lag go far away XD

And we can change the RGB LED from unity if you are near a light for example. Now the Explora is working really good ;)


How to parse char * buffer from C to C# via dll.


The C function:
extern "C" int  DLLIMPORT ReadDataSP(char *buffer, unsigned int nbChar);


The C# function
[DllImport ("SerialPort")]
public static extern int ReadDataSP( [In, Out] byte[] buffer, int nbChar);

And the usage:
 
byte[] incomingData = new byte[1024];
SerialPortBridge.ReadDataSP(incomingData,dataLength);

string s = System.Text.Encoding.UTF8.GetString(incomingData);

Debug.Log(s);


Cleaning Unit3d projects, remove unused assets



For some reasons, it´s easy to fill a unity project with a lot of materials, animations, test meshes, unused lightmaps etc... Cleaning by hand a projects it´s not a easy task, because (for example) you could have some materials on some folders that you can delete and then... you will see the magic material:




Here is some help to clean your projects:

(it´s a modification from this one: http://zaxisgames.blogspot.com.es/2012/02/automatically-locate-all-unused-assets.html )


CleanUpWindow.cs
 
 
 using UnityEngine;  
 using UnityEditor;  
 using System.IO;  
 using System.Collections;  
 using System.Collections.Generic; 





////////////////  
//Exclude .metas, .svn folders,prefabs and Editor and Plugin Folders.  
////////////////  


public class CleanUpWindow : EditorWindow  {  



 List usedAssets = new List();
 List unUsedAssetsString = new List();
 List includedDependencies = new List(); 
 
   
 private bool needToBuild = false;  
   static bool readyForDelete = false;  
 
 
 
 
[MenuItem("Window/CleanUpWindow")]  
static void Init(){  
  
 // Get existing open window or if none, make a new one:   
 CleanUpWindow window = (CleanUpWindow)EditorWindow.GetWindow(typeof(CleanUpWindow));  
 window.Show();  
 readyForDelete = false;  
}  
 
 
 
void OnGUI(){  
  
 if (needToBuild){  
  GUI.color = Color.red;  
  GUILayout.Label("Are you sure you remembered to build project?", EditorStyles.boldLabel);  
 }
  
 GUI.color = Color.white;  
 if (GUILayout.Button("Load EditorLog")) {  
  loadEditorLog();  
  if (!needToBuild){  
      readyForDelete = true;  
         listAssest();  
  }  
  }  
  
 if (!needToBuild){  
   
  GUI.color = Color.red;  
  if (GUILayout.Button("Clear EditorLog")){  
   clearEditorLog();  
   readyForDelete = false;  
   needToBuild = true;  
  } 
   
  GUI.color = Color.white;  
  if (readyForDelete){  
   if (GUILayout.Button("Delete Unused Files")){  
        deleteAssets();  
        readyForDelete = false;  
   }  
  }
   
 }
  
}  
 
 
 
 
 
private void listAssest(){  
  
 if (!needToBuild){ 
   
  if (unUsedAssetsString.Count >= 1){  
   // List all unused Files  
   string allUnusedFiles = "";  
   for(int i = 0; i < unUsedAssetsString.Count; i++){  
      allUnusedFiles += unUsedAssetsString[i] + "\n";  
   }  
   Debug.Log("UnUsed Assets*_*");  
   Debug.Log(allUnusedFiles);  
  }  
 } 
  
}  

 
 
 
 
 
 
 
 
 
private void deleteAssets(){  

 if (unUsedAssetsString.Count >= 1){  
  // List all unused Files  
  string allUnusedFiles = "";  
  for(int i = 0; i < unUsedAssetsString.Count; i++){  
    File.Delete(unUsedAssetsString[i]);  
  }  
 }  
 
   
}  
 
 
 

private void clearEditorLog(){  
 
  /*As unity also uses Debug.log file, you will hava a zero bytes size file.
   * The best you can do is close unity and open again
   */
  
}  
 
 
 
 
private void loadEditorLog(){  
  
 UsedAssets.GetLists(ref usedAssets, ref includedDependencies); 
  
 if (usedAssets.Count == 0){  
  needToBuild = true;  
  readyForDelete = false;  
  unUsedAssetsString.Clear();
 }  
 else{  
  compareAssetList(UsedAssets.GetAllAssets());  
  needToBuild = false;  
 }  
}  
 
 
 
 
private void compareAssetList(string[] assetList){  
   
 unUsedAssetsString.Clear();
   
 for (int i = 0; i < assetList.Length; i++){
   
  if (!usedAssets.Contains(assetList[i])) unUsedAssetsString.Add (assetList[i]);                      
   
 }  
  
  
} 


 
}  

//Ignore this, html issue while getting syntax highligh 
//


//Ignore this, html issue while getting syntax highligh 
//

UsedAssets.cs
 

using UnityEngine;  
using UnityEditor;  
using System;  
using System.IO;  
using System.Collections;  
using System.Collections.Generic;  



public class UsedAssets  { 
 
 
public static string[] GetAllAssets()  {  
  
  
    string[] tmpAssets1 = Directory.GetFiles(Application.dataPath, "*.*", SearchOption.AllDirectories);  
    string[] tmpAssets3 = Array.FindAll(tmpAssets1, name => !name.EndsWith(".meta"));  
    string[] tmpAssets4 = Array.FindAll(tmpAssets3, name => !name.Contains("StreamingAssets"));  
    string[] tmpAssets5 = Array.FindAll(tmpAssets4, name => !name.Contains("Resources"));  
    string[] tmpAssets6 = Array.FindAll(tmpAssets5, name => !name.Contains("Plugins"));  
    string[] tmpAssets7 = Array.FindAll(tmpAssets6, name => !name.Contains("Editor"));  
    string[] tmpAssets8 = Array.FindAll(tmpAssets7, name => !name.EndsWith(".prefab"));  
    string[] tmpAssets2 = Array.FindAll(tmpAssets8, name => !name.Contains("svn"));  
    string[] allAssets;
  
 allAssets = Array.FindAll(tmpAssets2, name => !name.EndsWith(".unity"));  
    for (int i = 0; i < allAssets.Length; i++){  
   
      allAssets[i] = allAssets[i].Substring(allAssets[i].IndexOf("/Assets") + 1);  
      allAssets[i] = allAssets[i].Replace(@"\", "/");  
    }  
  
    return allAssets;  
}  
 
 
 
 
public static void GetLists(ref List assetResult, ref List dependencyResult) { 
  
    assetResult.Clear();  
    dependencyResult.Clear();  
    string LocalAppData = string.Empty;  
    string UnityEditorLogfile = string.Empty;  
    if (Application.platform == RuntimePlatform.WindowsEditor){  
   
      LocalAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);  
      UnityEditorLogfile = LocalAppData + "\\Unity\\Editor\\Editor.log";  
    }  
  
    else if (Application.platform == RuntimePlatform.OSXEditor){  
   
      LocalAppData = Environment.GetFolderPath(Environment.SpecialFolder.Personal);  
      UnityEditorLogfile = LocalAppData + "/Library/Logs/Unity/Editor.log";  
    }  
      try {  
   
        // Have to use FileStream to get around sharing violations!  
        FileStream FS = new FileStream(UnityEditorLogfile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);  
        StreamReader SR = new StreamReader(FS);  
        string line;  
        while (!SR.EndOfStream && !(line = SR.ReadLine()).Contains("Mono dependencies included in the build")) ;  
   
        while (!SR.EndOfStream && (line = SR.ReadLine()) != ""){  
          dependencyResult.Add(line);  
        }  
        while (!SR.EndOfStream && !(line = SR.ReadLine()).Contains("Used Assets,")) ;  
   
        while (!SR.EndOfStream && (line = SR.ReadLine()) != ""){  
         if( !line.Contains("System memory") ){  
               line = line.Substring(line.IndexOf("% ") + 2);  
               assetResult.Add(line);  
             }  
        } 
   
   
      }  
      catch (Exception E){
   
        Debug.LogError("Error: " + E);  
      }  
}
 
 

 
 
 
}  
//
//


-Close and open Unity editor and  build your game (to fill the Editor.log with the used assets).
-Open CleanUpWindow (from Window meu), and click on LoadEditorLog.

 At this poing you can see on the Editor a list of all your unused assets.

 -Click on Delete Unused Assets.

 This scripts will not touch the .svn folders, meta files, Plugin, Editor and StreamingAssets Folders, it also avoid to delete the prefab files: As unity does not use prefabs for build the game, all prefabs will show as unused, so you can´t choose between used or unused prefabs. Now you can check for emtpy folders, and move all your materials, textures and models to other folders. It´s a good idea to remove all .svn files too:



find . -type d -name '.svn' -print -exec rm -rf {} \;





jueves, 24 de octubre de 2013

SetActiveRecursively, Unity4 ,and older unity3.x projects




If you upgrade some projects from unity 3.x to unity 4, you will notice that the old SetActiveRecursively is obsolete.

There are a newer functionality regarding active and desactive gameObjects, now gameObject.active (or SetActive) do the same as SetActiveRecursivley, but with one difference:
Each gameObject on the hierarchy has their own active state, and the gameObject will be (or not) active if their own active state is true, and the state of their parents are true.

This is really cool, because you can active recursively a gameObject with some desactived gameObjects, but it´s not good if your projects come from older unity version:

If you check the active checkbox on the Inspector, the gameObject will be active without the old popUp window ask you for activate the childs too.

If you try it with scenes created on unity4 you don´t have this problem, but you can find this project on older scenes (from unity 3.x) with disabled gameObject, you will have this problem, and the solution:

Extend the contextMenu for Transform Component to add active and desactive recurively:



 

static function _activeRecursive (command:MenuCommand){  

       var mTransform : Transform = command.context;  
       activeRecursively(mTransform,true); 
 
}  


@MenuItem ("CONTEXT/Transform/DesActiveRecursive")  
static function _desActiveRecursive (command:MenuCommand){
  
       var mTransform : Transform = command.context;  
       activeRecursively(mTransform,false);  
}  

static function activeRecursively(mTransform:Transform,mState:boolean){  
        
      mTransform.gameObject.SetActive(mState);  
      for ( var child : Transform in mTransform){  
            activeRecursively(child,mState);  
       }  
}  




I had some problems using the graphics emulation (gles), so disable it.
After using the script the first time, you can use the new way: the checkbox from inspector.