2014年2月26日 星期三

Unity AssetBundle 取用 C#

1.事前工作。
 1.1遠端準備一份.csv打包成.AssetBundle的檔案,內容欄位名,版本名。
 1.2本機端建立一資料夾AssetBundle,放入同為1.1的.AssetBundle。
 1.3再建立一資料夾StreamingAssets(必需為此名),裡面存放另一份Local.csv檔。

2範例流程
  2.1從遠端位置VersionURL 取得 AssetBundle,內容為資源名+資源版號。
  2.2轉成binAsset ,將內容存入VersionArray_Server二維字串陣列。
  2.3各資源利用LoadFromCacheOrDownload()方法,填入路徑及取得的版本號,即自行會判斷 更新,也就是透過此機制,可動態更新使用者端的表格資料及資源的AssetBundle,但用於手 機的AssetBundle,資源中不可含Script(此部份為網路上文章說明,個人未實測證明)。

 2.4以上的資料是在建立於手機本機端的快取區作業。

 2.5在分隔線後面部份,是取出位於打包好的檔案中,類似Android的.apk檔中,也就是步驟1.3 所存放的Local.csv檔,使用Application.persistentDataPath()方法,在手機本體中指定路徑,產生 一個新的檔案,此檔案可進行修改的操作。

2.6取得資源型的AssetBundle,動態生成至Scence的範例方法如下:
     Instantiate(bundle.Load("Cube_R"));


3.於Unity Assets下建立Script,視需求將此Script置於物件中,範例是放在Main Camera下,程式碼如下。

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


private string VersionURL =連結目標自設";
private string BundleURL = "連結目標自設";
private string SceneURL = "連結目標自設";


private string[][] VersionArray_Server;
string UIVersion,CharacterVersion,MonsterVersion,SceneVersion,EquipmentVersion,TableVersion;
bool DownloadOK;
string WeaponTableVersion = "";
string LocalFileVersion ="";
string DBPath = "";
string filepath = "";


void Start()
{
DownloadOK = false;
//在此決定要向儲存體,下載那個版本

//取得+比對版本
StartCoroutine(DownloadVersion_Sever(VersionURL,"Version",BundleURL));
}

