前言
? ? ? ? hi~ 大家好!歡迎大家來到我的全新unity學(xué)習(xí)記錄系列?,F(xiàn)在我想在2d橫板游戲中,實現(xiàn)一個角色的初始狀態(tài)-閑置狀態(tài)、移動狀態(tài)、空中狀態(tài)。并且是利用狀態(tài)機進行實現(xiàn)的。
? ? ? ? 本系列是跟著視頻教程走的,所寫也是作者個人的學(xué)習(xí)記錄筆記。如有錯誤請聯(lián)系我指正!
觀看教程鏈接:https://www.udemy.com/course/2d-rpg-alexdev/
教程游戲資源鏈接:https://pan.baidu.com/s/1IlUbYlUB0LP0dQfQPkvjZA?
提取碼:0721
目錄
一、Unity和資源準備
二、狀態(tài)機創(chuàng)建和Debug測試
1.有限狀態(tài)機描述
2.有限狀態(tài)機編碼基礎(chǔ)
三、動畫控制器和動畫組件
三、玩家初始狀態(tài)制作
1.玩家閑置和移動狀態(tài)的切換
2.玩家整體的翻轉(zhuǎn)
3.玩家在地面狀態(tài)和跳躍狀態(tài)的切換
碰撞檢測
4.玩家實現(xiàn)二段跳
一、Unity和資源準備
? ? ? ? 下載Unity,制定好程序編輯器,創(chuàng)建2D項目,進入unity編輯器界面。(我使用的版本:2022.3.2f1c1)
? ? ? ? 如上圖所示,如果沒有Console組件(程序控制臺)、Animation(動畫控制、動畫)組件,如下圖展示打開路徑。
? ? ? ? 然后將我們的游戲資源導(dǎo)入(游戲的美術(shù)資源),如下圖:
? ? ? ? 導(dǎo)入成功后,我們可以開始準備制作游戲了。
二、狀態(tài)機創(chuàng)建和Debug測試
1.有限狀態(tài)機描述
? ? ? ? 我一開始就提到了狀態(tài)機。這里的狀態(tài)機指的是unity中的有限狀態(tài)機,我們將使用它來控制接下來角色狀態(tài)的轉(zhuǎn)換。
? ? ? ? 我們從角色狀態(tài)來具體到有限狀態(tài)機有什么作用。
? ? ? ? 閑置狀態(tài)、移動狀態(tài)、跳躍狀態(tài)。角色初始為閑置狀態(tài),我們通過鍵盤上的a和d鍵切換角色的狀態(tài),變?yōu)橐苿訝顟B(tài),在閑置和移動狀態(tài)(地面狀態(tài))中可以通過space切換角色為跳躍狀態(tài),并且在第一段跳躍狀態(tài)中可以切換為二段跳。
? ? ? ? 可以看到,角色的狀態(tài)有一個初始的狀態(tài),并且我們可以隨時的進行切換狀態(tài),切換狀態(tài)是存在條件的。并且一個狀態(tài)實際上存在開始、執(zhí)行、結(jié)束(起始,中間、結(jié)束)的過程,那么切換狀態(tài)時均需要實現(xiàn)這些過程。
? ? ? ? 切換狀態(tài)過程我可以以跳躍距離,比如我們從閑置狀態(tài)切換到跳躍狀態(tài),跳躍狀態(tài)的初始過程就需要我們給予一個向上的速度,持續(xù)過程中不需要。
? ? ? ? 上述描述的其實就是有限狀態(tài)機。做的就是將有限的一些狀態(tài)通過條件決定切換??梢园l(fā)現(xiàn),通過這個,我們實際上就可以完成每個狀態(tài)的獨立??梢韵胂?,如果不存在狀態(tài)機,那么我們在編寫角色狀態(tài)切換時,就需要同時考慮到其他狀態(tài)的情況,比如攻擊時不可移動等,那么隨著新的狀態(tài)加入,我們需要自己寫的限制條件就會越來越多,導(dǎo)致編碼困難。
2.有限狀態(tài)機編碼基礎(chǔ)
? ? ? ? 回到我們的當(dāng)前游戲上。有限狀態(tài)機要完成的是狀態(tài)的切換,我們需要兩個組件:狀態(tài)機(StateMachine)和對應(yīng)的狀態(tài)類型(PlayerState)。另外,我們需要unity中的組件,對他們進行一個調(diào)用,此組件就是Player玩家組件(Player)。
? ? ? ? 括號中就是我們需要進行的C#編程文件。C#是一種面向?qū)ο笳Z言,接下來我們實現(xiàn)狀態(tài)機的過程很多就是用的面向?qū)ο蟮乃枷耄?、繼承、多態(tài))。
[Assets->Script]
? ? ? ? 首先說明一下編碼的目的和基本過程:我們需要通過Player來獲取游戲?qū)ο蟮慕M件,并且能夠在游戲開始時通過其Unity腳本達成每幀調(diào)用(MonoBehaviour)。而我們的狀態(tài)并不需要繼承MonoBehaviour類,也就不會參與到游戲的調(diào)用中(順便也節(jié)約了資源)。另外,狀態(tài)機設(shè)置初始階段和切換狀態(tài)(注意其中的三個過程:開始、中間、結(jié)束)。而Player狀態(tài)則表示我們操作的角色所有狀態(tài)的父類,它不繼承任何類(狀態(tài)機也是),可以通過多態(tài)操作,讓角色狀態(tài)做一些共同的事情(比如隨時檢測玩家的Xspeed水平方向的輸入),這也是多態(tài)的目的。最后在Player中完成對這些狀態(tài)對象的創(chuàng)建,通過狀態(tài)機在update中完成對某一狀態(tài)的隨幀調(diào)用,然后在具體的狀態(tài)中檢測條件完成切換。
? ? ? ? 實際上,有時候狀態(tài)的切換,此狀態(tài)可能時一些狀態(tài)的集合,比如閑置和移動狀態(tài),它們都是在地面上,地面上隨時可以進行跳躍。通過繼承和多態(tài)我們可以隨便完成這些集合切換的要求(多態(tài)->子類對象調(diào)用重寫的方法時會執(zhí)行父類的被重寫函數(shù)方法)
? ? ? ? 利用下面一張圖解釋上面的說法:
? ? ? ? 我們首先創(chuàng)建角色的閑置、移動狀態(tài)(PlayerState的子類),在Player中完成基礎(chǔ)的調(diào)用。代碼如下:
PlayerState
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerSate
{
protected Player player; // 方便調(diào)用游戲中獲取的資源
protected StateMachine stateMachine; // 游戲狀態(tài)機,實現(xiàn)狀態(tài)的切換
protected string stateBoolName; // 狀態(tài)名字 - 和后面游戲?qū)ο蟮膭赢嫏C組件相關(guān)
public PlayerSate(Player _player, StateMachine _stateMachine, string _stateBoolName)
{
player = _player;
stateMachine = _stateMachine;
stateBoolName = _stateBoolName;
}
// 開始狀態(tài)
public virtual void Enter()
{
}
// 中間狀態(tài)
public virtual void Update()
{
}
// 退出狀態(tài)
public virtual void Exit()
{
}
}
StateMachine
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class StateMachine
{
public PlayerSate currentState { get; private set; } // 想讓外界訪問,但是不允許修改
// 初始狀態(tài)
public void Initialize(PlayerSate _startState)
{
currentState = _startState;
currentState.Enter(); // 啟動開始階段
}
// 轉(zhuǎn)換狀態(tài)
public void ChangeState(PlayerSate _newState)
{
currentState.Exit(); // 前一個狀態(tài)先退出
currentState = _newState;
currentState.Enter(); // 執(zhí)行開始階段
}
}
Player?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
#region Component
private StateMachine stateMachine;
#endregion
#region State
// C#語法,可以整理段落
public PlayerIdleState idleState { get; private set; } // 后續(xù)在狀態(tài)中可能會調(diào)用到,但是不希望被修改
public PlayerMoveState moveState { get; private set; }
#endregion
// 初始化變量
private void Awake()
{
stateMachine = new StateMachine();
idleState = new PlayerIdleState(this, stateMachine, "Idle");
moveState = new PlayerMoveState(this, stateMachine, "Move");
}
void Start()
{
stateMachine.Initialize(idleState); // 一開始為閑置狀態(tài)
}
void Update()
{
stateMachine.currentState.Update(); // 多態(tài)調(diào)用 父類對象調(diào)用重寫方法,實現(xiàn)同種類型展示出不同的效果
}
}
? ? ? ? 然后我們在Unity層次界面內(nèi)創(chuàng)建空對象,將Player腳本掛接上去。這樣游戲加載時就能加載Player腳本代碼。點擊游戲窗口,敲f鍵時觀察代碼控制臺,查看狀態(tài)的切換。
? ? ? ? 注意紅色標注,按此時控制臺顯示的重復(fù)信息會顯示成數(shù)字置于消息框右下角,避免刷屏。
? ? ? ? 另外,在腳本編輯過程中,子類生成虛函數(shù)和構(gòu)造函數(shù)時,點擊選中當(dāng)前類名,alt + enter鍵可以快速構(gòu)造:
? ? ? ? 可以看到,此時我們的腳本已經(jīng)可以完成基礎(chǔ)的轉(zhuǎn)換的演示,那么我們讓它實際運行起來,展示對玩家基礎(chǔ)狀態(tài)的演示。
三、動畫控制器和動畫組件
? ? ? ? 在正式制作之前,先介紹一下Unity內(nèi)的動畫組件。窗口的創(chuàng)建先前布局時已經(jīng)說過,其中Animator就是動畫控制器,在這里可以制作動畫切換條件,動畫順序等。那么在動畫控制之前,我們還需要一段一段的動畫,通過Animation進行控制(將美術(shù)資源中的動畫一張一張連續(xù)播放出來)。
? ? ? ? 我們在美術(shù)資源中找到角色精靈圖:
? ? ? ? 在此精靈圖中,實際上已經(jīng)都切分好了,這里簡單介紹一下如何切分精靈圖的(本質(zhì)是由一張一張的圖組合而成,到Unity中進行切分而已)
? ? ? ? 模式中我們選中Multiple多個模式,選擇圖片編輯器(Sprite Editor)進行編輯
? ? ? ? 在如何切分中我們可以選擇三種進行切分,看好如何切分,這也和美術(shù)資源整理時相關(guān),盡量每張子圖一致,Point表示這張圖的支點(有時圖片不一致時利用此存在對齊的效果)。切分好后按apply進行應(yīng)用。
? ? ? ? 應(yīng)用完后,Pixels Per?Unit表示單位像素數(shù),在此可以設(shè)計圖片大小......
? ? ? ? 我們將其中一張閑置圖片拖到場景界面上,此時Unity會為我們默認創(chuàng)建一個對象(命名為Animator),將其掛載在Player對象下成為子對象,調(diào)整子對象的距離,將我們父對象的中心點對號角色對象的中心點。
? ? ? ? 為Animator組件添加?Animator組件,其就是動畫控制的組件,另外此對象為空,我們需要在文件中進行創(chuàng)建不同的動畫控制對象,以便不同的對象控制不同的狀態(tài)動畫。
上圖為創(chuàng)建玩家控制器的過程(可以利用文件夾進行分類)
? ? ? ? 將對象托拽到玩家子對象Animator組件Animator上去,在選擇此對象的狀態(tài)的條件下查看動畫控制窗口(Animator)就可以看到如下圖:
? ? ? ? 這個就很容易看出和我們的狀態(tài)機對應(yīng)的關(guān)系,但是存在一個任意狀態(tài)。也就是說,在沒有狀態(tài)機的條件下我們也可以進行創(chuàng)作角色狀態(tài)轉(zhuǎn)換,只不過互相之間的制約需要玩家自己控制,非常麻煩。
? ? ? ? 最后在看一下某一段動畫編輯。選中玩家動畫控制器的情況下,點擊下圖中的Create就可以創(chuàng)建一段動畫序列。
? ? ? ? 將角色一段閑置動畫序列拖進此窗口,在此窗口的右邊三小點上選擇Show Sample Rate來控制動畫的播放速度。
?
可以像上圖那樣觀察角色動畫狀態(tài)。
? ? ? ? 移動類似創(chuàng)建。這樣在動畫控制窗口我們可以創(chuàng)建條件來決定動畫狀態(tài)的切換了。其中右鍵角色狀態(tài),選擇make transition創(chuàng)建動畫過渡連線,在右邊窗口的Animation的+創(chuàng)建條件,因為狀態(tài)機的切換與Player組件掛鉤使用通用的Bool,所以創(chuàng)建兩個條件Idle和Move作為切換條件。點擊連線選擇條件切換,控制前后兩端動畫的退出狀態(tài)和過度狀態(tài),這里兩個切換我們均不設(shè)置退出時間和轉(zhuǎn)換持續(xù)時間。
?????????就這樣,對動畫序列和動畫控制的基本了解到此結(jié)束,需要更詳細的了解請前去學(xué)習(xí)。
三、玩家初始狀態(tài)制作
? ? ? ? 首先,我們需要在player玩家腳本上獲取角色的動畫控制組件(以便設(shè)置條件為true控制動畫的播放),每次在切換或者初始狀態(tài)的時對條件進行控制(公共操作,在父類上進行)。另外,我們需要我們的角色擁有重力,所以需要Unity中的組件Rigidbody 2D對玩家進行基本的物理控制。所以對Player(注意獲取的組件還存在子類的組件)腳本和PlayerState腳本的修改如下:
player:
PlayerState:
? ? ? ? 設(shè)置玩家物理控制組件的基本狀態(tài):
? ? ? ? 禁止Z軸旋轉(zhuǎn)(這和我們重力下降相關(guān)),同時需要調(diào)整參數(shù)插值和重力檢測為連續(xù)。(因為重力元素,作用到碰撞器上后,角色由于形狀因素,由于是2D平面,導(dǎo)致z軸旋轉(zhuǎn)讓其倒下)
? ? ? ? 然后創(chuàng)建一個簡單平臺,增加角色和平臺的碰撞器(存在碰撞器才能發(fā)生碰撞以及檢測)。需要注意碰撞器的類型和2D狀態(tài)。效果如下:
? ? ? ? ?初始狀態(tài)研究完畢,開始游戲我們就會看到玩家角色掉落,并且不會發(fā)生圖片z軸翻轉(zhuǎn)。
1.玩家閑置和移動狀態(tài)的切換
? ? ? ? 動畫序列和動畫控制我們在之前的步驟已經(jīng)完成,現(xiàn)在我們只需要在腳本里進行控制即可實現(xiàn)此狀態(tài)的切換。
? ? ? ? 由于狀態(tài)機初始狀態(tài)就是閑置狀態(tài),一開始我們角色就應(yīng)該播出閑置動畫。在閑置的動畫狀態(tài)類里,由于此時狀態(tài)是此,在游戲?qū)ο蟮碾S幀Update調(diào)用中,當(dāng)我們檢測到玩家按下了a和d鍵(Unity中存在Horizontal對AD的檢測,使用方法GetAxis進行檢測即可)時,應(yīng)該從閑置狀態(tài)切換到移動狀態(tài)。但是即然存在移動,我們就需要方向上的確定,獲取的ad狀態(tài)存在方向,由于多種狀態(tài)需要此值,可以設(shè)計xSpeed檢測方向于PlayerState上。
? ? ? ? 移動狀態(tài)需要進行移動,我們通過Player腳本獲取其腳本進行速度位移。但是速度位移的很多狀態(tài)下都需要進行控制,我們將其方法設(shè)計到Player下,形參傳遞x和y方向上的速度即可。初始和中間過程均需要維持速度。當(dāng)檢測到xSpeed為0時,移動狀態(tài)應(yīng)該轉(zhuǎn)換為閑置狀態(tài),并且閑置狀態(tài)的速度應(yīng)該為0,所以在閑置狀態(tài)的開始狀態(tài)速度設(shè)置為0。
? ? ? ? 由于我們需要能夠在Unity中自由控制玩家的速度,在Player聲明空開變量MoveSpeed來控制角色位移速度。?
? ? ? ? 腳本編寫:
Player:
?
PlayerState:
PlayerIdleState:?
PlayerMoveState:
? ? ? ? 我們試著運行一下:
? ? ? ? 可以看到我們實現(xiàn)了角色閑置狀態(tài)和移動狀態(tài)的切換。但是此時發(fā)現(xiàn)一個bug,角色圖片只有向右的動畫,沒有向左的動畫,需要重寫制作動畫設(shè)置條件嗎?并不需要,我們利用腳本就可以控制。?
2.玩家整體的翻轉(zhuǎn)
? ? ? ? 我們是不是只需要角色在往左移動的時候?qū)⒔巧w向左翻轉(zhuǎn)即可?
? ? ? ? 那么我們只需要控制角色方向切換移動時能夠進行控制翻轉(zhuǎn),而我們輸入的xSpeed正好可以管控角色輸入的方向。但是需要注意,翻轉(zhuǎn)時比如x<0向左翻轉(zhuǎn),但是必須控制當(dāng)前情況需要為向右的狀態(tài),如果本來是向左的狀態(tài)那么翻轉(zhuǎn)就失敗了。
? ? ? ? 控制是否左右的變量我們設(shè)置在Player(isRight bool),并且為了之后的碰撞檢測線的翻轉(zhuǎn)問題,我們留下positionDir指定玩家-1為左移動,1為右移動。初始均為右移動。因為翻轉(zhuǎn)是隨時的,并且在改變速度時才可翻轉(zhuǎn),那么我們設(shè)置在Player上的意義又多了一個。將Dir設(shè)置為公開,isRight設(shè)置為私有并且為true。start時檢測外界是否修改,修改需要設(shè)置對應(yīng)false。這樣翻轉(zhuǎn)才正確。
Player:
修改上述文件即可,我們查看效果即可。?
3.玩家在地面狀態(tài)和跳躍狀態(tài)的切換
? ? ? ? 在之前的狀態(tài)機中我們已經(jīng)談過,我們處于地面狀態(tài)時(移動和閑置),均可以進行跳躍。利用類與對象基礎(chǔ)的關(guān)系,我們床在移動和閑置類的父類,玩家狀態(tài)類的子類,由此地面類進行控制玩家從地面狀態(tài)到跳躍狀態(tài)的切換。
? ? ? ? 跳躍狀態(tài)在一開始需要一個向上的速度,我們需要空開jump跳躍數(shù)據(jù)進行控制。但是跳躍狀態(tài)存在兩種動畫:向上跳動畫+向下跳動畫。那么我們?nèi)绾慰刂七@兩種動畫的切換呢?
? ? ? ? 首先通過動畫序列創(chuàng)建向上跳和向下跳的動畫序列(之前的資源進行尋找)。然后在動畫控制界面我們做一點不一樣的事情,此時條件變成了一個float數(shù),從1到-1.我們通過創(chuàng)建混合樹的方式,控制角色在空中時的狀態(tài):
? ? ? ? 然后玩家跳躍后在PlayerState可為其添加角色下落速度方向為其修改(整個空中狀態(tài))。
? ? ? ? 因為此時為狀態(tài)樹模式,我們控制的狀態(tài)在同一時刻存在一種狀態(tài),所以常見的無限跳bug也解決了,但是玩家落地的時候如何判定為落地狀態(tài)呢?能只是簡單的判斷y方向上為0嗎?比如玩家滑行模式中(fly?)y方向速度為0不應(yīng)該為閑置狀態(tài),我們需要的是碰撞檢測。
碰撞檢測
? ? ? ? 我們需要實現(xiàn)一個地面碰撞檢測,為了方便后續(xù),我們同步實現(xiàn)墻體檢測(滑墻和登墻跳操作)。
? ? ? ? 地面檢測我們通過Unity的Physics2D中的Raycast向量檢測進行。此函數(shù)能夠在空間中確定一個從起點到上、下、左、右方向的距離的一個向量,并且可指定layerMask(層級蒙版)來檢測特定的layer,當(dāng)此向量檢測到存在對應(yīng)的碰撞體時,就會返回相應(yīng)個數(shù)(實際我們只需要知道碰撞到即可)
? ? ? ? 墻面檢測類似。那么我們想要將其形象化的表示出來才能進行更好的調(diào)節(jié)參數(shù)。表示出來我們可以使用Gizmos中的DrawLine功能,就能進行繪畫向量,由起始和終點位置決定。并且為了更好的進行調(diào)節(jié)實現(xiàn),起點位置的GameObject可以公開出去,這樣我們可以自由決定檢測的起始位置。
? ? ? ? 另外,你是否存在這種想法:玩家跳躍時表明一個狀態(tài)即可,墻體檢測IsGroundCheck隨時在update。是的,如果只是維持一個文件表明此跳躍空中狀態(tài)的化,由于初始給予向上速度和IsGroundCheck可能重疊,導(dǎo)致跳躍失敗的情況出現(xiàn)。(可自行測試)
? ? ? ? 綜上,我們的設(shè)計思路如下:(分成兩個文件表示跳躍的上跳和下跳也和之后的實現(xiàn)相關(guān))
?代碼整理:
? ? ? ? 首先文件確定如下:
? ? ? ? PlayerAirState文件表示空中狀態(tài),為PlayerJumpState和PlayerFallState的父類,能執(zhí)行一些共同的事情,比如update檢測YDir,空中能隨時的確定x速度和方向,后續(xù)的多段跳功能。JumpState表示上跳過程,Enter給予向上的速度,Player腳本設(shè)計JumpSpeed確定數(shù)值。update只需檢測如果玩家剛體速度小于0進行切換到下落狀態(tài)。FallState表示下落過程,注意Update檢測是否地面碰撞。(分開的主要原因錯開初始向上速度和地面檢測重疊一起,導(dǎo)致跳躍失?。?/p>
? ? ? ? Player文件new上述狀態(tài),并且提供Draw方法和向量檢測,暴露一些屬性決定位置和數(shù)值大小。
Player:
?
PlayerAirState:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerAirState : PlayerState
{
public PlayerAirState(Player _player, StateMachine _stateMachine, string _stateBoolName) : base(_player, _stateMachine, _stateBoolName)
{
}
public override void Enter()
{
base.Enter();
}
public override void Exit()
{
base.Exit();
}
public override void Update()
{
base.Update();
player.SetVelocity(xDir * player.moveSpeed, player.rb.velocity.y);
// 隨時控制跳躍的上跳和下躍狀態(tài)
player.animator.SetFloat("YDir", player.rb.velocity.y);
}
}
?PlayerJumpState:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerJumpState : PlayerAirState
{
public PlayerJumpState(Player _player, StateMachine _stateMachine, string _stateBoolName) : base(_player, _stateMachine, _stateBoolName)
{}
public override void Enter()
{
base.Enter();
// 初始給玩家一個向上跳的動作
player.SetVelocity(player.rb.velocity.x, player.jumpSeed);
}
public override void Exit()
{
base.Exit();
}
public override void Update()
{
base.Update();
if (player.rb.velocity.y < 0) stateMachine.ChangeState(player.fallState);
}
}
PlayerFallState:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerFallState : PlayerAirState
{
public PlayerFallState(Player _player, StateMachine _stateMachine, string _stateBoolName) : base(_player, _stateMachine, _stateBoolName)
{
}
public override void Enter()
{
base.Enter();
}
public override void Exit()
{
base.Exit();
}
public override void Update()
{
base.Update();
// 地面檢測,如果碰撞到了地面,轉(zhuǎn)換為閑置狀態(tài)
if (player.IsGroundCheck()) stateMachine.ChangeState(player.idleState);
}
}
?Player中地面和墻體檢測表現(xiàn)效果:
4.玩家實現(xiàn)二段跳
? ? ? ? 那么我們要實現(xiàn)二段跳如何實現(xiàn)?設(shè)想一下,是不是我們只要能在跳躍狀態(tài)中在檢測一下空格鍵,轉(zhuǎn)換為跳躍狀態(tài)是否就能實現(xiàn)多段跳功能?
? ? ? ? 但是只是上述那個條件,就可以造成無限跳了。為了限制為2段跳,我們不妨設(shè)計一個計數(shù)器,記錄為2個,每往上跳一次--,落地時恢復(fù)為2,在空中狀態(tài)中按下空格鍵時檢測計數(shù)器是否>0即可。那么此計數(shù)器必須在狀態(tài)切換時始終唯一,所以該變量就設(shè)在Player中去,Jump文件控制--,F(xiàn)all文件確定恢復(fù)。雙段跳就可以簡單的實現(xiàn)出來了:
Player:
PlayerAirState:
?
?PlayerJumpState:
PlayerFallState:
?
實際效果:
?文章來源:http://www.zghlxwxcb.cn/news/detail-762483.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-762483.html
到了這里,關(guān)于【unity】制作一個角色的初始狀態(tài)(左右跳二段跳)【2D橫板動作游戲】的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!