動(dòng)態(tài)網(wǎng)站開(kāi)發(fā)工程師—aspseo一鍵優(yōu)化
最終效果
前言
我們要實(shí)現(xiàn)的功能是雙擊疾跑,當(dāng)玩家快速地按下同一個(gè)移動(dòng)鍵兩次時(shí)能進(jìn)入跑步狀態(tài)
我假設(shè)快速按下的定義為0.2秒內(nèi),按下同一按鍵兩次
簡(jiǎn)單的分析一下需求,實(shí)現(xiàn)它的關(guān)鍵在于獲得按鍵按下的時(shí)間,我們需要知道第一次按下按鍵的時(shí)間,然后判斷規(guī)定時(shí)間內(nèi)有沒(méi)有按下按鍵
有兩種實(shí)現(xiàn)方法
第一種
啟動(dòng)一個(gè)計(jì)時(shí)器,判斷在計(jì)時(shí)器結(jié)束之前有沒(méi)有再次按下這個(gè)鍵
第二種
是分別記錄下兩次按鍵的時(shí)間,然后用第二次按下的時(shí)間減去第一次按下的時(shí)間,判斷是否小于0.2
這里我采用第二種方法,為了獲取按下的時(shí)間,我們需要使用到Unity給我們提供的Time類,里面的Time.time會(huì)提供游戲啟動(dòng)到現(xiàn)在運(yùn)行了多少秒,這個(gè)需求還需要我們檢測(cè)到按鍵是否被按下,我打算使用Input Manager來(lái)實(shí)現(xiàn)
public static float GetAxis (string axisName);
public static float GetAxisRaw(string axisName);
GetAxisRaw會(huì)在檢測(cè)到按鍵后,馬上返回1或-1,松開(kāi)按鍵后馬上變成0
而GetAxis會(huì)在檢測(cè)到按鍵的時(shí)候,從0過(guò)渡到1或-1,松開(kāi)按鍵后再過(guò)渡到0
為了方便,我使用GetAxisRaw來(lái)獲得輸入的時(shí)間,當(dāng)按鍵按下時(shí)意味著GetAxisRaw的返回值為1的絕對(duì)值,我們?cè)诜蠗l件的時(shí)候使用Time.time來(lái)獲得當(dāng)前的時(shí)間即可
但顯然,我們不希望玩家按下a后馬上按下d,還能讓人物進(jìn)入到疾跑狀態(tài),所以兩個(gè)按鍵的輸入時(shí)間要分開(kāi)存儲(chǔ),還有一個(gè)需要注意的地方是,當(dāng)玩家開(kāi)始走路或疾跑時(shí),a鍵或d鍵是按住不放的,所以當(dāng)玩家在移動(dòng)的時(shí)候,我們要使個(gè)bool變量為真,當(dāng)這個(gè)變量為真時(shí),就不再刷新輸入的時(shí)間
我們?cè)O(shè)想一下,玩家進(jìn)入游戲以后,馬上按下了一次移動(dòng)鍵,如果他電腦開(kāi)游戲開(kāi)的特別的快,他第一次按下移動(dòng)鍵的時(shí)間,離打開(kāi)游戲不到0.2秒,如果我們存儲(chǔ)按鍵時(shí)間的變量,沒(méi)有初始化,那么會(huì)默認(rèn)賦值為0,當(dāng)他第一次按下移動(dòng)時(shí),就會(huì)進(jìn)入到疾跑狀態(tài),這很明顯是我們不想要看到的bug
所以最后一個(gè)要點(diǎn)是給存儲(chǔ)按鍵時(shí)間的變量進(jìn)行初始化,但初始化的只要賦值為多少也是一個(gè)值得考慮的問(wèn)題,如果賦值為一個(gè)極大的正數(shù),就算賦值為1萬(wàn),萬(wàn)一玩家一開(kāi)始在掛機(jī)剛好在10,000.01秒,按一下移動(dòng)按鍵,還是會(huì)錯(cuò)誤地進(jìn)入到疾跑狀態(tài),所以可以給他賦值為,負(fù)的最大等待輸入時(shí)間,如果實(shí)在不放心,可以賦值為2倍,這樣第一次輸入就不會(huì)出現(xiàn)bug
經(jīng)過(guò)了這么多的分析,相信你此時(shí)此刻已經(jīng)完全明白了,接下來(lái)我們進(jìn)入到代碼實(shí)戰(zhàn)環(huán)節(jié)
開(kāi)始
配置動(dòng)畫(huà),walk為true進(jìn)入走路動(dòng)畫(huà),run為true進(jìn)入跑步動(dòng)畫(huà)
public class PlayerController : MonoBehaviour
{private Rigidbody2D rb;private Animator animator;public float maxAwaitTime;private float leftPressTime, rightPressTime;private bool moving, canRun;public int walkSpeed, runSpeed;private int currentSpeed;private float h;private void Awake(){rb = GetComponent<Rigidbody2D>();animator = GetComponent<Animator>();leftPressTime = rightPressTime = -maxAwaitTime;}private void Update(){h = Input.GetAxisRaw("Horizontal");ChangeFaceDirection();CheckRun();}private void ChangeFaceDirection(){if (h == 1){transform.localScale = new Vector3(1, 1, 1);}else if (h == -1){transform.localScale = new Vector3(-1, 1, 1);}}private void CheckRun(){if (h == 1 && !moving){if (Time.time - rightPressTime <= maxAwaitTime){canRun = true;}rightPressTime = Time.time;}if (h == -1 && !moving){if (Time.time - leftPressTime <= maxAwaitTime){canRun = true;}leftPressTime = Time.time;}//取 h 的絕對(duì)值if (Mathf.Abs(h) == 1){moving = true;if (canRun){currentSpeed = runSpeed;animator.SetBool("run", true);}else{currentSpeed = walkSpeed;animator.SetBool("walk", true);}}else{animator.SetBool("run", false);animator.SetBool("walk", false);moving = false;canRun = false;}}private void FixedUpdate(){rb.velocity = new Vector2(h * currentSpeed * Time.deltaTime, rb.velocity.y);}
}
效果
參考
【視頻】https://www.bilibili.com/video/BV1YN4113771/
完結(jié)
贈(zèng)人玫瑰,手有余香!如果文章內(nèi)容對(duì)你有所幫助,請(qǐng)不要吝嗇你的點(diǎn)贊評(píng)論和關(guān)注
,以便我第一時(shí)間收到反饋,你的每一次支持
都是我不斷創(chuàng)作的最大動(dòng)力。當(dāng)然如果你發(fā)現(xiàn)了文章中存在錯(cuò)誤
或者有更好的解決方法
,也歡迎評(píng)論私信告訴我哦!
好了,我是向宇
,https://xiangyu.blog.csdn.net
一位在小公司默默奮斗的開(kāi)發(fā)者,出于興趣愛(ài)好,于是最近才開(kāi)始自習(xí)unity。如果你遇到任何問(wèn)題,也歡迎你評(píng)論私信找我, 雖然有些問(wèn)題我可能也不一定會(huì),但是我會(huì)查閱各方資料,爭(zhēng)取給出最好的建議,希望可以幫助更多想學(xué)編程的人,共勉~