日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

用 Unity 探究 2D 游戏的打击感

發布時間:2024/8/26 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 用 Unity 探究 2D 游戏的打击感 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

引言

這是我畢業設計的一部分emmm……我的畢設和格斗游戲相關,而對于打擊感的研究算是其中我比較在意的一環。現在臨近畢業,我將畢設中開發部分的一些內容整理出來分享,希望能通過這樣學習到更多的東西。

打擊感為何物?

字面意思,“打到了的感覺”;好的打擊感是易讀的,包含信息充足的;它可以讓玩家感受到這次的攻擊奏效了、這次攻擊的輕重程度、感受到這是怎樣的攻擊。在電子游戲中,則通過視覺和聽覺呈現這些。

實現方式

市面上已經有很多作品供我們參考,讓我自己想出一個獨特的實現方式如同天方夜譚,不過我喜歡參照已有作品,去探究他們如何實現。

1)幀凍結(頓幀)

頓幀已經是司空見慣的手段,也是目前最常見的表現打擊感的方式。它會讓角色動畫停止在那里,讓玩家意識到發生了什么,接著再繼續播放動畫。我認為所有的打擊感幾乎都有這個東西,只不過可能有些幀凍結的時間設置,讓人很難用肉眼察覺到。在《街霸4》中,擊中時普遍的頓幀時間為:攻擊角色頓14/60幀≈0.23秒,受擊角色頓16/60幀≈0.26秒,是我見過最長的。

一般情況下,頓幀的時間不會超過0.3秒,除非是做特殊的效果處理,因為超過0.3秒這個圖像在玩家眼里會變得非常突出,顯得較為奇怪。通常程度越重的攻擊頓幀的時間也越長,而這也需要適當的動作設計,比如較長時間的出手準備動作能讓玩家對這次攻擊有一個“很重”的預期。

2)擊退距離

除非有特殊需求,不然大多數游戲在攻擊后,雙方角色之間的距離一定會產生變化。這是非常容易表現一個攻擊輕重程度的方式。

頓幀+擊退是我認為最主要的兩個方式,運用這兩者,即可實現最基本的打擊感。那么在這基礎上,可以添加一些“特效”來使它更加充實。

3)特效

可以有很多種,我認為這些就像是在打擊感上加花,使它更加豐滿。我通過總結,列舉了一些常見手段:

1.打擊火花(HitFire):攻擊奏效時在特定位置創建。需要注意畫風適當,風格對應;斬擊有斬擊的樣式,拳擊有拳擊的樣式,重攻擊應該比輕攻擊的火花更大更飽和等等。

2.精靈(Sprite)抖動:我們在很多游戲里可能都會看到,當角色受到攻擊時,幀凍結期間角色的圖片(Sprite)也在顫動,顫動的方式有多種,水平及垂直方向的,或是虛影向外擴張的(我不知道那種形式該怎么表述)。但這僅限于視覺上的抖動,該抖動不會有任何邏輯上的影響,比如角色的物理坐標,判定框這些均不會隨著精靈的抖動而改變。

3.屏幕震動:很多游戲都會通過震屏來彰顯一次攻擊的沖擊力,震屏的方式以及怎樣去表現不同的攻擊,這值得研究。

4.顏色變化:有些動作游戲會讓角色在受擊的時候,身體顏色產生變化,大多是在那一瞬間,身體閃一下相應顏色,紅色和白色較為常見。這會讓玩家更容易讀出角色正在挨打這件事。

本次畢設我主要采取了幀凍結+擊退+精靈抖動+打擊火花的組合進行實現。

下面是在Unity中的應用:

1.HitBox與HurtBox的搭建

先簡單說下我對游戲中攻擊和受擊的實現吧。
?


我的角色總共有3種攻擊方式,而我為每一種攻擊方式在角色下面都創建了一個子物體;
?


每一個攻擊子物體,都有他們對應的BoxCollider2D(IsTriiger)來代表他們的攻擊判定,同理,HurtBox也一樣。

