版本記錄
版本號 | 時(shí)間 |
---|---|
V1.0 | 2019.01.05 星期六 |
前言
Unity是由Unity Technologies開發(fā)的一個(gè)讓玩家輕松創(chuàng)建諸如三維視頻游戲秀菱、建筑可視化娩贷、實(shí)時(shí)三維動(dòng)畫等類型互動(dòng)內(nèi)容的多平臺的綜合型游戲開發(fā)工具嘉抒,是一個(gè)全面整合的專業(yè)游戲引擎凳兵。Unity類似于Director,Blender game engine, Virtools 或 Torque Game Builder等利用交互的圖型化開發(fā)環(huán)境為首要方式的軟件粘捎。其編輯器運(yùn)行在Windows 和Mac OS X下昭抒,可發(fā)布游戲至Windows、Mac茶鉴、Wii锋玲、iPhone、WebGL(需要HTML5)涵叮、Windows phone 8和Android平臺惭蹂。也可以利用Unity web player插件發(fā)布網(wǎng)頁游戲,支持Mac和Windows的網(wǎng)頁瀏覽割粮。它的網(wǎng)頁播放器也被Mac 所支持盾碗。網(wǎng)頁游戲 坦克英雄和手機(jī)游戲王者榮耀都是基于它的開發(fā)。
下面我們就一起開啟Unity之旅舀瓢。感興趣的看下面幾篇文章廷雅。
1. Unity開啟篇(一) —— Unity界面及創(chuàng)建第一個(gè)簡單的游戲 (一)
2. Unity開啟篇(二) —— Unity界面及創(chuàng)建第一個(gè)簡單的游戲 (二)
3. Unity開啟篇(三) —— 一款簡單射擊游戲示例 (一)
4. Unity開啟篇(四) —— 一款簡單射擊游戲示例 (二)
5. Unity開啟篇(五) —— 一款簡單射擊游戲示例 (三)
6. Unity開啟篇(六) —— Unity動(dòng)畫簡介 (一)
Switching Between Animations – State Machines 101
到目前為止,您已創(chuàng)建了動(dòng)畫片段(Animation Clips)
京髓。 您可以運(yùn)行它們中的每一個(gè)航缀,但無法更改在游戲過程中播放哪一個(gè)動(dòng)畫。 這是狀態(tài)機(jī)用武之地的地方堰怨。
當(dāng)您創(chuàng)建第一個(gè)動(dòng)畫片段時(shí)芥玉,Unity已經(jīng)為小丑創(chuàng)建了一個(gè)狀態(tài)機(jī)。 您可以在Animator View中查看它备图。 為此灿巧,請?jiān)趯哟谓Y(jié)構(gòu)中選擇Clown赶袄,然后從菜單中選擇Window \ Animator
。 您現(xiàn)在應(yīng)該看到Game
選項(xiàng)卡旁邊的Animator
選項(xiàng)卡抠藕。
已經(jīng)有幾種狀態(tài):MoveHorizontally
饿肺,MoveVertically
,Hit
幢痘,Entry
唬格,Exit
和AnyState
。 基本上颜说,每個(gè)狀態(tài)對應(yīng)于只要狀態(tài)處于活動(dòng)狀態(tài)就正在播放的動(dòng)畫片段购岗。
您還會看到一個(gè)從Entry
到MoveHorizontally
的箭頭。 這意味著MoveHorizontally
是默認(rèn)狀態(tài)门粪,即狀態(tài)機(jī)首次激活時(shí)所處的狀態(tài)喊积。 它是橙色的。
注意:如果您的屏幕很小并且沒有看到所有狀態(tài)玄妈,請不要擔(dān)心乾吻。 只需按住alt鍵并用鼠標(biāo)左鍵移動(dòng)鼠標(biāo)即可在
Animator View
中導(dǎo)航。狀態(tài)的布局不會影響行為拟蜻,所以請隨意以適合您的方式安排狀態(tài) - 只需拖動(dòng)它們即可昆禽。
1. Your First Transition
到現(xiàn)在為止還挺好采桃。 現(xiàn)在,您希望小丑在相應(yīng)動(dòng)畫結(jié)束后立即在MoveHorizontally
和MoveVertically
之間切換。 從一種狀態(tài)切換到另一種狀態(tài)稱為轉(zhuǎn)換喷屋。
要?jiǎng)?chuàng)建第一個(gè)過渡格二,請右鍵單擊MoveHorizontally
践啄。 從下拉菜單中選擇Make Transition
羡棵,然后單擊MoveVertically
。 這創(chuàng)造了兩個(gè)狀態(tài)之間的過渡稿蹲。 對于相反的方向扭勉,從MoveVertically
到MoveHorizontally
執(zhí)行相同的操作。
玩游戲:小丑現(xiàn)在從左向右移動(dòng)苛聘,然后向上和向下無限移動(dòng)涂炎。
但是有一些奇怪的事情發(fā)生了:小丑在各狀態(tài)之間切換時(shí)cutting corners
。 你從來沒有告訴它這樣做设哗。 這是怎么回事璧尸?
要回答這個(gè)問題,請?jiān)谟螒蜻\(yùn)行時(shí)選擇Inspector
中的Clown
并切換到Animator View
熬拒。 您將看到處于當(dāng)前活動(dòng)狀態(tài)的進(jìn)度條(progress bar )
。 仔細(xì)觀察并看到垫竞,當(dāng)MoveHorizontally
和MoveVertically
兩個(gè)狀態(tài)同時(shí)具有進(jìn)度條時(shí)澎粟,存在短暫的時(shí)間段蛀序。 這意味著Unity一次運(yùn)行兩個(gè)狀態(tài),將一個(gè)狀態(tài)與另一個(gè)狀態(tài)混合活烙。
混合狀態(tài)可能很有用徐裸;例如,當(dāng)你有一個(gè)從步行過渡到跑步的角色時(shí)啸盏,這看起來更自然重贺。 但是也有一些情況你不想混合兩種狀態(tài)。 幸運(yùn)的是回懦,Unity為您提供了允許您控制轉(zhuǎn)換的設(shè)置气笙。
在Animator View
中,單擊從MoveHorizontally
到MoveVertically
的過渡箭頭怯晕。 在Inspector
中潜圃,您現(xiàn)在可以看到控制轉(zhuǎn)換的設(shè)置。 通過單擊旁邊的三角形展開設(shè)置舟茶。 將Exit Time
設(shè)置為1
谭期,將Transition Duration
設(shè)置為0
。對從MoveVertically
到MoveHorizontally
的過渡執(zhí)行相同操作吧凉。
運(yùn)行游戲隧出。 現(xiàn)在,小丑將水平和垂直移動(dòng)阀捅,但不能同時(shí)移動(dòng)胀瞪。
再看一下過渡設(shè)置:
- 退出時(shí)間
(Exit Time)
確定是否可以在任何時(shí)間觸發(fā)轉(zhuǎn)換,或僅在指定的退出時(shí)間之后觸發(fā)轉(zhuǎn)換也搓。 - 退出時(shí)間是轉(zhuǎn)換開始之前的最早時(shí)間赏廓。它以標(biāo)準(zhǔn)化時(shí)間表示。退出時(shí)間
0.75
表示僅在動(dòng)畫完成75%時(shí)才開始轉(zhuǎn)換傍妒。 -
Transition Duration
和Fixed Duration
允許您指定轉(zhuǎn)換所需的時(shí)間幔摸。如果啟用了Fixed Duration
時(shí)間,請以秒為單位指定持續(xù)時(shí)間颤练。否則既忆,請?jiān)跇?biāo)準(zhǔn)化時(shí)間內(nèi)指定持續(xù)時(shí)間。 -
Transition Offset
控制在轉(zhuǎn)換到的目標(biāo)狀態(tài)下開始播放的時(shí)間的偏移量嗦玖。例如患雇,值為0.5意味著目標(biāo)狀態(tài)將在其自己的時(shí)間軸的50%處開始播放。 - 中斷源控制(
Interrupt Source
)是否可以中斷轉(zhuǎn)換宇挫,例如苛吱,當(dāng)觸發(fā)另一個(gè)轉(zhuǎn)換時(shí)。
有時(shí)很難想象這些參數(shù)意味著什么器瘪。值得慶幸的是翠储,轉(zhuǎn)換圖(Transition Graph)
直接位于檢查器中的轉(zhuǎn)換設(shè)置下方绘雁,可以精確地顯示每個(gè)動(dòng)畫的配置方式:
2. Just do it! – The Any State
無論小丑目前處于什么狀態(tài),每當(dāng)小丑被蛋糕擊中時(shí)援所,你都會想要運(yùn)行一個(gè)命中Hit動(dòng)畫庐舟。你怎么能實(shí)現(xiàn)這個(gè)目標(biāo)?
根據(jù)您到目前為止所學(xué)到的住拭,您可能只需創(chuàng)建兩個(gè)到Hit狀態(tài)的轉(zhuǎn)換:一個(gè)來自MoveHorizontally
狀態(tài)挪略,另一個(gè)來自MoveVertically
狀態(tài)。 雖然這會起作用滔岳,但它不會擴(kuò)展杠娱。 想象一下,你有一個(gè)使用十個(gè)狀態(tài)的更復(fù)雜怪物的游戲澈蟆。 你可以創(chuàng)建十個(gè)轉(zhuǎn)換墨辛,但它會變得混亂,我們希望盡可能簡單趴俘。
您可能已經(jīng)注意到任何狀態(tài)(Any State)
的綠松石盒子睹簇。 它基本上是繪制從所有狀態(tài)到單個(gè)目標(biāo)狀態(tài)的轉(zhuǎn)換的簡便方法。 完善寥闪!
右鍵單擊AnyState
太惠,選擇Make Transition
,然后單擊Hit
狀態(tài)疲憋。 現(xiàn)在您的Animator View
應(yīng)如下所示:
Hit
動(dòng)畫完成后凿渊,狀態(tài)應(yīng)轉(zhuǎn)換為MoveHorizontally
狀態(tài)。
嘗試自己做缚柳。 如果你遇到困難埃脏,請查看:
右鍵單擊
Hit
,然后選擇Make Transition
并單擊MoveHorizontally
以創(chuàng)建過渡秋忙。 選擇它彩掐。 在Inspector
中,將Exit Time
設(shè)置為1灰追,將Transition Duration
設(shè)置為0堵幽。
3. Control State Switches Using Parameters and Conditions
接下來你需要告訴Unity
何時(shí)應(yīng)該在Any State
和Hit
之間進(jìn)行轉(zhuǎn)換,因?yàn)檫@不應(yīng)該自動(dòng)發(fā)生弹澎。 你只希望Animator
在小丑被擊中時(shí)切換到Hit
狀態(tài)朴下。
為此,您可以使用參數(shù)和條件(parameters and conditions)
苦蒿。 參數(shù)是您在Animator
上指定的變量殴胧。 您可以使用它來定義特定轉(zhuǎn)換發(fā)生的條件。
以下是它在實(shí)踐中的工作原理:
在Animator View
的左上角佩迟,選擇Parameters
選項(xiàng)卡溃肪。 單擊+
按鈕免胃。 從下拉菜單中,選擇Trigger
惫撰。 這會創(chuàng)建一個(gè)新的觸發(fā)器。 命名它hit
躺涝。 而已厨钻! 您現(xiàn)在是第一個(gè)參數(shù)的自豪擁有者。
CreateParameterCropped
接下來坚嗜,選擇從任意狀態(tài)到Hit的過渡箭頭(transition arrow)
夯膀。 在“檢查器”中,滾動(dòng)到Conditions
部分苍蔬。 現(xiàn)在它顯示List is Empty
诱建。單擊+
按鈕。 這會將命中觸發(fā)器添加為條件碟绑。
一旦參數(shù)hit
變?yōu)?code>true俺猿,現(xiàn)在將觸發(fā)轉(zhuǎn)換。
要手動(dòng)嘗試格仲,請將動(dòng)畫視圖拖放到游戲視圖旁邊押袍,以便您可以同時(shí)查看兩者。 運(yùn)行游戲凯肋。 在Hierarchy
中谊惭,選擇Clown
。 在Animator
視圖中侮东,單擊hit參數(shù)后的radio button
圈盔。 你會聽到飛濺聲,然后小丑重置悄雅。 很棒 - 您的動(dòng)畫控制器按預(yù)期工作驱敲。
4. Types of Parameters and Combining Conditions
觸發(fā)器很有用,但當(dāng)然可以使用更多參數(shù)類型:
-
Float
:分?jǐn)?shù)(0.1,0.999,6.31煤伟,......)
-
Int
:整數(shù)(1,5,13,1005癌佩,......)
- 布爾:True or False
- 觸發(fā)器:布爾參數(shù),一旦轉(zhuǎn)換消耗便锨,就會重置為false
可根據(jù)您的要求使用每種類型围辙。 例如,Int可以計(jì)算玩家第10次擊中小丑并播放特殊動(dòng)畫的頻率放案。
此外姚建,您可以為Animator View
的參數(shù)列表中的每個(gè)參數(shù)指定默認(rèn)值。
條件(Condition)
用于決定何時(shí)應(yīng)發(fā)生轉(zhuǎn)換吱殉。 您可以在轉(zhuǎn)換上定義多個(gè)條件掸冤。 在這種情況下厘托,必須滿足所有條件才能觸發(fā)轉(zhuǎn)換。
你還可以表達(dá)稿湿,例如铅匹,如果小丑被擊中或者時(shí)間限制到了,小丑應(yīng)該轉(zhuǎn)換到命中狀態(tài)饺藤。 為此包斑,在Any State
和Hit
狀態(tài)之間創(chuàng)建第二個(gè)轉(zhuǎn)換。 在Inspector
中涕俗,您現(xiàn)在可以看到兩個(gè)過渡罗丰。 對于每個(gè)轉(zhuǎn)換,您可以單獨(dú)定義觸發(fā)條件再姑。
Bull’s Eye – Combine Animations and C# Scripts
到目前為止萌抵,您已經(jīng)看到Unity的動(dòng)畫系統(tǒng)有多強(qiáng)大和靈活,即使沒有一行代碼也是如此元镀。 但是,當(dāng)然凹联,使用代碼非常有趣沐兰,因此從腳本中觸發(fā)動(dòng)畫就是接下來要學(xué)習(xí)的內(nèi)容。
1. Trigger an Animation From Code
在對碰撞做出反應(yīng)之前蔽挠,您需要能夠檢測到它住闯。 在層次結(jié)構(gòu)中展開小丑并選擇其子皮膚(Skin)
。 在Inspector
中澳淑,單擊Add Component
并選擇Physics \ Mesh Collider
比原。 在新的Mesh Collider
組件中,勾選Convex
杠巡。
你現(xiàn)在可以看到小丑皮膚周圍的薄綠色邊框量窘。 當(dāng)然,形狀并不完全適合小丑氢拥,但它足夠接近蚌铜。
試試看。 運(yùn)行游戲 - 蛋糕(因?yàn)樗灿幸粋€(gè)Collider
)不再飛過小丑嫩海。
要在代碼中檢測此沖突冬殃,請?jiān)凇皺z查器”中選擇Skin
。 單擊添加組件Add Component
叁怪,然后選擇新腳本New Script
审葬。 將腳本命名為CollisionBehavior
,將Language
設(shè)置為C Sharp
,然后按Create and Add
涣觉。
當(dāng)另一個(gè)Collider
碰到小丑的Mesh Collider
時(shí)痴荐,它會觸發(fā)OnCollisionEnter
。 通過雙擊項(xiàng)目瀏覽器中的文件官册,在MonoDevelop
中打開CollisionBehavior
生兆。
在行void Start()
上面的CollisionBehavior
中添加以下代碼:
// 1
public bool collided;
//2
void OnCollisionEnter(Collision collision) {
if (!collided) {
collided = true;
// 3
GameObject clown = gameObject.transform.parent.gameObject;
Animator clownAnimator = clown.GetComponent<Animator> ();
// 4
clownAnimator.SetTrigger ("hit");
}
}
下面進(jìn)行詳細(xì)分解:
- 1) 創(chuàng)建一個(gè)
bool
變量,記住小丑是否已經(jīng)碰撞過膝宁。 - 2) 如果小丑還沒有碰撞皂贩,則僅觸發(fā)動(dòng)畫。 下一行設(shè)置
collided
為true
昆汹,以確保您只觸發(fā)一次Hit
動(dòng)畫。 - 3) 獲取
Clown GameObject
婴栽,它是當(dāng)前gameObject
的父級满粗,然后使用GetComponent
檢索Animator
。 - 4) 在
clownAnimator
上調(diào)用SetTrigger
愚争。 這使得動(dòng)畫師進(jìn)入了Hit
狀態(tài)映皆。 對于其他參數(shù)類型,您可以使用SetFloat
轰枝,SetInt
捅彻,SetBool
或ResetTrigger
。
運(yùn)行游戲鞍陨,進(jìn)行投擲步淹。 當(dāng)你設(shè)法擊中小丑時(shí),它會發(fā)出嘩然的聲音诚撵!
2. State Machine Behaviors: React to State Changes in Your Scripts
狀態(tài)機(jī)行為(State Machine Behaviors)
允許您編寫依賴于狀態(tài)的行為缭裆。 例如,只要它處于Hit
狀態(tài)寿烟,你就可以使小丑縮小澈驼。 試試看:
在Unity
中,轉(zhuǎn)到Animator View
并選擇Hit
狀態(tài)筛武。 在Inspector
中缝其,單擊Add Behavior
。 選擇New Script
徘六,將其命名為ClownHitBehavior
内边,然后按Create and Add
。
雙擊ClownHitBehavior
打開它硕噩。 你可能會注意到Unity已經(jīng)添加了一些被注釋掉的方法假残。 不要擔(dān)心它們 - 你會很快了解它們的作用。 而是專注于縮放小丑!
為此辉懒,請?jiān)?code>ClownHitBehavior中添加startTime
變量阳惹。
float startTime;
此變量將存儲進(jìn)入Hit
狀態(tài)的時(shí)間。 您可以使用它來控制動(dòng)畫的速度眶俩,具體取決于實(shí)際時(shí)間而不是幀速率莹汤。 這確保了無論游戲運(yùn)行速度有多快,小丑都會以相同的速度收縮颠印。
接下來纲岭,查找(注釋掉)OnStateEnter
方法。 在此方法中线罕,您設(shè)置startTime
的值止潮。 替換為:
override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
startTime = Time.time;
}
當(dāng)狀態(tài)機(jī)進(jìn)入命中狀態(tài)時(shí)調(diào)用OnStateEnter
。 使用Time.time
钞楼,您可以檢索自游戲開始以來的秒數(shù)喇闸。 雖然創(chuàng)造一個(gè)時(shí)鐘并不是那么好,但這對于縮小你的小丑還是很有效的询件。
接下來燃乍,查找OnStateUpdate
方法并將其替換為以下代碼:
override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) {
GameObject clown = animator.gameObject;
clown.transform.localScale *= Mathf.Lerp (1, 0, Time.time - startTime);
}
當(dāng)Hit
狀態(tài)處于活動(dòng)狀態(tài)時(shí),每個(gè)幀都會調(diào)用OnStateUpdate
宛琅。在每一幀中刻蟹,您都可以調(diào)整小丑的大小。
為此嘿辟,您首先需要找到Clown GameObject
舆瘪。當(dāng)腳本在Animator
組件上運(yùn)行時(shí),您不能像以前那樣通過gameObject
簡單地訪問它仓洼。相反介陶,請為該gameObject
詢問該方法的animator
變量,然后將其存儲在clown
變量中色建。
接下來哺呜,使用Mathf.Lerp
更改Clown GameObject
的比例。該方法在兩個(gè)數(shù)值之間線性插值linearly interpolates箕戳。
例如某残,屏幕上有兩個(gè)不同的點(diǎn)。一個(gè)是y位于左邊0陵吸,另一個(gè)是y位于右邊的20處玻墅。傳入.50
到Math.Lerp
將返回中間的一個(gè)點(diǎn)。
使用三個(gè)參數(shù)調(diào)用Math.Lerp
:它們之間插入的兩個(gè)值壮虫,在本例中為1
和0
澳厢,以及自Hit
動(dòng)畫開始以來的秒數(shù)环础。 Lerp
然后計(jì)算得到的比例。例如剩拢,在0秒時(shí)它將返回1线得,在1秒時(shí)它將返回0,在0.75秒時(shí)它將返回0.25徐伐。
在小丑打擊和投擲蛋糕直到你hit命中 - 小丑縮小贯钩,再也不會再出現(xiàn)。一場短暫的游戲办素!
注意:如果您想知道狀態(tài)機(jī)行為中的其他方法是什么:
OnStateEnter
:在正在播放的狀態(tài)的第一幀上調(diào)用OnStateEnter
角雷。OnStateUpdate
:在每個(gè)幀上更新MonoBehaviors
之后調(diào)用OnStateUpdate
,同時(shí)播放它所附加的行為的狀態(tài)性穿。OnStateExit
:在轉(zhuǎn)換到另一個(gè)狀態(tài)的最后一幀上調(diào)用OnStateExit
勺三。OnStateMove
:只要狀態(tài)正在播放,就會在每個(gè)幀的MonoBehaviors
上調(diào)用OnStateMove
而不是OnAnimatorMove
需曾。OnStateIK
:Unity計(jì)算人形角色的反向運(yùn)動(dòng)學(xué) Inverse Kinematics后調(diào)用OnStateIK
- 例如檩咱,允許它抓取項(xiàng)目。
3. Animation Events: Trigger Code From Your Animation
是時(shí)候讓小丑再次適應(yīng)值班胯舷。 一個(gè)很好的方法是通過Animation Events
,它允許您在動(dòng)畫片段運(yùn)行時(shí)從游戲?qū)ο蟮哪_本中調(diào)用函數(shù)绊含。
首先桑嘶,您需要一個(gè)腳本,其方法可以重置小丑的大小躬充。 在層次結(jié)構(gòu)中選擇小丑逃顶。 在“檢查器”中,滾動(dòng)到底部充甚,然后單擊Add Component
以政。 選擇New Script
并將腳本ResetClown
命名為C Sharp
。 點(diǎn)擊Create and Add
伴找。
在MonoDevelop
中打開ResetClown
腳本并添加以下代碼:
void ResetClownOnHit () {
gameObject.transform.localScale = Vector3.one;
gameObject.GetComponentInChildren<CollisionBehavior> ().collided = false;
}
在此方法中盈蛮,將小丑的localScale
設(shè)置為1
以恢復(fù)其原始大小。 然后使用GetComponentInChildren()
引用Skin
上的CollisionBehavior
并確保其碰撞變量設(shè)置為false
技矮。 如果你省略這一步抖誉,你的小丑仍然會移動(dòng),但不會再對碰撞作出反應(yīng)衰倦。
現(xiàn)在您需要?jiǎng)?chuàng)建一個(gè)調(diào)用此方法的Animation Event
袒炉。 在“層次結(jié)構(gòu)”中選擇“小丑”時(shí)切換到Animation View
,然后選擇Hit
動(dòng)畫片段樊零。 在時(shí)間線中將播放頭設(shè)置為1:30
我磁。 如果您的時(shí)間線在1:00
以后不可見,請使用滾輪將其縮小。 然后單擊Add Event
按鈕夺艰。
雙擊剛剛創(chuàng)建的動(dòng)畫事件的marker
芋哭。
在對話框窗口中,選擇ResetClownOnHit()
劲适。
這將創(chuàng)建一個(gè)動(dòng)畫事件楷掉,在1:30
調(diào)用ResetClownOnHit()
方法。
運(yùn)行游戲霞势。 現(xiàn)在小丑縮小了烹植,然后重新開始并再次開始移動(dòng),準(zhǔn)備再被蛋糕破壞了愕贡!
在本教程中草雕,您可以看到Unity
動(dòng)畫系統(tǒng)的可能性。 但是要知道你還有很多需要學(xué)習(xí)固以,下面是一些閱讀建議:
- 導(dǎo)入使用3D軟件創(chuàng)建的動(dòng)畫Importing animations墩虹,例如
Maya
,Cinema 4D
憨琳,3D Studio Max
或Blender
诫钓。 - 設(shè)置動(dòng)畫層Animation Layers和子狀態(tài)機(jī)Sub-State Machines。
- 使用Blend Trees使轉(zhuǎn)換看起來更平滑
后記
本篇主要講述了Unity動(dòng)畫簡介篙螟,感興趣的給個(gè)贊或者關(guān)注~~~