Tag Archives: plugin

Playmaker_DuelingBlades

PlayMaker 初試

PlayMaker係一個Unity Plugin for Finite State Machine (FSM),
可以drag & drop咁edit個state diagram。
如果你試過用code寫有關state ge嘢你就知道佢有幾好啦XD
其實買咗佢好耐一直冇時間試,
而家終於可以試返夠本:P

 Asset Store – Playmaker
Playmaker_DuelingBlades
DreamfallThumb

基本功能

  • 建造一個State
  • 喺個state度加transition(每一個transition對應一個event),定義個transition會去邊個state(drag個transition就會拉到條箭咀出黎)
  • 喺個state度加action,一到呢個state佢就會做曬成個state嘅action。本身有好多action可以㨂,或者自己做custom action
  • Action可以控制send邊個event同幾時send,如果個state有相應嘅transition,個FSM就會switch去個transition所指嘅state
  • State可以接收global transition,無論佢本身喺邊個state一收到global event都會跳去相應嘅state
  • 有variable可以用。當喺action填資料嗰陣可以直接填上值或者variable。可以令variable顯示喺inspector度
  • 一個FSM只有一個current state(呢個絕對係feature唔係limitation!)。當個editor play緊個FSM dialog會highlight current state/行過乜嘢state。可以喺個state度set break point做debug,亦可以即時睇到每個variable嘅值(睇到值呢個feature應該歸功於unity XD)

用途

  • Organic AI - 好多時生物嘅AI都係一個FSM:patrol,follow,fire,die⋯
  • Trigger - 例如一度門,有”打開”同”關閉”兩個state
  • Stated Control - 如果做一尐複雜嘅control,例如touch dragging gesture,可能會需要考慮”touch down”之前同之後,”touch up”之前同之後做唔同嘢,有2至4個state
  • Stated UI – 例如Button會有Enable/Disable兩個state,或者可能會有唔同state show唔同function

如果用code做FSM,
好可能就係一個function implement一個state,
未必做到尐同state有關嘅功能,
例如返到上一個state,檢查執行緊乜嘢state,
離開state個陣做某尐action,從外部接收event等等。
更改transition可能要search返個function喺邊,
然後夾硬改個function call@@
改code個陣又要好記得個workflow係點,
或者要自己做好個doc記低佢。

PlayMaker嘅好處就係你做個個machine本身就係一個diagram,
做FSM有關嘅改動都好方便。
佢亦要求每一個state/event都要命名,
其他人一睇唔知detail都知道個大概。
就算係自己改返自己嘢,
見到個diagram都會remind返好多嘢。

缺點

1. 每一個action都係一個script
雖然可以做custom action但係比較麻煩,
就算係做加減乘除都要用action做,
所以如果做大量procedural嘢就會好煩,
一個一個action係咁加會耐過打幾行code好多。
不過可以用send event嘅方法call其他MonoBehavior,
PlayMaker FSM就做返FSM相關嘢然後call 其他script procedure。
如果佢有個好方便嘅UI link去相關嘅script就正囉~

2. 重用性低
例如有一個state有好多action,
想做另一個有同樣action嘅state只可以copy and paste⋯
(或者save template再paste返出黎但係都係冇分別 lol)
除非你做咗個custom action出黎比唔同嘅state用。

3. 唔支援array
本身係冇任何同array有關嘅action/variable type,
更加唔洗講looping。
就算做咗同array有關嘅custom action,
looping 好可能都係由兩個state互相指住黎做。
暫時未諗到有咩好方法可以處理,
大不了所有array有關嘅嘢交返曬比script做

4. Edit mode有bug
呢個可以話係最大嘅缺點~_~
有時undo嘢會有bug(undo的確係唔易做嘅事⋯),
好多時undo完要reload個editor先見到佢係undo咗,
有時改完action sequence之後field value會錯@@
總之做完嘢save咗先,有咩事就reload個scene :P
不過當你做好個diagram去run就未見到有bug,
都係edit個陣尐細bug無傷大雅

其實頭兩個缺點都可以用custom action解決,
而且做custom action都幾好玩㗎XD
大家有興趣可以試下。

初試後感

第一次試我故意將所有都用PlayMaker做,
成個UI Logic同Control都係,
結果當然好悲劇XD

Screen Shot 2014-06-08 at 10.43.14 am

因為每一個button都起碼要做一個state,
咁十幾個button就有十幾個state,
再加幾個state去check邊粒button比人禁,
就變咗一個大到唔想睇嘅diagram XD。

亦由於state嘅重用性低,
加一個case又起碼要加一個event一個transition同一個stage,
為咗方便又要加一個variable(下面再詳細講),
所以如果想加一個同之前類似嘅button都要搞一輪zzz

當中有個FSM設計咗幾個global event,
諗住好似function call咁,call一個event做一樣嘢,
但係每次call都要用幾個action去set幾個parameter,
再用一個action去call,
可能仲要寫多個stage去等個FSM return

結論當然係應該將同FSM冇乜關係嘅嘢抽返比script去做XD
同埋個diagram唔應該做曬個UI hierarchy,
簡單尐講就係唔好一個button一個state,
唔好搞到個UI越多個diagram越大。

啱啱上手個陣會有少少唔知尐state放邊度嘅感覺,
(我嘅意思係放喺diagram邊度,純綷係用家視覺問題XD)
不過用咗一陣之後就OK,
一排stage最好就打直排唔好打橫排~