//取得伺服器表格    版本連結  檔名  表格連結
IEnumerator DownloadVersion_Sever(string VersionURL_Server ,string FileName ,string TableURL)
{

//更新版本表格
using (WWW asset = new WWW(VersionURL_Server))
{
yield return asset;
AssetBundle bundle = asset.assetBundle;

//bundle轉TextAsset 二進位文件
TextAsset binAsset = bundle.Load ("Version", typeof(TextAsset)) as TextAsset;

if(binAsset == null)
{
//沒取得版號,或內容不完整
Debug.LogError("VersionURL" + "no binAsset!!");
}
else
{
//讀取資料內容,遇到資料結尾\r,判定為一筆
string [] lineArray = binAsset.text.Split ("\r"[0]);

//建立存放陣列,依資料筆數,決定欄位數量
VersionArray_Server = new string [lineArray.Length][];

//把csv中的的數據填入陣列中 
for(int i =0;i < lineArray.Length; i++)  
{  
VersionArray_Server[i] = lineArray[i].Split (',');  
}
}
Debug.Log("Server端資料:" + GetDataByRowAndCol(0,0,VersionArray_Server)+ "+" +GetDataByRowAndCol(0,1,VersionArray_Server));
bundle.Unload(false);
}

//武器表格
using (WWW asset = WWW.LoadFromCacheOrDownload(TableURL, int.Parse(GetDataByRowAndCol(0,1,VersionArray_Server)))) //下載地址,版本號
{
yield return asset;

AssetBundle bundle = asset.assetBundle;

//bundle轉TextAsset 二進位文件
TextAsset binAsset = bundle.Load ("Weapon", typeof(TextAsset)) as TextAsset;

WeaponTableVersion = binAsset.text;

Debug.Log("已更換"+TableURL+"版本");
bundle.Unload(false);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------//

//各平台路徑
#if UNITY_EDITOR
filepath = Application.dataPath +"/StreamingAssets/Local.csv";
#elif UNITY_ANDROID
filepath = "jar:file://" + Application.dataPath + "!/assets/Local.csv";
#elif UNITY_IPHONE
filepath = Application.dataPath +"/Raw"+"/Local.csv";
#else
filepath = Application.dataPath +"/StreamingAssets/Local.csv";
#endif
string oriPath = System.IO.Path.Combine(Application.streamingAssetsPath, "Local.csv");


//判定平台
if(Application.platform == RuntimePlatform.IPhonePlayer)
{
using (WWW reader = new WWW(filepath))
{
yield return reader;
LocalFileVersion = reader.text;
}
}
else if(Application.platform == RuntimePlatform.Android)
{
using (WWW reader = new WWW(filepath))
{
//讀出
yield return reader;
LocalFileVersion = reader.text;

//寫入
string WritePath = Application.persistentDataPath + "/Local";
System.IO.File.WriteAllBytes(WritePath, reader.bytes);
DBPath = WritePath;
}
}
else
{
// pc
LocalFileVersion = System.IO.File.ReadAllText(oriPath);
}
DownloadOK = true;
}

void OnGUI()
{
if(DownloadOK)
{
GUI.Label (new Rect(Screen.width -700, Screen.height - 250,500,20),"伺服器版本號為:"+GetDataByRowAndCol(0,1,VersionArray_Server));
GUI.Label (new Rect(Screen.width -700, Screen.height - 200,500,20),"本機端版本號為:"+WeaponTableVersion);
GUI.Label (new Rect(Screen.width -700, Screen.height - 150,500,20),"本機端CSV檔版本號為:"+LocalFileVersion);
GUI.Label (new Rect(Screen.width -700, Screen.height - 100,500,20),"本機端檔案路徑為:"+DBPath);
GUI.Label (new Rect(Screen.width -800, Screen.height - 50,500,20),"filepath路俓為:"+filepath);
}
}


//下载Scene,加载场景  
IEnumerator DownloadScene()
{
//下载Scene,加载场景
using (WWW scene = WWW.LoadFromCacheOrDownload(SceneURL,1)) //下載地址,版本號
//using (WWW scene = new WWW(SceneURL))
{
yield return scene;
AssetBundle bundleS = scene.assetBundle;

if(bundleS == null)
{
Debug.LogError("no Scene");
}

Application.LoadLevel("scene1");
}
}


//取得指定資料
string GetDataByRowAndCol(int nRow, int nCol, string[][] CSVArray)  
{  
if (CSVArray.Length <= 0 || nRow >= CSVArray.Length)  
return "";  
if (nCol >= CSVArray[0].Length)  
return "";  

return CSVArray[nRow][nCol];  
}

}


Unity AssetBundle 建立 C#

1.於Unity Assets下建立一資料夾Script。
2.建立Script檔,檔名自取範例為ExportASSETbundle.cs,將此檔置於Script資料夾中。

內容程式碼如下:

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


class ExportAssetBundle
{

[MenuItem("Assetbundle/Build APP AssetBundle")]
    static void ExportResource()
    {
        //打開保存面板,取得使用者選取的路俓
        string path = EditorUtility.SaveFilePanel("Save Resource", "", "New Resource", "assetbundle");

        if (path.Length != 0)
        {
            // 選擇要保存的對象 
            Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
            //打包
#if UNITY_ANDROID
BuildPipeline.BuildAssetBundle(Selection.activeObject, selection, path, BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets, BuildTarget.Android);
#elif UNITY_IPHONE
BuildPipeline.BuildAssetBundle(Selection.activeObject, selection, path, BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets, BuildTarget.iPhone);
Debug.Log("iphone手機平台AssetBundle格式");
#elif UNITY_WP8
BuildPipeline.BuildAssetBundle(Selection.activeObject, selection, path, BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets, BuildTarget.WP8Player);
Debug.Log("wp手機平台AssetBundle格式");
#else
BuildPipeline.BuildAssetBundle(Selection.activeObject, selection, path, BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets);
Debug.Log("非手機平台AssetBundle格式");
#endif          
        }
else
{
Debug.Log(path + "AssetBundle建立失敗");
}
    }


[MenuItem("Assetbundle/Build Scene")]
    static void ExportScene()
    {
// 打開保存面板,取得使用者選取的路俓
        string path = EditorUtility.SaveFilePanel("Save Resource", "", "New Resource", "unity3d");

        if (path.Length != 0)
        {
// 選擇要保存的對象 
            //Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
            string[] scenes = { "Assets/scene1.unity" };
            //打包  
            BuildPipeline.BuildPlayer(scenes, path, BuildTarget.StandaloneWindows, BuildOptions.BuildAdditionalStreamedScenes);
        }
    }
}