我用Animator的幀事件控制每個攻擊動作開啟攻擊判定的時機和位置。
?

  • private void OnTriggerEnter2D(Collider2D collision)
  • {? ?? ?
  • ??if(collision.tag == "Hurt2")
  • ??{? ?? ?
  • ??}? ?
  • }
  • 復制代碼


    我會在OnTriggerEnter2D函數里面實現攻擊需要發生的事情,若攻擊物體碰到了標簽為“Hurt2”(2P的受擊判定框)的物體時,攻擊便發生了。

    2.邏輯流程

    在討論實現之前,我想先梳理一下邏輯流程,先是攻擊角色的流程:
    ?

    • 首先,在Hitbox與HurtBox重疊時,我們會判定為攻擊奏效,此時我會優先處理的是關閉HitBox,因為我不希望攻擊事件重復發生,避免一些麻煩;
    • 之后是“頓幀”,我通過控制動畫播放速度,使速度為0來實現這一功能;
    • 接著我們需要記錄下角色當前的速度(X軸和Y軸),因為接下來我們要鎖定角色的位移了,在幀凍結期間,我們不希望角色的位置仍在變化;
    • 創建火花特效,創建的位置我希望是在判定框相交區間的中心位置;
    • 頓幀結束,恢復動畫播放;
    • 恢復角色之前被記錄的速度,若本次攻擊是空中攻擊,那么這之后角色會繼續下落了;



    ?對角色施加對應方向的力,以達到擊退的效果,手機靚號交易平臺也可以是垂直方向的力,達到浮空或強DOWN之類的效果。

    那么總結下來,流程就是:

    關閉HitBox→停止動畫播放→記錄當前速度→鎖定角色的X軸Y軸→創建火花→恢復動畫播放→恢復角色速度→施加力(擊退)

    對于受擊角色來說也是類似,不過會多出一個抖動的效果,并且不用記錄角色速度:

    進入受擊動畫→停止動畫播放(此時應處于受擊動畫的第一幀)→處理精靈抖動(抖動時間應小于頓幀時間)→恢復動畫播放→施加力

    好的,整理完了流程,可能在講實現方式的時候思路會更清晰一些。

    3.幀凍結的實現

    我通過控制Animator的播放速度和Invoke函數這兩者結合來實現幀凍結這一功能。

  • public float HitStop_AS = 1;
  • public float HitStop_AO = 1;
  • public float HitStop_DS = 1;
  • public float HitStop_DO = 1;
  • void Start () {? ?? ?
  • ??HitStop_AS = HitStop_AS / 60;? ?? ???
  • ??HitStop_AO = HitStop_AO / 60;? ?? ?
  • ??HitStop_DS = HitStop_DS / 60;? ?? ?
  • ??HitStop_DO = HitStop_DO / 60;
  • }
  • private void OnTriggerEnter2D(Collider2D collision){? ?
  • ??if(collision.tag == "Hurt2")
  • ??{? ???
  • ? ? gameObject.GetComponent<Animator>().speed = 0;? ?
  • ? ? Invoke("AnimPlay", HitStop_AS);? ?? ?
  • ??}
  • }
  • void AnimPlay() {
  • ??gameObject.GetComponent<Animator>().speed = 1;
  • }
  • 復制代碼


    Invoke可以讓規定的函數在規定時間后啟動,而我在Invoke函數中使用的HitStop_AS參數就是攻擊擊中后攻擊角色自身的幀凍結時間,這里的參數需要以秒為單位。

    在定義變量時,HitStop這一類參數是以幀為單位定義的,在public之后我可以在Unity界面中很方便的以幀的概念進行調節,在游戲開始時,便會通過Start()里面的指令轉化為秒單位。

    我創建了名為HitStop的腳本,這些都是寫在那個腳本里的,而我會給每個攻擊子物體都套上這個腳本,這樣每一個攻擊招式都具備這些模板一樣的變量了。對此我進行了一系列的總結。

    表1攻擊招式應具備的模板屬性

    屬性備注

    動畫總幀/anim完整攻擊動畫的幀數;不可調整

    發生/A概念變量,攻擊判定產生前的幀數;可調整

    攻擊持續/KA概念變量,攻擊判定持續存在的幀數;可調整

    擊中時的頓幀/HitStop_AS擊中時自身動畫停止播放的幀數;可調整

    被擊中者的頓幀/HitStop_AO被擊中者動畫停止播放的幀數;可調整

    被防時的頓幀/HitStop_DS被防御時自身動畫停止播放的幀數;可調整

    防御者的頓幀/HitStop_DO防御者動畫停止播放的幀數;可調整

    表2受擊方相關屬性

    屬性備注

    受擊動畫總幀/anim_o完整受擊動畫的總幀數;不可調整

    防御動畫幀/anim_d完整防御動畫的總幀數;大多情況下防御動畫都是一張同樣的圖持續多幀;不可調整

    表3其他相關屬性

    屬性備注

    黃金受擊幀/zhexue受擊頓幀結束后,受擊動畫至少要播放的幀數。即這個幀數會讓玩家明確的感受到第二次攻擊生效了;想達到這個效果,夸張的受擊動畫設計是必要的,動作幅度越大,感受就越直觀;目前還沒有一個明確的答案能解釋多少幀合適,但動作改變幅度明顯即可。

    連招間歇幀/ComboBreak攻擊者的第一招命中后,輸入可以形成連招的第二招之前允許玩家間隔的最大幀
    ?


    這里有很多是我自己總結的一些概念,像是一些公式也只是出于玩家視角理解的知識進行總結;格斗游戲現在已經發展成了“電子競技”,對于玩家來說,“有利幀”“不利幀”這些都已成為了必修功課,所以我認為這些也有必要列入到設計工作當中,而這些公式或許能幫助我在開發中提供更多的便利,僅供參考。

    4.打擊火花的創建

    先前我使用了從不同游戲中的拿過來的美術素材進行實驗,畫風的不統一會讓人覺得很不舒服,因為這是最直觀的感受,所以我后來挑了一整套同一個游戲的素材,效果好多了。

    我認為,合適的火花特效非常重要。同時,特效創建的位置也應合理,我希望火花創建在HitBox與HurtBox相交區間的中心處。

    為此,我自定義了一個二維向量,用來計算相交區間的中心坐標:
    ?

  • Vector2 hit(BoxCollider2D self, BoxCollider2D oppo)
  • {
  • ??Vector2 hit = new Vector2(1,1);
  • ??//===============判定框的中心坐標=====================================
  • ??float self_pos_x = transform.position.x + self.offset.x;
  • ??float self_pos_y = transform.position.y + self.offset.y;
  • ??float oppo_pos_x = Player2_Hurt.transform.position.x + oppo.offset.x;
  • ??float oppo_pos_y = Player2_Hurt.transform.position.y + oppo.offset.y;
  • ??if (self_pos_y + self.size.y/2 >= oppo_pos_y + oppo.size.y / 2)
  • ??{
  • ? ? if(self_pos_y - self.size.y/2 <= oppo_pos_y - oppo.size.y / 2)
  • ? ? {
  • ? ?? ?hit = Player2.transform.GetChild(0).gameObject.transform.position;
  • ? ? }
  • ? ? else
  • ? ? {
  • ? ?? ?hit = new Vector2(Player2.transform.GetChild(0).gameObject.transform.position.x, (self_pos_y - self.size.y / 2) + ((oppo_pos_y + oppo.size.y / 2) - (self_pos_y - self.size.y / 2)) / 2);
  • ? ? }
  • ??}
  • ??else if (self_pos_y + self.size.y / 2 < oppo_pos_y + oppo.size.y / 2)
  • ??{
  • ? ? if(self_pos_y - self.size.y / 2 >= oppo_pos_y - oppo.size.y / 2)
  • ? ? {
  • ? ?? ?hit = new Vector2(Player2.transform.GetChild(0).gameObject.transform.position.x, self_pos_y);
  • ? ? }
  • ? ? else if (self_pos_y - self.size.y / 2 < oppo_pos_y - oppo.size.y / 2)
  • ? ? {
  • ? ?? ?hit = new Vector2(Player2.transform.GetChild(0).gameObject.transform.position.x, (self_pos_y + self.size.y / 2) - ((self_pos_y + self.size.y / 2) - (oppo_pos_y - oppo.size.y / 2)) / 2);
  • ? ? }
  • ??}
  • ??return hit;
  • }
  • 復制代碼



    之后通過Instantiate()函數在OnTriggerEnter2D()中實現創建的功能。

    5.精靈抖動

    角色sprite的抖動僅限于視覺上,角色的物理坐標不會隨著抖動而變化。為了實現這一邏輯,我在sprite物體上創建了一個父物體,而角色的物理BoxCollider以及RigidBody等組件都會套在這個父物體上。
    ?


    父物體的運動會影響到子物體,但子物體的運動不會影響父物體,這樣在Sprite抖動的時候就不會影響到物理判定框了。
    ?

  • public float A = 1;
  • public float speed = 1;
  • float x = 0;
  • bool swag = false;
  • if (swag){
  • ??x = x + speed * Time.deltaTime;
  • ??this.transform.position = new Vector3(transform.parent.gameObject.transform.position.x + A * Mathf.Cos(x), transform.position.y, transform.position.z);
  • }
  • 復制代碼


    我為此定義了3個變量,A為抖動的振幅,speed為抖動的速度,即抖動頻率的控制,x會按照speed定義的速度持續增加。

    若判定抖動觸發(bool==true),則讓角色Sprite的X坐標等于A*Mathf.Cos(x)的值,借由三角函數的函數圖像可知,若x一直遞增,坐標便會呈現波動態。

    連擊預輸入的實現
    ?


    我將每一個攻擊動畫都分為了三個區間,并且定義了一個bool值;

    當進入到第二個(圖中黃色)區間時,便會開始檢測玩家是否按下了攻擊鍵,若按下攻擊鍵,則給bool變量賦值true;到第三個區間時,便會開始檢測bool值的真假,若為真,則允許動畫切換到下一個攻擊動作。而在每個動畫的第一幀,將bool值重新置為false。

    一般我會在允許動畫切換的關鍵幀前面留2-3幀作為預輸入的區間。

    總結

    那么,這是最終實現出來的效果:錄像軟件和GIF制作出來的效果不能很好的表達出來……
    ?


    本次畢設研究主要以視覺表現為主;一個合適的音效的確能給打擊感帶來更好的體驗,但一個好的打擊感主要還是通過視覺反饋造就的。玩家在按下按鍵的一瞬間或是按鍵之前心里就已經有了相應的預期,而產生的結果如果符合或超過玩家的預期則證明該反饋是優秀的。



    不難理解為什么有人只通過看視頻就想要對打擊感評頭論足,因為人們更在意感官表現,因為那很直觀,盡管操作手感也包括在打擊感的一環里,但并不是沒有僅憑視覺就讓人稱贊的作品。

    通過這次畢設的實驗,我發現也許打擊感更多要靠美術去表現。程序上的實現手段總結了下來大多都能理解,運用得當即可。但我在任何參數都沒改變的情況下,僅僅換了一整套更高質量的美術資源,呈現出來的效果卻讓我感覺好了很多。上面在說明“幀凍結”的時候提到過,一次好的打擊感也需要有好的動作設計和上乘的美術表現。通過實驗,我對此有了較為深刻的印象。

    我希望能通過分享和交流學習到更多的東西。

    以上這些主要為我的畢業設計中系統開發的一部分,有很多地方沒有說明為何要這樣做。希望有機會能將更多的東西整理出來吧。

    總結

    以上是生活随笔為你收集整理的用 Unity 探究 2D 游戏的打击感的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。