PlayMaker是什么屿笼?
PlayMaker是Unity3D的一款 可視化 的 有限元狀態(tài)機(jī)(Finite-state machine刹泄,簡(jiǎn)稱(chēng)Fsm) 插件,用來(lái)進(jìn)行交互設(shè)計(jì)。
有限狀態(tài)機(jī)(英語(yǔ):Finite-state machine蚤假,縮寫(xiě):Fsm)又稱(chēng)有限狀態(tài)自動(dòng)機(jī),簡(jiǎn)稱(chēng)狀態(tài)機(jī)吧兔,是表示有限個(gè)狀態(tài)以及在這些狀態(tài)之間的轉(zhuǎn)移和動(dòng)作等行為的數(shù)學(xué)模型磷仰。
我個(gè)人對(duì)Fsm的理解是這樣的:
Fsm將對(duì)象的復(fù)雜行為特征歸納為有限個(gè)不同的“狀態(tài)”,然后在每個(gè)狀態(tài)中分別指定一系列“行為”讓處于該該狀態(tài)的對(duì)象來(lái)執(zhí)行境蔼,同時(shí)設(shè)置一些“條件”(在FSM中稱(chēng)做“事件”)灶平,當(dāng)這些條件被滿(mǎn)足時(shí)(按FSM的說(shuō)法就是事件被觸發(fā))伺通,對(duì)象的從當(dāng)前狀態(tài)變換為另一個(gè)狀態(tài),由此帶來(lái)其所執(zhí)行“行為”的的變化逢享。
很多人把PlayMaker等同于“可視化編程”罐监,官方在宣傳時(shí)也自我標(biāo)榜為“PlayMaker - Visual Scripting for Unity3D”。在我看來(lái)瞒爬,這么說(shuō)其實(shí)是不太恰當(dāng)?shù)摹?/p>
Unity3D中真正可以稱(chēng)作“可視化編程插件”應(yīng)該是 uScript Professional弓柱,而PlayMaker只能算是一個(gè)“可視化交互設(shè)計(jì)插件”,因?yàn)镻layMaker只允許使用FSM這一種“編程策略”侧但,而且Fsm這一策略的設(shè)計(jì)思路其實(shí)是有別于正常撰寫(xiě)程序腳本時(shí)所采用的設(shè)計(jì)思路的矢空。
準(zhǔn)確的說(shuō),PlayMaker提供了一套可視化的解決方案俊犯,讓用戶(hù)可以無(wú)需撰寫(xiě)腳本代碼妇多,就能運(yùn)用有限元狀態(tài)機(jī)的設(shè)計(jì)思路在Unity3D中設(shè)計(jì)并實(shí)現(xiàn)交互邏輯。
對(duì)于完全沒(méi)有編程基礎(chǔ)的用戶(hù)來(lái)說(shuō)燕侠,了解PlayMaker和編程的區(qū)別沒(méi)什么太大的意義者祖。但對(duì)于有一點(diǎn)點(diǎn)編程基礎(chǔ)(卻還沒(méi)有深厚到自己寫(xiě)狀態(tài)機(jī)的程度),但又想要用PlayMaker來(lái)做交互的人來(lái)說(shuō)绢彤,直接把以前寫(xiě)簡(jiǎn)單程序的思維習(xí)慣代入PlayMaker七问,是會(huì)吃苦頭的。
所以茫舶,我們學(xué)習(xí)PlayMaker械巡,最主要的是去學(xué)習(xí)一種交互設(shè)計(jì)的思維方法。掌握PlayMaker本身的特性和功能當(dāng)然很有必要饶氏,但最終的目的是建立一種思維習(xí)慣讥耗,這種思維方法和思維習(xí)慣,是可以帶到其他軟件工具中去的疹启,比如UE4的 Blueprints(藍(lán)圖系統(tǒng))古程,甚至真正的Programming。
PlayMaker究竟能做什么喊崖?
PlayMaker曾被認(rèn)為是能夠?qū)⒂螒蛑谱髡邚摹按a”的汪洋大海中拯救出來(lái)的“救世主”挣磨,這當(dāng)然是一個(gè)笑話(huà)。
雖然PlayMaker官方網(wǎng)站上列舉了很多使用PlayMaker制作的游戲產(chǎn)品荤懂。但實(shí)際上茁裙,如果你希望通過(guò)幾周的學(xué)習(xí),掌握了解PlayMaker本身用法之后就能夠制作一個(gè)功能完成的游戲產(chǎn)品节仿,那是極為不現(xiàn)實(shí)的晤锥。
PlayMaker可以讓用戶(hù)擺脫“寫(xiě)代碼”這項(xiàng)工作,但不代表可以讓用戶(hù)擺脫“程序設(shè)計(jì)”這項(xiàng)工作廊宪,而且由于PlayMaker完全基于狀態(tài)機(jī)這種“策略”矾瘾,實(shí)際上增加了“程序設(shè)計(jì)”的工作難度眉踱。掌握PlayMaker這件工具本身的使用方法只是第一步,更重要的是利用這件工具去鍛煉我們思維霜威,去解決實(shí)際問(wèn)題。
PlayMaker真正的用途并不是去替代那些程序員(游戲開(kāi)發(fā))的編程工作册烈,而是給非程序員提供一個(gè)快速制作玩法原型(prototype)的工具戈泼,讓他們能夠獨(dú)立把腦海中“想象”的玩法設(shè)計(jì)實(shí)現(xiàn)出來(lái),無(wú)需花費(fèi)好幾年的時(shí)間去專(zhuān)門(mén)學(xué)習(xí)編程赏僧,也無(wú)需去“跪求”程序員大大們的幫助大猛。
當(dāng)我們經(jīng)過(guò)努力的學(xué)習(xí),逐漸能夠使用PlayMaker實(shí)現(xiàn)一個(gè)相對(duì)完整的游戲交互邏輯的時(shí)候淀零,其實(shí)我們的“編程思維”就不知不覺(jué)中建立起來(lái)了挽绩。那些使用PlayMaker制作出完整游戲的開(kāi)發(fā)者,我相信大多數(shù)都是很優(yōu)秀的程序員,因?yàn)椴徽撌荂# Scripting還是PlayMaker FSM,其背后的本質(zhì)都是所謂的“計(jì)算機(jī)程序設(shè)計(jì)思維”德召。
所以账蓉,PlayMaker究竟能做什么?這個(gè)問(wèn)題其實(shí)挺不好回答的盖文。PlayMaker只是一個(gè)工具,有優(yōu)勢(shì),也有不足灶搜。我們能用這個(gè)工具做什么取決于我們自身,而不是這個(gè)工具工窍。
PlayMaker的基本概念:Fsm割卖、States、Events患雏、Transition鹏溯、Actions、Variables
Fsm(狀態(tài)機(jī))
舉個(gè)小例子
前面已經(jīng)講過(guò)了Fsm的基本定義纵苛,現(xiàn)在舉一個(gè)日常生活的例子剿涮。
我們一天中會(huì)做很多事情,但我們可以把這些事情歸納為幾個(gè)狀態(tài):睡覺(jué)攻人;吃飯取试;上課;打游戲等怀吻。如果把早上作為一天的開(kāi)始瞬浓,我們的生活邏輯是這樣的:
- 一開(kāi)始我們?cè)谒X(jué)(初始狀態(tài)),但設(shè)了個(gè)鬧鐘(觸發(fā)條件)蓬坡;到7點(diǎn)了猿棉,鬧鐘響起來(lái)(滿(mǎn)足觸發(fā)條件)磅叛,我們?nèi)コ燥垼顟B(tài)轉(zhuǎn)換);吃飯完成(滿(mǎn)足觸發(fā)條件)萨赁,我們?nèi)ド险n(狀態(tài)轉(zhuǎn)換)弊琴;下課鈴響(滿(mǎn)足觸發(fā)條件),我們又去吃飯(狀態(tài)轉(zhuǎn)換)杖爽;吃完(滿(mǎn)足觸發(fā)條件)看看時(shí)間(新?tīng)顟B(tài)哦)敲董,如果還早(滿(mǎn)足觸發(fā)條件1),就打打游戲(狀態(tài)轉(zhuǎn)換)慰安;如果時(shí)間不早了(滿(mǎn)足觸發(fā)條件2)腋寨,就趕緊去上課(狀態(tài)轉(zhuǎn)換);……
可以看到化焕,如果我沒(méi)有添加“看看時(shí)間”這樣一個(gè)新?tīng)顟B(tài)萄窜,只有吃飯睡覺(jué)上課打游戲的狀態(tài)機(jī)是多么無(wú)聊啊撒桨!當(dāng)然查刻,其實(shí)現(xiàn)在也挺無(wú)聊的,不過(guò)我們可以嘗試把“看看時(shí)間”這個(gè)狀態(tài)添加到整個(gè)生活邏輯的各個(gè)部分元莫,就會(huì)有意思很多赖阻。
在不同的狀態(tài)下我們會(huì)做不同的事情,睡覺(jué)狀態(tài)下會(huì)循環(huán)進(jìn)行“呼吸”操作踱蠢。吃飯狀態(tài)下會(huì)依次進(jìn)行“夾菜”火欧、“送入口中”、“咀嚼”茎截、“吞下”等操作苇侵。重要的是,不同狀態(tài)下的行為設(shè)計(jì)是彼此獨(dú)立的企锌,而且與交互邏輯的設(shè)計(jì)本身也是彼此獨(dú)立的榆浓。我們可以在進(jìn)行行為設(shè)計(jì)之前就完成完整的交互邏輯設(shè)計(jì),然后再慢慢添加從簡(jiǎn)單到復(fù)雜的各狀態(tài)行為撕攒。
創(chuàng)建Fsm
在PlayMaker中陡鹃,F(xiàn)sm是被作為component(組件)添加給GameObject的。因此抖坪,一個(gè)Fsm可以被看做是一個(gè)獨(dú)立的腳本程序萍鲸,用以實(shí)現(xiàn)一個(gè)獨(dú)立的功能。
從菜單PlayMaker
> PlayMaker Editor
中打開(kāi)PlayMaker編輯器擦俐。
選擇需要添加FSM的GameObject(這里我新創(chuàng)建了一個(gè)Cube)脊阴,打開(kāi)PlayMaker編輯器,在編輯器中按照提示點(diǎn)擊鼠標(biāo)右鍵,選擇Add FSM
嘿期,就為該Cube附加了全新的FSM類(lèi)型的組件(Component):
這時(shí)界面上已經(jīng)提示我們的Fsm是被添加在Cube物體上了:“Cube:FSM”(注意品擎,這里的“FSM”代表的是這個(gè)Fsm的名字,新建的Fsm的名字都叫做“FSM”备徐、“FSM 1”萄传、“FSM 2”,最好能夠修改一下蜜猾,以免混亂)盲再。
Inspector面板上我們可以看到這個(gè)Component:
沒(méi)有很多參數(shù),可以修改名稱(chēng)瓣铣,可以點(diǎn)擊Edit
打開(kāi)編輯器來(lái)進(jìn)行詳細(xì)設(shè)置,可以添加一些簡(jiǎn)單描述Description...
贷揽,還可以選擇一個(gè)Fsm模板以重復(fù)利用以前的工作成果棠笑。
PlayMaker的編輯器分兩欄,左邊叫Graph(圖表面板)禽绪,右邊是參數(shù)面板蓖救。參數(shù)面板有4部分組成:FSM、State印屁、Events循捺、Variables,分別用來(lái)對(duì)狀態(tài)機(jī)雄人、狀態(tài)从橘、事件、變量進(jìn)行設(shè)置础钠。
在FSM欄中其實(shí)沒(méi)有什么太多需要修改的恰力,名稱(chēng)要改一下,我通常會(huì)使用FSM_*
的方式來(lái)命名旗吁,然后單詞首字母大寫(xiě)踩萎,單詞間不留空格,比如FSM_Movement
很钓、FSM_HealthControl
這樣香府。
當(dāng)我們創(chuàng)建了一個(gè)新的Fsm時(shí),會(huì)自動(dòng)得到一個(gè)初始狀態(tài)State 1
码倦,這個(gè)State 1
上方還有一個(gè)START
的圖標(biāo)并有箭頭指向State 1
企孩。
START
這樣位于狀態(tài)上方的黑底方塊叫做“Global Transition”(全局轉(zhuǎn)換),而且START
這個(gè)事件本身還是個(gè)“系統(tǒng)事件”叹洲。關(guān)于事件和轉(zhuǎn)換的問(wèn)題等下再講柠硕,現(xiàn)在我們只需要知道這個(gè)圖示的意思是:當(dāng)一個(gè)叫做“START”的事情發(fā)生時(shí),這個(gè)Cube物體進(jìn)入“State 1”狀態(tài),由于“START”在Fsm組件被創(chuàng)建的那一刻就會(huì)發(fā)生蝗柔,也就是這個(gè)Cube物體被創(chuàng)建的時(shí)候就會(huì)發(fā)生闻葵,所以當(dāng)場(chǎng)景被載入時(shí),游戲物體Cube就已經(jīng)處于“State 1”狀態(tài)了癣丧。
State(狀態(tài))
在空白處點(diǎn)擊鼠標(biāo)右鍵槽畔,選擇Add State
,可以添加一個(gè)新的狀態(tài)State 2
胁编∠峋可以看到新的State 2
上是沒(méi)有觸發(fā)條件的,這說(shuō)明State 2
完全沒(méi)可能被激活嬉橙,也就是完全不起作用早直。
我們可以在State 2
上單擊右鍵并選擇Set as Start State
,那么State 2
就會(huì)變成我們的初始狀態(tài)市框,State 1
不起任何作用霞扬。
點(diǎn)擊Unity3D工具欄中間的Play按鈕運(yùn)行場(chǎng)景,我們會(huì)發(fā)現(xiàn)State 2
上有一圈綠光枫振,PM編輯器左下角也有提示當(dāng)前狀態(tài)處于“State 2”喻圃。
這時(shí)我們是沒(méi)有辦法讓Cube返回“State 1”的,因?yàn)槲覀冞€沒(méi)有設(shè)置任何觸發(fā)條件粪滤。
Event(事件)和Transition(轉(zhuǎn)換)
下面我們來(lái)添加一些觸發(fā)條件斧拍,也就是event事件。
在State 2
上點(diǎn)擊右鍵杖小,選擇Add Transition
> FINISHED
肆汹。(“FINISHED”也是一個(gè)系統(tǒng)事件,代表“本狀態(tài)已經(jīng)執(zhí)行完所有操作的意思)
這時(shí)候State 2
下面多出來(lái)一行FINISHED
予权,說(shuō)明我們已經(jīng)添加了一個(gè)Transition(轉(zhuǎn)換)給State 2
县踢,同時(shí)這個(gè)Transition的發(fā)生條件是FINISHED
事件被觸發(fā)。
但這時(shí)出現(xiàn)了一個(gè)錯(cuò)誤標(biāo)志(紅色圓圈中間有白色感嘆號(hào))伟件,這是因?yàn)槲覀兘o一個(gè)State添加了Transition硼啤,卻還沒(méi)有指定這個(gè)Transition的目標(biāo)State,就好像我們上了一輛的士斧账,卻還沒(méi)告訴司機(jī)往哪里開(kāi)一樣谴返。這個(gè)錯(cuò)誤標(biāo)志就是在提示我:你小子還有事情沒(méi)干完呢!
用鼠標(biāo)把FINISHED
拖到State 1
上松開(kāi)咧织,我們就指定了這個(gè)Transition的目的地是State 1
嗓袱,也就是說(shuō)我們告訴電腦,當(dāng)FINISHED
這個(gè)事件被觸發(fā)時(shí)习绢,請(qǐng)將Cube的當(dāng)前狀態(tài)轉(zhuǎn)換到State 1
渠抹,這時(shí)候錯(cuò)誤提示消失了蝙昙。
當(dāng)我們選擇一個(gè)state的時(shí)候,編輯器右邊會(huì)自動(dòng)切換到State欄梧却,這一欄中應(yīng)該是儲(chǔ)存該狀態(tài)下需要執(zhí)行的所有Action(動(dòng)作)的奇颠,但在這個(gè)例子中我們還沒(méi)有添加任何Action,所以這里是空的放航。
點(diǎn)擊State欄位右邊的Events
進(jìn)入Events欄烈拒,我們會(huì)發(fā)現(xiàn)這里已經(jīng)有了一個(gè)叫“FINISHED”的Event了,而且顯示被使用過(guò)1次广鳍。Fsm中所有被使用到的Events都會(huì)被顯示在這一欄內(nèi)荆几,我們可以通過(guò)查看Used
數(shù)挑出那些無(wú)用的Event并刪除掉。
如果需要添加新的Event赊时,只需要在下方Add Event
中輸入名稱(chēng)吨铸,點(diǎn)擊Enter
(回車(chē))鍵就可以了。
Event最前面的小方框如果被勾選的話(huà)祖秒,這個(gè)Event就會(huì)變成一個(gè)“Global Event”(全局事件)焊傅。普通的Event只能在Fsm內(nèi)部被觸發(fā),而Global Event可以從Fsm外部被觸發(fā)狈涮。也就是說(shuō)Fsm A中的global event可以在Fsm B中通過(guò)特殊的Action(
Send Event
)來(lái)觸發(fā),但Fsm A中的普通event只可以在Fsm A內(nèi)部被觸發(fā)鸭栖。
前面在添加Transition的時(shí)候會(huì)看到除了可以添加普通Transition以外還可以添加Global Transition(全局轉(zhuǎn)換)歌馍。全局轉(zhuǎn)換的形態(tài)就是好像最前面的START
一樣,位于State的上方且黑底晕鹊。所謂全局轉(zhuǎn)換的意思是不論物體當(dāng)前處于哪個(gè)State松却,只要該Event被觸發(fā),都會(huì)轉(zhuǎn)換到目標(biāo)State溅话。而一般的Transition晓锻,只有在其所在State是當(dāng)前狀態(tài)的情況下才能夠進(jìn)行轉(zhuǎn)換。
區(qū)分清楚事件/全局事件飞几、轉(zhuǎn)換/全局轉(zhuǎn)換砚哆、變量/全局變量等概念對(duì)于掌握PlayMaker非常重要。
下面我們可以把之前的生活邏輯做成一個(gè)Fsm了:
在場(chǎng)景中新建一個(gè)空物體(Create
> Create Empty
)屑墨,Reset位移躁锁,改名為MyLife
。
打開(kāi)PM編輯器卵史,建立如下Graph:
看起來(lái)战转,我們的生活還是蠻復(fù)雜的嘛!
點(diǎn)擊Play:當(dāng)前狀態(tài)停留在Sleeping
以躯。因?yàn)槲覀冞€沒(méi)有設(shè)置任何Action槐秧,所以也不會(huì)自動(dòng)觸發(fā)任何非系統(tǒng)Event,但我們可以手動(dòng)激活Transition。
按住Alt
鍵不放刁标,點(diǎn)擊我們希望激活的Transition颠通,會(huì)發(fā)現(xiàn)當(dāng)前狀態(tài)發(fā)生了改變。當(dāng)狀態(tài)改變到Getting up
的時(shí)候命雀,會(huì)很快跳到Breakfast
然后又跳到Check time
蒜哀,這是因?yàn)?code>FINISHED是一個(gè)系統(tǒng)事件,狀態(tài)中的Action都執(zhí)行完畢就會(huì)自動(dòng)跳轉(zhuǎn)吏砂。
“無(wú)限循環(huán)”錯(cuò)誤:
下面我們建立一個(gè)簡(jiǎn)單的Graph來(lái)演示一個(gè)PlayMaker中很常見(jiàn)的錯(cuò)誤:
我們希望狀態(tài)1完成以后去完成狀態(tài)2撵儿,狀態(tài)2完成以后又回到狀態(tài)1,貌似是個(gè)很正常的邏輯狐血,在兩個(gè)狀態(tài)間不斷循環(huán)淀歇。(底下的State 3
是這個(gè)錯(cuò)誤的簡(jiǎn)化版,也是不斷循環(huán)執(zhí)行自身的意思)
但如果點(diǎn)擊Play
按鈕匈织,會(huì)出現(xiàn)[DISABLED]
提示浪默,Unity的Console欄也會(huì)出現(xiàn)錯(cuò)誤提示:
Error : FSM : Loop cont exceeded maximum: 1000 Default is 1000. Override in Fsm inspector.
估計(jì)大家在自己實(shí)踐的過(guò)程中會(huì)經(jīng)常看到這個(gè)錯(cuò)誤提示缀匕。它表面上的意思是告訴我們纳决,這個(gè)FSM循環(huán)了超過(guò)1000次,預(yù)設(shè)的最大循環(huán)次數(shù)是1000乡小,請(qǐng)?jiān)贗nspector面板中修改設(shè)置阔加。如果大家真的跑去修改這個(gè)預(yù)設(shè)的最大循環(huán)數(shù),可能會(huì)出現(xiàn)兩個(gè)可能满钟,一是會(huì)超過(guò)你新設(shè)置的最大循環(huán)數(shù)繼續(xù)報(bào)錯(cuò)胜榔,二是會(huì)導(dǎo)致死機(jī)。
為什么呢湃番?我們?cè)趦蓚€(gè)State中都沒(méi)有任何Action夭织,所以會(huì)立即轉(zhuǎn)換到目標(biāo)State,于是在游戲時(shí)間1幀內(nèi)吠撮,State 1
和State 2
會(huì)不斷轉(zhuǎn)換尊惰,直到達(dá)到1000次被強(qiáng)行停止,在這個(gè)過(guò)程中泥兰,游戲一直停頓在那一幀择浊,如果你的電腦很快,也許這個(gè)錯(cuò)誤信息不到1秒鐘就報(bào)出來(lái)了逾条,但如果你的電腦很慢琢岩,可能會(huì)停頓四五秒才會(huì)達(dá)到1000次循環(huán),在這四五秒中整個(gè)游戲是卡住的师脂。
這個(gè)錯(cuò)誤類(lèi)似于編程中出現(xiàn)的“無(wú)限循環(huán)”錯(cuò)誤担孔。如果出現(xiàn)這個(gè)錯(cuò)誤江锨,首先要檢查一下我們的程序邏輯有沒(méi)有問(wèn)題,如果邏輯上確實(shí)沒(méi)有問(wèn)題糕篇,可以給
State 2
添加一個(gè)叫Next Frame Event
的行為啄育,然后用這個(gè)行為觸發(fā)FINISHED
事件,這樣從State 2
往State 1
的轉(zhuǎn)換就會(huì)被強(qiáng)制在下一個(gè)游戲幀中發(fā)生拌消。
System Events(系統(tǒng)事件)
-
APPLICATION FOCUS
:游戲運(yùn)行時(shí) -
APPLICATION PAUSE
:游戲暫停時(shí) -
APPLICATION QUIT
:游戲退出時(shí) -
BECAME INVISIBLE
:物體不可見(jiàn)時(shí) -
BECAME VISIBLE
:物體可見(jiàn)時(shí) -
COLLISION ENTER
:碰撞體進(jìn)入時(shí) -
COLLICION ENTER 2D
:2D碰撞體進(jìn)入時(shí) -
COLLISION EXIT
:碰撞體離開(kāi)時(shí) -
COLLISION EXIT 2D
:2D碰撞體離開(kāi)時(shí) -
COLLISION STAY
:碰撞體停留期間 -
COLLISION STAY 2D
:2D碰撞體停留期間 -
CONTROLLER COLLIDER HIT
:Controller類(lèi)碰撞體被觸碰時(shí) -
JOINT BREAK
:骨骼斷開(kāi)時(shí) -
JOINT BREAK 2D
:2D骨骼斷開(kāi)時(shí) -
LEVEL LOADED
挑豌;關(guān)卡載入時(shí) -
MOUSE DOWN
:鼠標(biāo)在物體上被按下時(shí) -
MOUSE DRAG
:鼠標(biāo)在物體上被按下然后拖動(dòng)時(shí) -
MOUSE ENTER
:鼠標(biāo)滑入物體時(shí) -
MOUSE EXIT
:鼠標(biāo)滑出物體時(shí) -
MOUSE OVER
:鼠標(biāo)懸停物體之上時(shí) -
MOUSE UP
:鼠標(biāo)在物體上按下并松開(kāi)時(shí)(單擊) -
MOUSE UP AS BUTTON
:鼠標(biāo)單擊(作為按鈕) -
PARTICLE COLLISION
:粒子碰到碰撞體時(shí) -
TRIGGER ENTER
:觸發(fā)器被進(jìn)入時(shí) -
TRIGGER ENTER 2D
:2D觸發(fā)器被進(jìn)入時(shí) -
TRIGGER EXIT
:觸發(fā)器被離開(kāi)時(shí) -
TRIGGER EXIT 2D
:2D觸發(fā)器被離開(kāi)時(shí) -
TRIGGER STAY
:觸發(fā)器被停留期間 -
TRIGGER STAY 2D
:2D觸發(fā)器被停留期間
普通的event必須由Action來(lái)觸發(fā),而系統(tǒng)事件則無(wú)需通過(guò)Action來(lái)觸發(fā)墩崩。我們可以做一個(gè)簡(jiǎn)單的例子氓英,通過(guò)鼠標(biāo)左鍵的按下和松開(kāi)來(lái)控制兩個(gè)狀態(tài)之間的轉(zhuǎn)換:
新建場(chǎng)景,創(chuàng)建一個(gè)Cube鹦筹,Reset位移铝阐。然后打開(kāi)PM編輯器,創(chuàng)建FSM铐拐,并另外創(chuàng)建一個(gè)State 2
徘键。在State 1
上點(diǎn)擊右鍵,選擇Add Transition
> System Events
> MOUSE DOWN
遍蟋,同理在State 2
上添加MOUSE UP
吹害,然后把它們連起來(lái)。
在Scene View中按然后點(diǎn)擊Play運(yùn)行場(chǎng)景它呀。f
鍵使Cube居中虚青,
保持PM的編輯器可見(jiàn),然后在Game View中按下鼠標(biāo)左鍵挟憔。
如果是在Cube上按下左鍵的話(huà),Cube會(huì)進(jìn)入State 2烟号,松開(kāi)鼠標(biāo)绊谭,Cube返回State 1。
我劃掉上面前半句的意思是這步操作沒(méi)什么用汪拥。測(cè)試場(chǎng)景必須在Game View中進(jìn)行达传,在Scene View中改變視角并不影響Game View。
要注意的是迫筑,這個(gè)范例能夠做成功宪赶,是因?yàn)槲覀兊腇sm是添加在一個(gè)Cube物體上的,
MOUSE UP
和MOUSE DOWN
這兩個(gè)系統(tǒng)事件是探測(cè)鼠標(biāo)是否在當(dāng)前物體范圍內(nèi)被按下或者松開(kāi)脯燃,因而都需要這個(gè)“當(dāng)前物體”是具有Collider碰撞體設(shè)置的搂妻,而Cube創(chuàng)建出來(lái)就自帶Collider,這樣才沒(méi)有出錯(cuò)辕棚。
Network Events(網(wǎng)絡(luò)事件)
-
CONNECTED TO SERVER
:連接上服務(wù)器時(shí) -
DISCONNECTED FROM SERVER
:從服務(wù)器斷開(kāi)時(shí) -
FAILED TO CONNECT
:連接服務(wù)器失敗時(shí) -
FAILED TO CONNECT TO MASTER SERVER
:鏈接主服務(wù)器失敗時(shí) -
MASTER SERVER EVENT
:主服務(wù)器事件 -
NETWORK INSTANTIATE
:網(wǎng)絡(luò)重名時(shí) -
PLAYER CONNECTED
:玩家連接成功時(shí) -
PLAYER DISCONNECTED
:玩家連接中斷時(shí) -
SERVER INITIALIZED
:服務(wù)器重置時(shí)
Action(動(dòng)作)
如果說(shuō)使用Fsm欲主、States邓厕、Events和Transitions可以搭出一個(gè)合理的交互邏輯的框架的話(huà),這個(gè)交互邏輯在添加Action之前就完全是一個(gè)空架子扁瓢,一個(gè)設(shè)計(jì)而已详恼。只有添加了Action,State才變得有意義引几,GameObject才會(huì)隨著PlayMaker設(shè)計(jì)的這個(gè)邏輯來(lái)行動(dòng)昧互。
PlayMaker有非常多的Action,而且還有很多開(kāi)發(fā)者在為PlayMaker編寫(xiě)各式各樣的第三方Action(可以理解成有人為PlayMaker這個(gè)插件開(kāi)發(fā)插件)伟桅,一個(gè)Action通常執(zhí)行一項(xiàng)或幾項(xiàng)Unity3D的“操作”敞掘,比如獲取某個(gè)GameObject的位置,在場(chǎng)景中新建一個(gè)Cube贿讹,改變一個(gè)材質(zhì)球的顏色渐逃,為一個(gè)變量賦值等等。
選擇一個(gè)State民褂,點(diǎn)擊編輯器右下角的Action Browser
可以打開(kāi)動(dòng)作瀏覽器茄菊。第一眼看到這個(gè)瀏覽器我整個(gè)人是崩潰的,那么多Action找都找不過(guò)來(lái)赊堪,更別說(shuō)使用了面殖。好在這個(gè)瀏覽器提供了搜索過(guò)濾功能,我們可以輸入一些關(guān)鍵字來(lái)快速定位我們想要使用的Action哭廉。
大家可以到 這里 查看完整的行為列表手冊(cè)脊僚,特別特別多。
Ceeger上有 較早版本的PlayMaker漢化手冊(cè) 可供下載遵绰,不過(guò)和現(xiàn)在的1.8.4
版已經(jīng)有些不同了辽幌。雖然PlayMaker可以設(shè)置語(yǔ)言為中文(
Preferences
>General
>Language
>Chinese Simplified
),但暫時(shí)并沒(méi)有漢化Action列表椿访。
怎么學(xué)習(xí)PlayMaker的Action
這么多Action應(yīng)該怎么去學(xué)乌企?我們要不要把每個(gè)Action的用法都背下來(lái)?我個(gè)人的經(jīng)驗(yàn)是從實(shí)踐中去學(xué)習(xí)成玫。
首先當(dāng)然需要把整個(gè)Action列表瀏覽一遍加酵,大致知道PlayMaker提供了哪些方便有用的Action給我們,又有哪些是很基礎(chǔ)性的功能哭当,簡(jiǎn)單卻常常會(huì)用到猪腕。
Action列表自身的組織結(jié)構(gòu)是有分類(lèi)的,但這個(gè)分類(lèi)主要是依照Action所處理的對(duì)象來(lái)分的钦勘,而且主類(lèi)就有幾十個(gè)陋葡,并不是特別適合我們學(xué)習(xí)。我這里提供一個(gè)我自己理解的依照Action所執(zhí)行功能而做的大致分類(lèi)給大家參考:
- 用來(lái)獲取參數(shù)/變量數(shù)值的
- 用來(lái)改變參數(shù)/變量數(shù)值
- 用來(lái)創(chuàng)建或刪除游戲物體
- 用來(lái)給游戲物體添加或刪除組件
- 用來(lái)執(zhí)行某個(gè)組件(或腳本)中的特定功能函數(shù)(Function)
- 用來(lái)觸發(fā)Fsm事件
- 對(duì)整個(gè)游戲系統(tǒng)進(jìn)行控制彻采,比如暫停脖岛、退出朵栖、載入場(chǎng)景等等
其實(shí),Action列表中有很大一部分是我們平時(shí)很少會(huì)用到的柴梆,甚至有一些是針對(duì)特定插件的支持陨溅,如果不用這些插件,就根本不會(huì)需要用到這些Action绍在。
按照功能標(biāo)準(zhǔn)在腦海中對(duì)所有Action有了個(gè)初步印象以后门扇,就要記憶一些關(guān)鍵字了,因?yàn)槲覀?9%的情況下偿渡,都是通過(guò)關(guān)鍵字在Action Browser中去搜索需要的Action臼寄,而不是順著列表慢慢找。記住這些關(guān)鍵字可以極大的方便我們定位Action溜宽,節(jié)省時(shí)間吉拳。這些關(guān)鍵字包括:get
、set
适揉、gameobject
留攒、position
、fsm
嫉嘀、float
炼邀、bool
、vector3
剪侮、collision
拭宁、trigger
、ray
瓣俯、compare
等等杰标。
這個(gè)記憶工作可以隨著我們學(xué)習(xí)和練習(xí)的過(guò)程來(lái)做,看得多了彩匕,做得多了腔剂,慢慢也就知道要實(shí)現(xiàn)哪些功能需要用到哪些Action了,那么這些Action的用法就是需要熟練掌握的推掸。總而言之桶蝎,學(xué)習(xí)Action要按照“功能類(lèi)”來(lái)一類(lèi)一類(lèi)地學(xué)驻仅,而不是一個(gè)一個(gè)Action地學(xué)谅畅。
對(duì)于我們用到的Action,花一點(diǎn)點(diǎn)時(shí)間去看看這個(gè)Action的具體用法噪服。在Action Browser中定位到Action之后是可以看到一個(gè)簡(jiǎn)單的描述的毡泻,英文好的同學(xué)可以直接閱讀一下,看不懂的就去找中文翻譯粘优。我有時(shí)間的時(shí)候也會(huì)慢慢完成 PlayMaker Actions (未完成) 這一篇文章仇味,以供大家參考呻顽。
對(duì)PlayMaker有個(gè)基本的掌握之后,網(wǎng)上的PlayMaker教程對(duì)你基本上就沒(méi)有什么難度(總體來(lái)說(shuō)PlayMaker的教學(xué)資源還是太少丹墨,也太淺)廊遍,這個(gè)時(shí)候可以開(kāi)始看那些入門(mén)級(jí)別的Unity3D小游戲教程,看人家怎么寫(xiě)腳本來(lái)實(shí)現(xiàn)交互設(shè)計(jì)的贩挣,然后把別人的思路轉(zhuǎn)化到PlayMaker里面喉前,用PlayMaker去重現(xiàn)這些教程的內(nèi)容。
關(guān)于 Every Frame
選項(xiàng)
有些Actions會(huì)具有一個(gè)Every Frame
的選項(xiàng)王财,通常都在最下方卵迂。勾選這個(gè)選項(xiàng),會(huì)迫使這個(gè)Action每幀都執(zhí)行一遍绒净,直到游戲物體離開(kāi)當(dāng)前狀態(tài)见咒。不勾選的話(huà)這個(gè)選項(xiàng)的話(huà),每次進(jìn)入這個(gè)狀態(tài)以后挂疆,這個(gè)Action的操作都會(huì)進(jìn)行一次改览,不論游戲物體在這個(gè)狀態(tài)停留多久。
但這并不是說(shuō)沒(méi)有這個(gè)選項(xiàng)的Action就都是只執(zhí)行一次的囱嫩,沒(méi)有這個(gè)選項(xiàng)代表這個(gè)Action要么只能執(zhí)行一次恃疯,要么是必須每幀執(zhí)行的。
怎么來(lái)判斷是否勾選這個(gè)選項(xiàng)呢墨闲?比如我們有個(gè)Action是監(jiān)控是否有子彈擊中玩家的今妄,那么這個(gè)Action當(dāng)然要每幀都執(zhí)行一遍咯,但如果是發(fā)射子彈的Action鸳碧,通常就不能每幀執(zhí)行了盾鳞,僅在“發(fā)射”狀態(tài)被激活時(shí)執(zhí)行一次就可以了。
如果一個(gè)State的列表中有至少1個(gè)
Every Frame
類(lèi)型的Action瞻离,那么這個(gè)State就不可能自然終止腾仅,也就是說(shuō)系統(tǒng)事件FINISHED
永遠(yuǎn)不會(huì)被觸發(fā),因?yàn)檫@個(gè)Every Frame
類(lèi)型的Action永遠(yuǎn)不會(huì)執(zhí)行完畢套利。
這里有一個(gè)思維誤區(qū)推励,就是理所當(dāng)然的認(rèn)為從一個(gè)狀態(tài)轉(zhuǎn)換到另一個(gè)狀態(tài)的時(shí)候,游戲進(jìn)入了新的一幀肉迫,這是不對(duì)的验辞。如果沒(méi)有
Next Frame Event
的話(huà),從狀態(tài)A轉(zhuǎn)換到狀態(tài)B然后再到狀態(tài)C是有可能發(fā)生在同一幀游戲時(shí)間以?xún)?nèi)的喊衫。因此在PlayMaker中利用狀態(tài)轉(zhuǎn)換做循環(huán)要非常小心跌造,否則很容易在一幀里面無(wú)限循環(huán)。
變量(variables)
變量是用來(lái)儲(chǔ)存數(shù)據(jù)/數(shù)值的。
Unity3D自身有變量壳贪,不同的Component都有很多或私有(private)或公開(kāi)(public)的變量陵珍,PlayMaker可以通過(guò)Action去調(diào)用它們(Get Property
)或者直接對(duì)其賦值(Set Property
)。
PlayMaker自身也有變量违施,我們叫做Fsm變量互纯,以區(qū)別于Unity3D的變量。調(diào)用其他Fsm的變量需要用到Get FSM Variable
這個(gè)Action磕蒲,為其他Fsm變量賦值要用到Set FSM Variable
這個(gè)Action伟姐。
對(duì)于本Fsm內(nèi)部的變量進(jìn)行操作是最簡(jiǎn)單的,很多Action都可以讀取某個(gè)內(nèi)部變量值或者將某個(gè)值儲(chǔ)存在內(nèi)部變量中亿卤。
變量需要事先申明其“類(lèi)型”愤兵,PlayMaker對(duì)于變量類(lèi)型的要求非常嚴(yán)格,大家可以在 Unity3D的數(shù)據(jù)類(lèi)型以及PlayMaker的變量 一文中詳細(xì)了解排吴。