code style

9/30/2016

How to load dynamic library with Unity plugin on Mac OSX

When develop Unity plugin on Mac, you might want to load third party dynamic library. But it usually occurs "fail to load" situation. That is because loading path is different between development and production environment.

For instance, when you develop in Edit mode, the loading path will be
 ./Assets/Plugins/osxplugin.bundle/Contents/Resources/thirdparty.dylib

But when you build a release version, the loading path will be
./Contents/Plugins/osxplugin.bundle/Contents/Resources/thirdparty.dylib

Mac OSX provide a command line tool to modify that.

$ install_name_tool -id @loader_path/thirdparty.dylib thirdparty.dylib

You could use otool to check dylib status.

eg.
$ otool -L libcurl.dylib 
libcurl.dylib:
 @loader_path/libcurl.dylib (compatibility version 0.0.0, current version 0.0.0)
 /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1226.10.1)
 /usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.5)

Now, you can develop and build a unity app without dylib loading issue.

9/07/2016

How to create an Unity AAR Plugin for Android

Environment: Android Studio 2.1.3

1. new Module -> Android Library

2. new -> Java Class for your Java code.

3. new -> Folder -> JNI folder

4. new -> C++ Class for your C++ code

5. new -> Folder -> Assets folder for your plugin asset files.

6. edit build.gradle for your library

apply plugin: 'com.android.library'

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.1"

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"

        ndk {
            moduleName "unity_plugin"

            // STL library
            stl "gnustl_static"

            // target platforms
            abiFilters "armeabi-v7a", "x86"

            // link other libraries for your C++ code
            String path = file(projectDir).absolutePath + "/src/main/jniLibs/\$(TARGET_ARCH_ABI)/"
            ldLibs "log", "z", "m", "android", path+"libCustom.so"
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_6
        targetCompatibility JavaVersion.VERSION_1_6
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:24.2.0'

    // reference for Unity Java classes,
    // see https://docs.unity3d.com/Manual/PluginsForAndroid.html
    // "Extending the UnityPlayerActivity Java Code" part
    provided files('classes.jar') 
}

7. add permissions in AndroidManifest.xml,
 such as < uses-permission android:name="android.permission.INTERNET" >

8. double click on YourApplication.:YourLibrary.Tasks.build.assembleRelease in Gradle projects panel to generate the release version of AAR.

9. copy AAR to Unity Assets/Plugins/Android folder.

Unity Plugin Tips

Unity WebCamTexture Fast Copy

讀取WebCamTexture內容是用Color32 type,但是Texture2D更新內容需要byte type。
使用StructLayout宣告可以將不同type資料共用同一個記憶體位址。
(Win/Mac測試ok)

[StructLayout(LayoutKind.Explicit)]
public struct Color32Bytes{
  [FieldOffset(0)]
  public byte[] byteArray;

  [FieldOffset(0)]
  public Color32[] colors;
}

colorData = new Color32Bytes();
colorData.colors = new Color32[webCamTexture.width * webCamTexture.height]; 

webCamTexture.GetPixels32(colorData.colors);
displayTexture.LoadRawTextureData(colorData.byteArray);
displayTexture.Apply();



Unity Native Plugin Fast C# Callback

使用MonoPInvokeCallback宣告,可以讓C++ Plugin呼叫C#函式。
(Android測試ok)