以下係尐值得注意嘅嘢:

  • Annoying Active Browser
    我唔知Windows版係咪都係咁,我用Mac版開咗PlayMaker Editor之後佢個自動開Action Browser,然後用Cmd+Tab去另一個panel個陣佢會loop住select PlayMaker Editor <-> Action Browser。解決方法就係將Action Browser merge去PlayMaker Editor,成為同一個panel
  • Event “Forwarding”
    “Get Mouse Button Down”  Action係會等Mouse Button Down然後sent一個event 。如果一個state用”Get Mouse Button Down” Action去下一個state,而下一個又有”Get Mouse Button Down”,咁下一個state又會因為咁去再下一個state。因為佢用咗Unity嘅”Input.GetMouseButtonUp”,同一個message loop都會收到同一個result。
    仲有呢個唔知係唔係bug:如果喺state A收到event 1會去state B,然後state B收到event 1會去另一個state,就算個FSM只係收到一個event 1都會連續跳state,更可能因為咁出現dead loop。所以某尐位我會delay 0.1秒先send event。呢個問題有待查證。
  • Variable for GameObject value
    就算你想reference嘅GameObject係喺個scene度,我建議你開個variable裝住佢而唔係直接set落個action度,一來要改動嘅時候只要改個variable就改曬全部action,二來可以display in inspector令你見到曬呢個FSM用緊邊尐GameObject
  • FSM callback
    如果FSM A等FSM B做完嘢先去下一個state,但係又唔想FSM B直接reference FSM A(Modular Programming!!),可以喺FSM B開一個GameObject variable,係FSM B做嘢之前set個variable做FSM A,再用”Send Event By Name” action 通知個variable ge FSM。不過咁做令呢個callback只可以有一個receiver(PlayMaker冇支援array⋯)。或者call script再call其他FSM。
  • Save FSM as a Prefab
    如果你唔將個FSM GameObject save做Prefab,然後你個project上咗version control同人地夾黎做,咁個scene file其他嘢conflict咗就會連累埋個FSM。但係save做prefab之後prefab嘅variable對scene GameObject嘅linkage會冇曬,然後又好可能會出尐不必要嘅error(尤其是”Call Method” action)
    解決方法係所有action都唔好直接reference GameObject,而係用variable
    至於”Call Method”我就直接comment了CallMethod.cs第102行(errorString += “Behaviour is invalid!\n”;)
    記得唔好改prefab FSM然後revert to prefab,如果唔係連scene嘅FSM variable都冇曬reference。應該係改scene FSM然後apply to prefab

改良提案

  • Script linkage
    如果可以加粒掣係同script有關嘅action度,一click就彈去個句function就好囉,不過unity plugin黎講應該做唔到。
    或者做一個script execution action然後可以加幾句script。
    Variable嘅class應該要implement operator,唔洗下下都會dot佢個value出黎
    現在:variable.Value = value;
    建議:variable = value;
  • Every frame
    好多原有action都有”Every Frame”呢個flag,用法係當個FSM stay喺嗰個state個陣,個action每個frame都會做嘢,唔洗做多個transition過一個frame loop比自己咁煩。但係唔知點解唔係個個action都有。其實應該要改到個super class本身就有
  • Comment Block
    我見其他graphical programming都會做一個冇用ge rectangle放喺一堆note下面說明個堆係乜,可以寫埋字做說明

以我所見PlayMaker都算係幾好玩幾幫到手嘅嘢,
有賴Unity Asset Store尐update都做得幾好,
雖然要比錢買但係值得一試~

Android is plugin unfriendly

As I worked for mobile app almost 2 years, I conclude that Android is not a good platform for plugin development, comparing to iOS platform. I always feel painful to integrate any plugin for Android apps. Here are some reasons why.

Manifest.xml vs info.plist

Manifest file just does too much then a configuration file. Every activity/service and permission requirement in Android app have to register itself in it, which causes many plugins to modify this file. By the design pattern of Android SDK, many plugins cannot avoid to do so.

More than one plugins modifying the same file turns out the plugin users to do that manually, which increase the chance of careless mistake and the effort to manage them, or the users will do a template for several plugins, but it is still complicated if there are too many.

In my opinion, I don’t see any point for such registration on Manifest XML. To protect end-user? They won’t care about it. To protect app developer from third-party developer? No it can protect nothing. It would be perfect if Manifest XML does exactly what info.plist does. At least it should be application oriented, but not module oriented. There should be another automatic system to detect and conclude the combined activity/service and permission requirement.

Message in Activity

Such as onActivityResult, must be listened by an Activity, and there is only one active activity at the same time normally. It also causes different plugins trying to modify the only activity class.

Android View Parameter

All parameters of an Android View, such as position, width and height and etc, are stored in a ViewParam, which is an instance of one of the ViewParam classes, depending on the parent view of it. which causes a dependency of plugin component to external component.

Many plugins developer (mostly in iOS) implement a help method to create a view for users, so that the view could be added to the custom view made by the plugin users and it’s done. However, the view parameter cannot be pre-made as the plugin developer don’t know what is the parent view they are using. The plugin users have to hard code the parameters themselves, and have to update that if the view is updated.

May be it’s not fair to compare an old designed Cocoa Framework with a really new Java framework, and Google is so busy about catching up the visual design against iOS. For now a plugin management for Android should be a good idea to be invented.