3.執行後,Unity面版會多一項Assetbundle選項,裡面有二項功能,一個是打包資源/文件類檔的Build APP AssetBundle,一項是打包Scence的Build Scene。

4.選取要打包目標,可複選(Sence不可),選取面版功能,設定打包位置及檔名,執行即完成。

5.使用請於File  > Build Setting.. 選擇對應平台,範例中有設三平台,(Android/iphone/winphone )再進行打包操作。

2014年2月12日 星期三

Unity 2D 動畫設定

這篇主要是拿2014.01.18 Unity 4.3 2D 實戰班範例,課程中的動畫部份寫成備忘,讓公司美術了解其運作方式。

1.幫Sprite加上動畫屬性。
 1.1使用上課範例Course Samples > Animator > Move with Animation
 1.2打開專案後,將Assets中準備好的圖組walk_sheet,型態是Sprite拉到畫面中,會自動產生實體物件walk_sheet_0(名稱可自改),可拉圖組也可拉單圖,拉圖組也僅取其中一張顯示而已。
    1.3也可以自行產生Sprite,再將指定顯示用圖拖曳到Sprite中。



 1.3於左上Hierarchy區塊(藍框範圍),選取剛產生物件,右方Inspector區塊(綠框範圍)會出現該物件的屬性(右方紅框內的項目)。


 1.4按下Add Component按鈕(紅框),下方會出現列表,接著在藍框處輸入查詢Animator,下方經過過濾後,出現綠框的屬性Animator,點擊選取產生。



1.5於Assets新增一個資料夾Folder自行命名,範例資料夾命名test2


1.6於資料來中,按滑鼠右鍵Create > Animator Controller 產生物件自行命名,範例命名  名Controll_a (此物件功能會在後面步驟再說明)。
 

1.7將上一步所產生的Animator Controller,拖曳至7.2所產生Animator的Controller中,跟指定    Sprite(場中的人物)建立連結。



1.8選取畫面中或Sprite使用Windows > Animation 。



1.9產生Animation介面,按下Add Curve創立新的Animation物件,可以看成是動作A,並命名,範例命名run



1.10將Assets中的圖組點開,選取全部動作,拖曳至Animation中.即可透過執行看結果。


2.調整動畫角本
   2.1左方橘框點擊後,可讓右方各動畫節點下方,顯示對應的圖。
   2.2紅框部份,各菱形節點為插入的圖片,動畫會依此順序撥放。
   2.3藍框部份為時間軸,動畫執行到該點,會切換成對應該時間軸的圖。
   2.4藍框左方的Sampl欄位顯示的60,則表示時間軸一秒會分成60份,可變更設定。
   2.5Sample上方欄位顯示42,表示目前是紅線停在42/60秒的節點處。
   2.6Animation的紅點跟鍵頭,就是執行跟停止動畫的預覽。



3.動畫位移效果

  3.1按下Add Curve會顯示如圖畫面,選擇Transform(位移)之下的Positicn(點),點擊右方的+號。


    3.2會產生紅框的Position時間軸,左方鍵頭可點擊展開,如圖右紅框,只有起始二個節點,選取二節點看左方的Position.X/Y/Z值皆為0,表示從開始執行到最後,動畫都固在那個位置。



    3.3選取想要變更位置的時間軸,點擊二下,會產生如圖藍框處,產生新的節點,點選此節             點。


    3.4將Scene畫面(藍框)的人物,移動位置(類似紅框動作),會發現3.3圖該節點的Position.x以及 y會依移動的位置而變化,代表當動畫執行時,圖片會在設定的時間內(範例是0~0.1秒),位置從起始點,移動到設定點,之後在移動到起始點。


   