[C#]
// declare callback
delegate void RenderCallback(int request);

[MonoPInvokeCallback(typeof(RenderCallback))]  
static void RenderFunc(int request) {
  // do something
}

[DllImport("unity_plugin")]  
static extern void RegisterCallbacks(RenderCallback cb);


[C++]
typedef void (*RenderCB)(int event);
static RenderCB sfpRender = nullptr;
extern "C" void RegisterCallbacks(RenderCB cb) {
    sfpRender = cb;
}

9/03/2015

How to induce low memory warnings on iOS device?

It's difficult to test game function in low memory scenario.

Someone suggests using iOS simulator to do the test.

Someone says write codes to allocate large chunk of memory to induce that, or call private method
[[UIApplication sharedApplication] performSelector:@selector(_performMemoryWarning)];

Rather than writing code in the project, you could use Xcode debugger to execute the private function.

Edit the action of breakpoint and enter
expr (void)[[UIApplication sharedApplication] performSelector:@selector(_performMemoryWarning)];
Voilà, mission completed.

By the way, my indie game "Nimble Jump" Android version is in beta testing now.
Please try it and give some feedback. Thank you!
play.google.com/apps/testing/com.jbyu.ninja.





1/12/2015

也來寫卡牌遊戲好了(二)

沒想到我也學富堅一樣拖稿拖超久!


咳! 好Der~ 今天我們來繼續談談怎麼寫卡牌遊戲。

什麼?! 你說卡牌遊戲已經過時了?!?! 現在都是什麼刀什麼塔的!

咳! 好Der~ 今天我們就來談談中國手遊什麼的如何砸錢買廣告。(喂)


呃....那今天要說什麼? (翻翻筆記、抓抓頭)

我覺得是這樣啦,我相信台北市民的智慧,應該是不會在乎要講什麼,這一路走來,不管面對再多的劣勢,我們始終堅持打一場正面的遊戲開發。(喂!!!!)



咳! 好Der~ 今天我們來討論做遊戲的時候要用什麼工具來管理數據資料。 對!就是SQLite、SQLite、SQLite,很重要,所以要講三次。


SQLite就是專門用於獨立單機架構的資料庫系統。輕便短小、沒有負擔、讓人幾乎忘了它的存在。你還在用csv檔案來儲存角色數值嗎?你還在為了資料排序而寫了一堆sorting algorithm嗎?


用了SQLite,馬上就能解決您過去的困擾 (然後多了更多要如何好好利用SQLite的煩惱)(登愣)

首先,效率問題!SQLite是將資料儲存在檔案系統,所以File IO可能會是個問題。幸好,SQLite有提供memory function,可以將SQLite搬到RAM上面做操作,因為現在記憶體夠大,小小的遊戲數值應該是佔不了多少空間。可以參考這邊的作法 link

通常遊戲中的動態數據,例如玩家資料、關卡進度、道具數量,是從遊戲server傳回client儲存。而靜態數據,例如卡片設定、關卡設定、道具設定...等等,往往變動幅度不大,如果每次玩家進行遊戲都得重複下載這些數據,就有點浪費大家的時間與頻寬。比較偷懶的作法就是在更新數據的時候讓server自動產生靜態數據db,然後再通知client下載這個db。
這邊提供一個mysql轉換成sqlite的script

因為靜態數據db會存在client,相信很多人不想讓別人看到你db裡面放了什麼鬼東西,所以我們就得加密db。免費的SQLite雖然有提供加密的界面,但是並沒有實作;官方的實作版本得花錢購買。幸好,wxSQLite3有提供加密的功能,省去我們自己DIY的功夫。

SQLite CLI的加密方式如下
$~/sqlite3secure source.sqlite
.backup /tmp/temp.txt
attach database "encrypted.sqlite" as x key "password";
.restore x /tmp/temp.txt
.quit

好了,到這邊SQLite的基礎建設差不多都搞定了。接下來就是讓開發人員開開心心地在client裡面下SQL指令去查詢遊戲數據囉~ 可喜可賀!
(真的有這麼輕鬆寫意嗎?  噓~~~ 不要傷了皇「城之內」的和氣)

至於用ORM方便物件導向操作什麼的,我只能說「真男人都是直接下SQL指令抓raw data來用Der」
(其實是我沒空研究啦)


時間也差不多了, 咱們下回再見 (天線寶寶說掰掰)

8/09/2014

也來寫卡牌遊戲好了(一)

這年頭不寫個卡牌遊戲好像跟不上時代。

遙想去年敝人也是在台北某間大樓的52樓裡面的某間公司在進行一個卡牌遊戲改版的動作!

只可惜遊戲做完了,公司也收起來了。C'est la vie~


****************************阿公講古分隔線********************************

今天不說別的,就來談談卡牌遊戲的貼圖怎麼優化最佳化!

還記得我寫過TexturePacker的文章嗎?

所謂的Texture Atlas就是把零散的小貼圖集合成一張大貼圖,不僅可以加速貼圖載入的速度,也可以避免OpenGL的texture swap cost。

但是!但是~卡牌角色衣服總是要多露有多露、胸部要多大有多大~
胸部都那麼大了,你卡片解析度不加大也說不過去吧? (都是視網膜螢幕害的)

我們假設卡牌解析度是512x640,以iOS最大貼圖解析度2048x2048來看,最多可以塞個12張。PNG格式大約是4-5MB,PVR格式是2MB,PVR CCZ格式可以壓到1.5MB左右。

看起來還不錯是吧?你忘了卡牌遊戲動輒數百張的卡片數量,光是計算PVR的時間就可以看部藍光DVD了!更別說哪天某張卡片圖樣要更新,又得重算一次。

再來如果說遊戲要同時呈現數張卡片,好死不死,每張卡片都散落在不同的Texture Atlas,那麼貼圖記憶體的使用量也會倍增。

嗯嗯~所以Texture Atlas雖說檔案大小是很優化最佳化,但是在這種使用情境下,就....不那麼理想。

糾竟遊戲工程師該怎麼辦呢?讓我們繼續看下去~

幸好有神人發明了Vector Quantization Algorithms。來~跟我說一遍~
V e c t o r  Q u a n t i z a t i on  A l g o r i t h m s (英國腔)

中文翻譯是向量量化演算法,雖然我看得懂中文,恩~也看得懂英文。但是我看不懂這是什麼東西 (咳)

好!不懂原理沒關係,我們懂得怎麼用就好!

http://pngquant.org/ 很貼心的蒐集了各作業系統的貼圖轉換工具。
使用V e c t o r  Q u a n t i z a t i on  A l g o r i t h m s (英國腔)可以幫我們把PNG減肥最多7成以上,而且還支援透明度,我都要痛哭流涕了~

逆看看,偶當場就縮了四分之一!

當然天下沒有白吃的午餐,我們還是得犧牲一些圖像品質來得到這樣的壓縮比。其實它就是把全彩貼圖轉換256色貼圖,失真是一定的唷~

貼圖維持PNG格式的好處就是 iOS 跟 Android 都能夠無痛使用,不再為 PVR、ETC1 等格式煩惱了~呀比~

說了這麼多,你還不趕快去用用看 (丟筆)

2/04/2014

TinySWF - a simple SWF player

最近看到GREE一個開源專案LWF,提供遊戲開發者一套免費的FLASH framework。

剛好之前也寫過類似的專案,現在就共襄盛舉、野人獻曝一下。


https://github.com/jbyu/tinyswf

TinySWF


為了方便讓美術人員製作UI與過場動畫,最好是有一套健全的GUI編輯器讓大家使用,當然為了這個理由而花費龐大的資源與時間來開發一套編輯器,必定是勞民傷財(還很可能吃力不討好、惹人嫌)。所以TinySWF就是為了直接利用Adobe Flash這套編輯器而產生的!

Features
  • Bitmap
  • Motion Tween
  • Text
  • Shape
  • Button
  • MovieClip
  • Mask
  • Sound
  • SWF3 action model
    • play
    • stop
    • gotoAndPlay
    • nextFrame
    • fscommand


TinySWF可以直接解析SWF檔案,不需要轉檔。其繪圖核心目前提供了OpenGL與cocos2d-x的介面,當然大家也可以設計自己的繪圖核心。

TinySWF提供了三個抽象介面讓大家界接:
  • Renderer       繪圖核心
  • Speaker         音效核心
  • FontHandler   字型處理


在開發TinySWF之前,我其實使用過開山鼻祖 gameswf 這套,Scaleform 就是基於它改良而成的。然而SWF實在是個很龐大的架構,如果只是想利用其中幾個功能而已,花費大把時間移植到mobile平台上就顯得不太划算。於是乎,便開始著手寫一個小巧的flash player,開發宗旨就是力求精簡!

雖然TinySWF不比LWF支援unity, html5。不過TinySWF支持向量圖型、遮照,也算是方便的功能。如果想做些複雜的碰撞偵測的話,可以利用向量圖型做polygon test。

TinySWF算是我第一個比較有系統的開源專案,希望大家可以多多給予批評指教~



6/25/2013

SquareEnix 三國志亂舞 程式架構分析

三國志亂舞

SE社很貼心地在遊戲中放了版權宣告

cocos2d-iphone  BJ4

FBEncryptor  AES加密工具

stig-json-framework  json工具

ziparchive  iOS zip utility
 
css-refresh  CSS開發工具

cubiq-iscroll  javascript touch event tool

jQuery  BJ4

brian-c/phantom-limb  在PC上模擬touch event

sizzle  CSS selector engine
 
SWFObject  javascript flash player

所以整個遊戲應該是用cocos2d-iphone + html5建構出來的