前置閱讀:PlayMaker:觸發(fā)事件
Demo演示:PM_Cube
準(zhǔn)備場景
- 新建場景郊艘,保存為
PM_Cube
声旺。 - 創(chuàng)建一個(gè)Plane當(dāng)?shù)孛嫘扯Γ麨?code>Ground舰蟆,重置位置(在Transform組件上點(diǎn)擊右上角的“小齒輪”,選擇
Reset
)狸棍。再創(chuàng)建一個(gè)Cube物體身害,重置位置,修改Y Position
為 0.5草戈。 - 為
Ground
和Cube
分別創(chuàng)建材質(zhì)球塌鸯,修改顏色以示區(qū)別。 - 在Scene View中調(diào)整好一個(gè)合適的攝影機(jī)角度唐片,選擇
Main Camera
丙猬,從菜單選擇GameObject
>Align With View
將其與Scene View對(duì)齊。
PM_Cube version 0.1
做一個(gè)有“顏值”的Cube费韭!
選擇Cube
茧球,打開PlayMaker Editor為其添加一個(gè)Fsm(命名為FSM_Color)。選擇State 1
星持,點(diǎn)擊Action Browser
打開動(dòng)作瀏覽器抢埋,在搜索欄輸入“color”,然后選擇Material類別中的Set Material Color
钉汗,雙擊將其添加到State 1
中羹令。
在我們添加好的Action中鲤屡,修改Material
參數(shù)為我們?cè)O(shè)置給Cube的材質(zhì)(點(diǎn)擊Material
參數(shù)后面的小圓點(diǎn)损痰,然后選擇material,或者直接將material從Project面板中拖到這里)酒来,修改Color
參數(shù)為我們想要的顏色卢未。
這個(gè)Action的作用是:將指定GameObject(Game Object
)上Mesh Renderer組件中的特定材質(zhì)球(Material Index
)或者任意指定的材質(zhì)球(Material
)上特定名稱(Named Color
)的顏色參數(shù),修改為指定顏色(Color
)堰汉。
-
Use Owner
代表“自己”辽社,表示使用該Fsm所在的GameObject - 參數(shù)后面的“=”按鈕代表這個(gè)參數(shù)可以使用一個(gè)FSM變量
-
Every Frame
如果被勾選,代表每幀都會(huì)執(zhí)行一次該Action的操作
運(yùn)行場景(點(diǎn)擊Play
按鈕)翘鸭,我們發(fā)現(xiàn)Cube變成了綠色滴铅。
退出Play模式,我們發(fā)現(xiàn)Cube保持為綠色就乓,這是因?yàn)槲覀冎苯訉?duì)材質(zhì)球的顏色做了修改汉匙,而材質(zhì)球并不是場景物體拱烁,而是Asset資源,所以在Play模式被修改了以后噩翠,退出Play模式也不會(huì)恢復(fù)戏自。
在Play模式下我們對(duì)場景物體進(jìn)行的修改,退出Play模式以后都不會(huì)被保存伤锚,但初學(xué)者經(jīng)常忘記這一點(diǎn)擅笔。所以可以從菜單
Edit
>Preferences
打開Unity Preferences面板,然后選擇Colors
欄屯援,將第一行的Playmode tint
顏色修改成一個(gè)比較顯眼的顏色猛们,這樣就不會(huì)忘記退出Play Mode了。
PM_Cube version 0.2
Cube也是會(huì)翻臉的哦玄呛!
下面我們改造一下:
首先我取消了Material
參數(shù)上的設(shè)置(點(diǎn)擊小圓點(diǎn)阅懦,選擇None
)。這是因?yàn)槲壹热灰呀?jīng)設(shè)置了使用模型本身Material Index
為0的那個(gè)材質(zhì)進(jìn)行修改徘铝,就無需再指定特定材質(zhì)球了耳胎。
修改“GameObject上Material Index = 0的材質(zhì)”和“修改對(duì)應(yīng)的
.mat
文件”還是有所區(qū)別的,我們可以認(rèn)為游戲物體上實(shí)際附加的材質(zhì)是Assets目錄下.mat
文件的一份拷貝惕它,修改Material Index = 0的材質(zhì)參數(shù)實(shí)際上不會(huì)改變.mat
文件本身怕午。
所以做了這個(gè)修改以后,就不會(huì)出現(xiàn)退出Play模式顏色依然保持改變的情況了淹魄。通常情況下郁惜,我們都盡量不要直接對(duì)Asset本體進(jìn)行修改,調(diào)用以后修改GameObject就可以了甲锡。
按下Color后面的“=”按鈕兆蕉,然后點(diǎn)擊紅色顯示的None
,選擇New Variable...
以創(chuàng)建一個(gè)新的變量缤沦,起名為“color”虎韵。
然后到Variables欄中,就會(huì)看到有新的變量出現(xiàn)了缸废,這個(gè)變量名稱為color包蓝,類型是“Color”。
給PlayMaker的動(dòng)作參數(shù)指定變量企量,變量類型必須與參數(shù)的數(shù)據(jù)類型一致测萎,所以最好的辦法是在參數(shù)中創(chuàng)建新變量,這樣類型就一定是匹配的了届巩。
如果想直接在變量面板中新建變量硅瞧,首先在空白處點(diǎn)擊以取消當(dāng)前選擇的參數(shù),然后在下方
New Variable
欄中輸入名稱恕汇,Variable Type
欄中選擇類型腕唧,點(diǎn)擊Add
或者按回車都可以完成創(chuàng)建冒嫡。
我勾選了這個(gè)color變量的Inspector
選項(xiàng)以使它能夠在Inspector面板中可見,然后修改了默認(rèn)顏色四苇。
接下來改造Graph:
我添加了3個(gè)新的state孝凌,用來將顏色分別修改成綠色、紅色和藍(lán)色月腋,在Events面板中創(chuàng)建了3個(gè)新的event:Set Green
蟀架、Set Red
、Set Blue
用來觸發(fā)狀態(tài)的轉(zhuǎn)換榆骚,在State 1
中使用這3個(gè)event做transition片拍,分別指向紅綠藍(lán)三個(gè)state。最后給紅綠藍(lán)三個(gè)state添加FINISHED
轉(zhuǎn)換讓他們完成操作后重新回到State 1
妓肢。
在紅綠藍(lán)三個(gè)state中我都使用了Set Color Value
這個(gè)Action來修改顏色捌省,因?yàn)樵谶@3個(gè)狀態(tài)中我不是要去改變材質(zhì)顏色,而是要去改變顏色變量color
的數(shù)值碉钠。
運(yùn)行測試:
一開始會(huì)呈現(xiàn)color值預(yù)設(shè)的顏色纲缓,手動(dòng)轉(zhuǎn)換狀態(tài)(Alt
+ 左鍵單擊),可以改變Cube的顏色喊废。
實(shí)際的邏輯是這樣的祝高,紅綠藍(lán)三個(gè)state修改了變量color
的值,然后返回State 1
的時(shí)候污筷,State 1
讀取變量color
最新的值并賦給材質(zhì)的_Color
參數(shù)工闺,顏色改變。每一次進(jìn)入State 1
瓣蛀,都會(huì)執(zhí)行一次“讀取color
并賦值”的操作陆蟆,所以保證了每次修改完變量值,Cube的顏色都會(huì)發(fā)生改變惋增。
當(dāng)然叠殷,想要達(dá)到這樣的交互效果,這并不是唯一的設(shè)計(jì)方案器腋。大家可以在我們逐漸將這個(gè)實(shí)例改造得越來越復(fù)雜之后再回過頭來想一想溪猿,為什么這里會(huì)采用這樣的設(shè)計(jì)方案钩杰,為什么有時(shí)候即使只添加了一點(diǎn)新的需求纫塌,原來的設(shè)計(jì)方案會(huì)立刻顯得不合適而需要大幅度的修改。
PM_Cube version 0.3
Cube這次是來真的了讲弄!
下面添加一些觸發(fā)條件來讓這個(gè)交互邏輯變得Playable措左。
在State 1中添加3個(gè)Get Mouse Button Down
行為,分別指定其Button
為Left
避除、Middle
怎披、Right
胸嘁,然后設(shè)置其Sent Event
為Set Red
、Set Blue
凉逛、Set Green
性宏。
運(yùn)行測試:
當(dāng)我們?cè)谌我馕恢冒聪率髽?biāo)左中右鍵時(shí),Cube的顏色會(huì)相應(yīng)變成紅状飞、藍(lán)毫胜、綠。
Get Mouse Button Down
和之前的系統(tǒng)事件MOUSE DOWN
是不一樣的诬辈,前者只是檢查鼠標(biāo)按鍵是否被按下酵使,而后者是檢查是否在游戲物體上按下鼠標(biāo)左鍵;In Update Only
選項(xiàng)非常重要焙糟。Get Mouse Button Down
檢測的是按鍵是否處于被按下狀態(tài)口渔,如果是,立刻轉(zhuǎn)換狀態(tài)穿撮。但由于我們的目標(biāo)狀態(tài)也是可以立即完成并轉(zhuǎn)換回State 1
的缺脉,而我們?nèi)祟悘陌聪率髽?biāo)到松開鼠標(biāo)還有一段時(shí)間,在這段時(shí)間兩個(gè)狀態(tài)是會(huì)不斷進(jìn)行循環(huán)的悦穿,這就產(chǎn)生了“無限循環(huán)”錯(cuò)誤枪向。而In Update Only
選項(xiàng)則強(qiáng)制狀態(tài)轉(zhuǎn)換只在Update(也就是刷新至下一幀)時(shí)發(fā)生,從而避免了在一幀時(shí)間內(nèi)發(fā)生多次轉(zhuǎn)換的情況發(fā)生咧党。
PM_Cube version 0.4
Cube不會(huì)無緣無故翻臉的啦秘蛔!
現(xiàn)在在任何地方按下鼠標(biāo)鍵都可以會(huì)使Cube顏色發(fā)生改變,如果我希望只是在“點(diǎn)擊”Cube的時(shí)候才會(huì)發(fā)生顏色改變的傍衡,就要讓PlayMaker學(xué)會(huì)判斷點(diǎn)擊時(shí)鼠標(biāo)下方是什么物體深员。
如果看過 PlayMaker:觸發(fā)事件 一文就會(huì)知道,我們可以使用Mouse Pick
行為來進(jìn)行這個(gè)判斷蛙埂,但問題是應(yīng)該把Mouse Pick
放在哪個(gè)狀態(tài)中呢倦畅?
State 1
是進(jìn)行輸入判斷的,把Mouse Pick
放在這里肯定會(huì)有沖突绣的。因?yàn)殡m然一個(gè)state中的所有action其實(shí)都會(huì)在1幀時(shí)間內(nèi)全部執(zhí)行一遍叠赐,但還是有先后順序的。不論我把Mouse Pick
放在Get Mouse Button Down
的前面還是后面屡江,一旦有event被觸發(fā)芭概,狀態(tài)立刻發(fā)生轉(zhuǎn)換,后面的Action根本就不會(huì)被執(zhí)行惩嘉。
于是我決定把Mouse Pick
放在3個(gè)顏色state里面罢洲。按下鼠標(biāo)鍵后轉(zhuǎn)換到顏色state,首先執(zhí)行判斷鼠標(biāo)是否處于物體之上文黎,如果不處于惹苗,直接轉(zhuǎn)換回State 1
殿较,不執(zhí)行修改color數(shù)值的操作。
Mouse Pick
只是獲取Ray碰撞到的第一個(gè)GameObject桩蓉,我將這個(gè)GameObject儲(chǔ)存到一個(gè)新的變量picked object
中淋纲。判斷還需要用Game Object Compare
來完成,比較變量picked object
是否等于“自身”(Owner
)院究,如果不是帚戳,則說明鼠標(biāo)不在該物體上方,于是觸發(fā)一個(gè)新事件Cancel
儡首,轉(zhuǎn)換回State 1
片任。
在
Red
上設(shè)置好Mouse Pick
和Game Object Compare
后,測試通過蔬胯,然后選擇這兩個(gè)Action对供,復(fù)制(Ctrl
+c
),進(jìn)入另外兩個(gè)state氛濒,粘貼(Ctrl
+v
)产场,就可以把Action序列放進(jìn)去了。這是PlayMaker的一種常用的操作方法舞竿。
可以看到京景,不論是Mouse Pick
還是Game Object Compare
,我都沒有勾選Every Frame
選項(xiàng)骗奖,因?yàn)檫@個(gè)判斷做一次就可以了确徙,無需實(shí)時(shí)監(jiān)控。
此外执桌,Mouse Pick
和Game Object Compare
一定要在Set Color Value
之前鄙皇,否則即便條件成立,系統(tǒng)也會(huì)先執(zhí)行完設(shè)置顏色的操作再轉(zhuǎn)換狀態(tài)仰挣。
接下來我們可以把Cube復(fù)制幾個(gè)伴逸,然后運(yùn)行測試,每個(gè)小方塊都可以被鼠標(biāo)單獨(dú)點(diǎn)擊改變顏色膘壶。
刪除多余的方塊错蝴,把Cube拖到Project面板中以創(chuàng)建成一個(gè)prefab(會(huì)自動(dòng)命名為Cube.prefab
)。
我們可以刪除場景中的Cube颓芭,然后把
Cube.prefab
拖入場景測試一下這個(gè)預(yù)設(shè)物體是否運(yùn)行正常顷锰。這個(gè)例子里面當(dāng)然是正常的,但也有可能生成的prefab再放入場景就完全不起作用了畜伐。原因就在于馍惹,如果一個(gè)組件中的某個(gè)變量被手動(dòng)指定為場景中的某個(gè)游戲物體躺率,而且這個(gè)游戲物體又沒有被包括在prefab中的話玛界,這個(gè)變量賦值信息是不會(huì)被保存在prefab中的万矾。比如,我們?cè)?code>Game Object Compare行為中慎框,如果不是指定
Use Owner
去與picked object
做比較良狈,而是手動(dòng)指定場景中的地面,那么在prefab中相應(yīng)Fsm里的這個(gè)Game Object
參數(shù)其實(shí)是沒有被賦值的笨枯。
PM_Cube version 1.0
偷偷告訴你薪丁,Cube是女生哦!
換個(gè)玩法馅精,點(diǎn)擊屏幕從鼠標(biāo)發(fā)射一個(gè)隨機(jī)顏色的方塊到場景中严嗜。
首先我們要制作一個(gè)隨機(jī)選取顏色方塊。
在場景中重新創(chuàng)建一個(gè)Cube洲敢,附上之前的材質(zhì)漫玄。添加Fsm,在State 1上添加一個(gè)Select Random Color
動(dòng)作和一個(gè)Set Material Color
動(dòng)作压彭。
Select Random Color
可以在給定的多個(gè)顏色值中隨機(jī)選取一個(gè)顏色睦优,我們?cè)O(shè)置Store Color
為一個(gè)新變量color
。
在Set Material Color
中把Color
參數(shù)設(shè)置為使用變量color
壮不。
這時(shí)我們運(yùn)行場景汗盘,Cube會(huì)隨機(jī)顯示成紅、綠询一、藍(lán)中任意一種顏色(大家可以自行設(shè)置七彩小Cube)隐孽。將這個(gè)新的Cube做成prefab(由于已經(jīng)有一個(gè)Cube.prefab
了,所以應(yīng)該會(huì)被自動(dòng)命名為Cube 1.prefab
)健蕊,刪除場景中的Cube缓醋。
在場景中Create
一個(gè)Empty Group
,命名為GameManager
绊诲。Fsm必須作為組件被附加在一個(gè)GameObject上送粱,所以這個(gè)空物體就是我們Fsm的載體。
按下圖創(chuàng)建Graph:
State 1
中檢測鼠標(biāo)左鍵是否按下掂之,如果是抗俄,觸發(fā)LMB Down事件跳轉(zhuǎn)到State 2
。
State 2
中添加一個(gè)Create Object
行為世舰,設(shè)置Game Object為Cube 1.prefab
(點(diǎn)擊后面的小圓點(diǎn)动雹,然后在Assets欄中選擇Cube 1
)。
注意跟压,選擇GameObject的時(shí)候一定要分清楚選擇的是Assets中的prefab還是Scene中的GameObject胰蝠,兩者的圖標(biāo)是不一樣的。
運(yùn)行場景,每次點(diǎn)擊鼠標(biāo)都會(huì)創(chuàng)建一個(gè)新的Cube 1(Clone)
(我們可以從Hierarchy面板中看到茸塞,(Clone)
代表這是一個(gè)實(shí)時(shí)創(chuàng)建出來的克隆體)躲庄。但由于所有的Cube都擁擠在原點(diǎn)位置,所以看上去好像只有一個(gè)的樣子钾虐。拖出來一些Cube噪窘,顏色確實(shí)是隨機(jī)變化了。
但是現(xiàn)在還有幾個(gè)問題沒有解決效扫,一是都擠在一堆了倔监,二是沒有“發(fā)射”的感覺。
Create Object
動(dòng)作為我們生成了一個(gè)Cube菌仁,由于我們沒有設(shè)置Position
和Rotation
浩习,所以這個(gè)Cube會(huì)自動(dòng)被放在坐標(biāo)原點(diǎn)。現(xiàn)在我們希望它出現(xiàn)在鼠標(biāo)點(diǎn)擊的位置济丘。
鼠標(biāo)點(diǎn)擊的位置其實(shí)是攝影機(jī)平面的位置瘦锹,于是我們需要把攝影機(jī)平面坐標(biāo)轉(zhuǎn)換成三維空間立體坐標(biāo),這件事情可以由Screen To World Point
動(dòng)作來完成闪盔。為了方便調(diào)試弯院,我Fsm中新建了一個(gè)State 3
并設(shè)成START
。
Screen To World Point
需要輸入屏幕坐標(biāo)泪掀,于是我還需要獲取屏幕坐標(biāo):
- 我找了半天也找不到一次性獲取屏幕坐標(biāo)(Vector2)的動(dòng)作听绳,所以使用
Get Mouse X
和Get Mouse Y
來分別獲取,儲(chǔ)存到mouse x
和mouse y
兩個(gè)變量中 - 因?yàn)?code>Get Mouse X和
Get Mouse Y
中都勾選了Normalize
异赫,于是我也把Screen To World Point
中的Normalized
給勾上椅挣,并設(shè)置Screen Z
等于2 - 然后在
Screen To World Point
中把Screen X
和Screen Y
分別設(shè)置為mouse x
和mouse y
- 再將獲得的世界坐標(biāo)(
Store World Vector
)儲(chǔ)存在一個(gè)叫world position
的變量里 - 最后勾選上
Every Frame
為了驗(yàn)證這個(gè)世界坐標(biāo)是否正確,我又添加了一個(gè)Set Position
的動(dòng)作塔拳,并在場景中放入了一個(gè)Cube 1.prefab
:
- 指定
Game Object
為場景中的Cube 1 - 指定
Vector
為變量world position
- 勾選上
Every Frame
和Late Update
(設(shè)置每幀到最后再更新位置)
測試結(jié)果還不錯(cuò)鼠证,于是把這套Action搬去真正的Graph:
- 將
State 3
中的Get Mouse X
、Get Mouse Y
靠抑、Screen To World Point
復(fù)制到State 2
里面量九,使其處于Create Object
上方 - 取消
Screen To World Point
的Every Frame
的勾選 - 最后把
State 1
設(shè)置回開始狀態(tài)(點(diǎn)擊右鍵,選擇Set As Start State
)
測試運(yùn)行颂碧,有問題荠列!創(chuàng)建完第一個(gè)Cube之后就回不去State 1
了。這是因?yàn)?code>Get Mouse X和Get Mouse Y
都是每幀執(zhí)行的動(dòng)作载城,根本不會(huì)自然結(jié)束肌似,所以需要手動(dòng)添加一個(gè)Next Frame Event
行為,讓它來觸發(fā)FINISHED
事件诉瓦。
結(jié)果有效川队,但貌似詭異的力细。
PM_Cube version 1.1
就問你怕不怕!
下面終于可以開始制作“發(fā)射”的效果了9潭睢C呗臁!
為了讓Cube能夠被射出去对雪,需要用到動(dòng)力學(xué)(Physics)河狐,所以首先就需要給Cube添加一個(gè)Rigidbody
組件米绕。我們可以直接選取Cube 1.prefab
瑟捣,然后在Inspector最下面點(diǎn)擊Add Component
按鈕,輸入“rigidbody”栅干,按回車確認(rèn)選擇迈套,就將Cube變成了一個(gè)動(dòng)力學(xué)物體。
運(yùn)行場景碱鳞,動(dòng)力學(xué)物體的確好玩桑李,但還沒有添加初速度,就還不算“發(fā)射”窿给。
選擇GameManager贵白,打開PlayMaker編輯器。在State 2
的最后崩泡,添加一個(gè)Add Force
行為禁荒。
Add Force
首先提示我們GameObject需要Rigidbody組件,別忙著加角撞,我們這是在GameManager呛伴,這個(gè)Force并不是加給GameManager的。將Game Object
設(shè)置成cube
變量谒所,這個(gè)警告提示自然就沒有了热康。
Add Force
需要知道這個(gè)Force加在物體的什么位置(At Position
),以及這個(gè)Force的方向及大辛恿臁(Vector)姐军。位置不需要設(shè)置,自動(dòng)就會(huì)處于物體中心尖淘,但Force的方向就有點(diǎn)復(fù)雜了庶弃。大家可以點(diǎn)開X
、Y
德澈、Z
三個(gè)參數(shù)后面的“=”符號(hào)歇攻,手動(dòng)設(shè)置Force的向量分量(要注意是在什么坐標(biāo)空間(Space
)中),也可以開動(dòng)腦筋做一點(diǎn)點(diǎn)數(shù)學(xué)計(jì)算梆造,讓Force符合我們的希望缴守。
最后面這一段有點(diǎn)超綱了葬毫,大家看不太懂的可以自己手動(dòng)用
X
、Y
屡穗、Z
值試出一個(gè)合適的數(shù)值出來贴捡。
我選擇讓Cube沿著攝影機(jī)的方向被發(fā)射出去,所以需要用Cube出生位置減去攝影機(jī)所在的位置來獲得這個(gè)方向矢量(Vector3)村砂,然后將這個(gè)方向矢量標(biāo)準(zhǔn)化(也就是讓它方向保持不變但長度變?yōu)?)烂斋,最后再倍乘上一個(gè)力度值,就可以得到所需要的方向和力度的一個(gè)Force了础废。
詳細(xì)的Action設(shè)置可以看下面這張圖:
- 在
Add Force
上方我先添加了一個(gè)Get Position
汛骂,指定讓它獲取Main Camera的位置并儲(chǔ)存為camera position
變量 - 然后再接一個(gè)
Vector3 Operator
把之前獲得的world position
減去camera position
,結(jié)果儲(chǔ)存為force vector
- 接著使用
Vector3 Normalize
把這個(gè)force vector
標(biāo)準(zhǔn)化 - 然后使用
Vector3 Multiply
把force vector
乘上(Multiply By
)一個(gè)新建的叫做force
的變量 - 最后在
Add Force
中設(shè)置Vector
參數(shù)為force vector
评腺,并更改Force Mode
為Impulse
以表示這是一個(gè)瞬發(fā)的力量
這個(gè)范例也顯示了PlayMaker比較蛋疼的一個(gè)問題帘瞭,就是特別不方便做比較復(fù)雜的數(shù)值計(jì)算。Add Force上方四五個(gè)Action蒿讥,用數(shù)學(xué)公式來寫其實(shí)一行就可以搞定:
force_vector = force * Normalize (cube_position - camera_position)
但在PlayMaker里面就搞得既復(fù)雜又拗口蝶念。
項(xiàng)目工程文件 (不包括PlayMaker插件及其uGUI擴(kuò)展Action包)