4.動畫細部調整方法。
 4.1選取下方的Cuves,右方會切換成如圖的介面。 
 4.2介面顯示的,其實跟步驟同3是一樣的操作,只是用曲線的方式呈現。
    4.3選擇上方增加節點的按鈕(在此生成節點,在步驟3介面也會同步產生)。



 4.4將產生的紅色垂直線,移動到想要增加節點的位置,要在橘色方塊區域做移動操作。
 4.5決定後按下紅框按鈕,就會產生新的節點。
    4.6可選取節點,然後拖曳進行修改。



5.Animator功能細項說明

   5.1Animator類似一個群組,可管理各組動畫間的連結,下圖是以步驟1.5所建立test2資料夾,以及步驟1.5中所建立的的Animator名為Controll_a
   5.2通常一個Animator代表一個角色,裡面的Animation則是該角色的各種動作。



   5.3點擊Controll_a進入Animator的設定畫面,綠色方塊Any State是一定存在的,代表任何狀態橘色方塊代表Defualt(預設)狀態,灰色方塊代表尚未執行的狀態。
    


 5.4在此範圍內按滑鼠右鍵,Create State > Empty 可新增新的狀態。


   5.5選取狀態方塊,右方會出現該狀態屬性,將設定好的Animation拖曳至欄位即完成狀態與動畫的連結。


   5.6當各狀態都有賦予對應的Animation選取步驟1.1所建立的sprite(選取實體sprite,才能讓打開的Animation介面進行之後的操作),操作步驟1.8開啟Animation 的控制介面,如圖示就可以選取各個狀態,針對要表現的動作來設計。




    5.6在方塊上按滑鼠右鍵,可新增連結,選取後會出現鍵頭跟其他狀態建立連結。



 5.7關係的建立,通常用於動作遊戲的角色設定,如圖所示各個動作狀態的切換關係。




 5.8左下方Parameters處可定義屬性,範例是設一個int型態,名為speed的屬性。
 5.9選取連接的線段,選取到會顯示藍色,右方會出現屬性表。
 5.10其中Conditions部份可針對先前設定的speed做條件判斷,條件成立才切換下個動作狀  
           態。





2014年2月9日 星期日

Windows Azure Web網站 + ASP.NET 連結發佈

這是最近在研究手機APP遊戲,使用微軟提供的後台服務Windows Azure Web Server走http傳輸的模式的備忘記錄。

1.首先在  Windows Azrue 建立一網站,及MsSQL資料庫,並在網站設定處建立彼此連結,此部份在此不做細部說明。

2.打開Visual Studio2013 ,開啟新專案,檔案(F) > 專案(P) > ASP.NET  Web應用程式。

 2.1此處選擇.NET Framework4.5.1,較舊的版本在之後要設定Migrations時會找不到套件。
 2.2專案型態選擇Visual C# > Web   出現在右邊的選項ASP.NET Web應用程式。
 2.3下面名稱(N):的欄位,請輸入專案的名稱。


2.4選擇後按下確認,新增專案。



3.建立Models,於方案總管的Models資料夾按滑鼠右鍵,選擇加入(D) > 類別(C)...


    3.1輸入類別名稱,按下新增(A)產生。


 3.2於新產生的類別中,設定Model的內容,範例是建立五個資料,然後建置(B)執行建置方案,如果命名為id,系統有機會預設成主鍵,此範例指定PersonID為主鍵,上面加[Key]。

   3.3記得要加第6行,跟第14行,不然建立Controller時會產生如圖的錯誤。


4.建立Controller並跟Mode連結。
 4.1於方案總管的Controllers資料夾按滑鼠右鍵,加入(D) > 控制器...


    4.2選擇 具有動作、使用Entity Framework API2 控制器 這項按新增。



  4.3.設定控制器,控制器名稱號(C):,命名建議同Model後面加Controller;模型類別(E):,選取右方展開功能後,選擇指定的Model。
  4.4使用非同步控制器動作,這項可視需求來選擇。


  4.5資料內容類別(C):,選擇右下方的新的資料內容...,會產生一視窗,建議中間反白部份改成同Model的名稱,按加入回上一視窗,再按加入產生Contrller(控制器)。



5.Enable Migrations 此部份官方範例未說明,自測時少這驟,會導致網站發佈,連結失敗,必且須在.NET Framework4.5版本或之上才有效。

  5.1執行   工具(T) > 程式庫套件管理員(N) > 套件管理器主控台(O)  。



 5.2下方會出現可輸入的畫面,輸入enable-migrations ,執行。
    5.3再輸入 add-migrations ,執行。



    5.3在使用MVC4專案時,執行5.2後,可能會發生錯誤,產生一些紅字說明,此時則需要再輸入Enable-Migrations -ContextTypeName WebGameServer.Model.UesersContext,執行,以及Enable-Migrations -ContextTypeName WebGameServer.Model.PlayerContext。

   範例專案名:WebGameServer
   範例Model名: Player

6.至Azure 的網站取得連結檔,及DB取得連結字串
    6.1取得連結字串,進入Azrue,選擇DB,此處是用預設的跟網站有設好連結的MutsuDB,點擊進入。



 6.2選擇右下方的,顯示連接字串進入,即出現中間的畫面,選擇ADO.NET的內容,將紅框內容字串Copy至文字檔中,即完成取得連接字串,Password={在此輸入您的密碼}這部份要改成存取該資料庫的密碼。

    6.3再選擇網站,範例部份,網站是使用Mutsu,點擊右方項目進入。



 6.4再選擇右下方,下載發行設定檔,然後指定該檔案的存檔路俓,即完成取得連結檔。



7發佈至Azure。
 7.1回到Visual Studio2013 專案,在方案總管下,選取專案,按滑鼠右鍵,選擇發行(B)...


7.2進入發行Web畫面,選擇匯入(I)...,進入匯入發行設定。



7.3選擇右下方瀏覽(B)...,選擇步驟6.4所儲存的發行設定檔,然後按OK,按OK儲檔。


7.4接著進入連線設定,只要上一步驟正常,資料會自行產生,可用驗證連線(V),測試連線是否正常,按下一個(X)>,進入下個設定。


7.5進入設定,將檔案發行選項點開,移除目的地的其他檔案(V)打勾。



7.6再設定資料庫的連結,裡面會顯示專案中有設定的Model(藍框),在下方將步驟6.2取得的連接字串填入,按下一步,可用預覽看有那些檔案上傳,或直接執行發行(P)


7.7發行完後,瀏覽器開打開一新視窗,即成功。

8.這部份補充,使用非同步,跟資料庫做查/增/刪/修操作,加在需操作的Controller中。


PlayerAsyController db = new PlayerAsyController();

查詢
Player _player = await db.Player.FindAsync(i);   //i為key值,第i筆

增加
db.People.Add(Player); //創新
Player.FirstName = "aa";//給值
Player.LastName = "bb";//給值
await db.SaveChangesAsync(); //記錄

刪除
db.Player.Remove(Player);
await db.SaveChangesAsync(); //記錄

修改
await db.Database.ExecuteSqlCommandAsync("UPDATE People SET FirstName = 'UPDATE" + i + "' WHERE PersonID = " + i);
await db.SaveChangesAsync(); //記錄

2014年1月21日 星期二

將Unity3D專案發佈在Windows Phone上



作業環境限制


  1. Windows8  ,請用64-bit pro版本,32-bit版本會無法裝之後的WindowsPhoneSDK8.0。
  2. VisualStudio2012,更高版本也可以。
  3. 需安裝WindwosPhoneSDK8.0。
  4. WindwosPhose手機要解鎖,付費或取得資格,於Windows Phone Developer Registration項目偵測及開啟手機連結(圖1)

  
圖1


使用步驟



  1. 打開VisualStudio,建立專案,種類選擇WindwosPhone應用程式,建立好後關閉(圖2)。 
  2. 打開Unity,選擇左上方功能列的File > Build Settings(圖3)
  3. Platform選擇Windows Phone8,按下Switch Platform。
  4. Scenes In Build 按下Add Current增加所需的Scenes。
  5. Development Build項目打勾。
  6. 按下左下的Build And Run,路俓選擇步驟1產的專案資料夾,即可編完後輸出至手機(圖4)

圖2 
 
圖3

圖4