![]()
作者:余田
首發(fā)“魚塘游戲制作工坊”公眾號
一、前言
最近在設(shè)計基于組裝和物理的玩法,其中有兩個非常有趣的問題,最近初步思考出結(jié)果,值得探討交流一下。
問題1
如何基于組裝和物理,設(shè)計單位間碰撞的傷害規(guī)則,既要好理解,且和其他傷害類型盡量統(tǒng)一邏輯?
問題2
如何基于組裝和物理,設(shè)計移動操控方案,同樣,既用物理作為底層,便于未來的拓展,又要保證操作手感?
在開始具體設(shè)計前,先要回答一個問題,為什么底層基于物理那么重要?基于物理其實設(shè)計和實現(xiàn)都會麻煩很多,但是好處就是未來的拓展性,一個統(tǒng)一堅實的底層,將會串聯(lián)起所有未來的設(shè)計。例如如果我們的底層移動規(guī)則是基于力和質(zhì)量等物理設(shè)計,那未來所有影響單位位移的特性,都可以用簡單的施力方式改變來實現(xiàn),比如后坐力,擊退等等。同時,物理本身的好處比如具有提前認知,有足夠深度,復(fù)雜系統(tǒng)能支持涌現(xiàn)設(shè)計等等,以前的文章都詳細提過,就不贅述了。
實際上,這里強調(diào)的是統(tǒng)一堅實的底層,只要達到這兩個要求,不管是不是物理作為底層都行。
二、碰撞設(shè)計
現(xiàn)實參考
設(shè)我們單位的所有常規(guī)碰撞為非彈性碰撞,因為完全彈性碰撞并不會造成傷害。同時,我們的單位是組裝而成,因此基于模塊設(shè)計,模塊有基礎(chǔ)的碰撞傷害,碰撞傷害和被傷害都是以模塊為單位。若模塊和核心相連,則質(zhì)量為整體質(zhì)量,速度仍為模塊自己的速度,若模塊脫離,則為模塊自身的質(zhì)量和速度。
整體上,碰撞需要符合玩家的直覺,一定是參考現(xiàn)實物理,但又不能完全照搬。因此我們只取物理中和碰撞相關(guān)的,且玩家最容易感知到的特性。
先參考現(xiàn)實,現(xiàn)實中的碰撞傷害很難有一個統(tǒng)一的標(biāo)準(zhǔn),碰撞結(jié)果本身就多種多樣,但不論怎樣的結(jié)果,有一個統(tǒng)一的度量方法,就是基于動能損失,本質(zhì)就是將動能轉(zhuǎn)化成其他能量,一般我們忽略產(chǎn)生的熱能等等,基本上就等于雙方受到傷害的程度。我們先列一些現(xiàn)實中的公式:
動量:p=m*v
動能:ke = (1/2) * m * v2
損傷D = 參數(shù)M * (1/2) * (m1 * m2) / (m1 + m2) * |v1 - v2|2
M代表調(diào)整參數(shù),表達不同材質(zhì),角度等因素造成的影響
游戲設(shè)計
游戲中設(shè)計,則需要我們進一步細化,且做出自己的變化,我將我們的碰撞過程抽象為五個步驟:
1.首先是碰撞角度考慮
碰撞時兩模塊相對速度 Vr=v1 - v2
過一遍閾值,Vr小于閾值則跳過計算,忽略傷害
獲取碰撞點的法線向量,unity里就是collisionNormal
則最終的相對碰撞速度為 Vrf = Vector2.Dot ( Vr , collisionNormal )
Vrf也過一遍最小閾值,小于則忽略本次傷害
2.質(zhì)量,動量,能量考慮
設(shè)雙方總質(zhì)量為m1,m2,則初步損傷Da= (1/2) ( (m1 * m2) / (m1 + m2) ) Vrf2
3.統(tǒng)一的撞擊能力表達
將現(xiàn)實中的強度和硬度等概念去掉,用一個類似攻擊力的,撞擊能力來同時體現(xiàn)鋒利度硬度等背后的特性
同樣的,不同組件可配,整體上,我們希望用于撞擊的,鋒利的,強度高的,撞擊能力配高一些即可
設(shè)我方組件撞擊能力ImpactPower1,敵方ImpactPower2
則我方最終受到傷害Db1 = ImpactPower2 * Da;敵方為Db2 = ImpactPower1 * Da
4.統(tǒng)一的防御能力表達
將所有常規(guī)傷害來源的防御能力統(tǒng)一,暫定為裝甲值A(chǔ)rmor,碰撞或者子彈,激光擊中等,都過一樣的防御流程
防御公式也統(tǒng)一,比如用常規(guī)的除法防御,Dc_1 = Db1 × K / (Armor_1 + K)
至于其他防御公式,也可以隨時換
5.模塊間的傷害傳遞
用傷害類型來區(qū)分是否觸發(fā)蔓延效果,所有動能傷害,觸發(fā)沖擊蔓延,所有非動能,觸發(fā)其他機制。簡化為用傷害類型來控制,如此可以更靈活,例如碰撞為全動能傷害,武器則更靈活,可以部分動能傷害混合其他傷害,各自計算即可。
沖擊蔓延規(guī)則,是基于面的規(guī)則,目的是讓玩家感受到?jīng)_擊后影響一片組件的感受,符合直覺且塑造物理碰撞獨有的意義。規(guī)則為:
用BFS方式,找出被沖擊組件L0的相連組件L1,以及L1相鄰的組件L2(不包含L0和L1)
L0收到的動能傷害D0,以一定比例P1折損后D1,平均分配到L1上,該傷害不視作動能傷害,視作特殊傳遞傷害,不會觸發(fā)蔓延
同理,D1以P2比例折損后的D2,平均分配到L2。P1,P2可配
加入閾值,低于閾值傷害V,則不觸發(fā)蔓延,V可配
三、機動性設(shè)計
再次回顧設(shè)計目的,基于物理的機動性設(shè)計有兩大重點:
- 基于物理的提前認知,來降一些復(fù)雜設(shè)定的門檻,不需要多擬真,但要玩家感知上符合物理
- 未來所有可以基于現(xiàn)實規(guī)則的設(shè)計,都可以利用物理底層統(tǒng)一起來實現(xiàn),而不需要另加一套規(guī)則
先總結(jié)一下,對玩家體驗有較大影響的機動性相關(guān)要素是哪些?
- 最高速度
- 加速度,減速度,旋轉(zhuǎn)角速度,影響操控手感
- 質(zhì)量,不僅影響速度,也影響慣性感受
- 響應(yīng)風(fēng)格,搖桿推動時的響應(yīng)曲線,同樣明顯影響手感
這里先提另外一種實現(xiàn)方案,有少量基于物理的游戲,一般是太空類游戲,是通過控制飛船引擎出力推動主角移動,這種確實更擬真物理。但問題是玩家操控難度大,因為玩家一般期望控制結(jié)果,而這種操控方式需考慮加減速過程,與常規(guī)游戲操作邏輯不同,操作手感一般都比較差。
而要手感比較好,一般游戲都會讓操控輸入,直接映射角色的實際速度,甚至定死幾檔速度,同時加減速度都跟物理無關(guān),是直接設(shè)定好,甚至有很多不遵循現(xiàn)實的設(shè)定來保證手感,例如土狼時間,邊緣吸附,空中轉(zhuǎn)向等等。這當(dāng)然沒問題,絕大多數(shù)游戲的設(shè)計意圖下,手感大于擬真。
而對我們來說,是“既要又要”,我們需要玩家手感好,但是底層需要仍是由物理驅(qū)動,來保證拓展性。具體來說,我們將運動分為兩層,一層物理層,一層操控層。飛船的實際運動由物理層控制,跟飛船的總推力和總質(zhì)量等物理參數(shù)有關(guān)。另一個是操控層,玩家操控搖桿時,抽象為給船一個目標(biāo)速度和方向的指令,剩下的推力賦予,由系統(tǒng)來計算,減輕玩家負擔(dān)。等于有一個飛船中控在幫玩家實時調(diào)節(jié)引擎推力,防止出現(xiàn)轉(zhuǎn)向和精確控制速度困難的問題。同時,考慮到后續(xù)的組裝,對物理層進行一定簡化和抽象,具體如下:
物理層
飛船物理層運動的核心參數(shù)如下:
1.總推力Fa
用作計算飛船理論最大速度等等,由組裝時的情況決定一個最終值,忽略方向和組裝位置等影響,簡化為一個總推力
2.總質(zhì)量Ma
同上,組裝時所有模塊帶來的質(zhì)量加總,或者有其他加成減益都算完后的一個結(jié)果值,物理側(cè)不關(guān)心細節(jié),也只關(guān)心一個總值
3.阻尼系數(shù)μ
系統(tǒng)默認阻尼系數(shù),加上環(huán)境帶來的阻尼情況,例如固定摩擦和空氣摩擦的近似設(shè)計,最終抽象為一個阻尼系數(shù)μ的輸出結(jié)果。我們先省略默認阻尼,看需要再設(shè)計。先將阻尼系數(shù)分為兩個部分,持續(xù)固定阻力以及類空氣阻力兩部分:
- 持續(xù)固定阻力F_const,作用是在低速時,防止停不下來,讓操控更加干凈利落
- 類空氣阻力F_air,特點是速度越快阻力越大,因此可以控制最大速度,且反過來,因為有空氣阻力,所以加速過程可以更快,讓手感更好
- 則最大速度時的平衡條件為Fa = F_const + F_air
- 先簡化空氣阻力F_air的公式為線性公式,F(xiàn)_air = Kair * V_current。Kair可配。公式有可能會換平方公式,看實際手感調(diào)。
- 則最大預(yù)測速度 Vmax = ( Fa - F_const )/ Kair
4.總轉(zhuǎn)動慣量I
慣量I表達了物理上,一個物體旋轉(zhuǎn)的難度,我們用一個近似的簡化公式:I = k*m*R^2
- k代表質(zhì)量形狀分布,質(zhì)量越集中,越好旋轉(zhuǎn)。我們可以用組裝的長寬比來近似的定這個值,參考現(xiàn)實,0.2到1之間
- R為半徑,越大旋轉(zhuǎn)越難,直接用組裝飛船的最小包裹圓的半徑即可
- m就是總質(zhì)量,理論上物體的質(zhì)量分布會影響慣量,但這里我們進行簡化,直接取總質(zhì)量Ma即可
如上,就是I的精細設(shè)計方向,可以讓組裝有符合直覺的隱形影響,同時,自然地達成大船轉(zhuǎn)的慢這點。
5.總姿態(tài)推力力矩Tmax
和慣量一起決定了最大角加速度Aθ=Tmax/I。這里的力矩可以簡化為根據(jù)組裝時的引擎情況來決定,可以精細也可以粗獷,豐儉由人。對我們游戲來說,因為當(dāng)前單位旋轉(zhuǎn)的重要性沒有那么高,因此暫時簡化設(shè)計,例如姿態(tài)力矩Tmax = 總推力Fa的百分比。也就是引擎裝的多這個也高。
這個參數(shù)可以默認對玩家隱藏,但可以有這個空間,給到不同的機動組件不同風(fēng)格,比如機械腿,這個就賊大,來表達轉(zhuǎn)向快之類的。
6.比較重要的衍生參數(shù)
最大理論速度Vmax 由推力質(zhì)量以及阻尼系數(shù),共同計算出來的最大速度,每張地圖都有可能不同
最大線加速度Amax 由Fa/Ma直接得來
最大角加速度Aθ Aθ=Tmax/I
操控層
操控層如下:
1.計算目標(biāo)速度差(向量)
左邊的搖桿來控制機動,左搖桿坐標(biāo):s = (sx, sy) ∈ [-1,1]2
搖桿有死區(qū)設(shè)定,若 |s| < deadzone,則視為 0,防止抖動,具體比例可配
設(shè)搖桿的輸入向量為V_in,以及當(dāng)前飛船的速度V_current
將V_in的模長設(shè)定為,死區(qū)起點為|Vmin|,可配,搖桿拉到底設(shè)為最大速度的模|Vmax|。先用線性變化,后續(xù)可以優(yōu)化成立方曲線或自定義曲線,手感會更好
最終得出一個目標(biāo)速度V_target,方向沒變,大小變成了上一行所算的大小
然后,當(dāng)前的速度向量差Δv = V_target - V_current
2.計算目標(biāo)加速度
計算Δv的絕對值,來跟最大速度比,來實現(xiàn)根據(jù)速度差距,用不同加速度加速,可以防止最后的抖動,設(shè)最大加速度閾值比例Smax,最小Smin
|Δv|> Smax * Vmax 時,直接用 Amax,注意,如果組件破壞質(zhì)量要動態(tài)變化,則Amax要重新更新
|Vd|< Smin * Vmax 時,用一個Amin,Amin可以直接配置
Smin * Vmax <|Vd|< Smax * Vmax 時,Amin,Amax間線性變化即可。
最后得出一個 A_target,也就是達成上述速度變化的一個目標(biāo)加速度
3.賦力
然后速度部分最后一步,目標(biāo)力F_target = Ma * A_target。同樣注意Ma為當(dāng)前的質(zhì)量,unity直接賦予這個力就行。
4.飛船朝向
在目標(biāo)速度V_target和當(dāng)前速度V_current間插值,來留出調(diào)不同風(fēng)格手感船的空間
目標(biāo)朝向方向d_face = normalize( lerp(normalize(v_current), normalize(v_target), k_face) )。k_face可配
然后取飛船當(dāng)前的朝向向量 ship_forward
算出角度差,同樣可以算出角加速度需求,然后和線速度類似,設(shè)兩個角度閾值,θmin,θmax。
大于θmax直接用最大角速度Aθ,小于θmin則用一個最小角加速度Aθmin,可配;兩者之間則插值,來防止抖動。
最后也用這個算出來的目標(biāo)角加速度,用unity賦予飛船,同樣注意飛船質(zhì)量變化帶來的影響。
四、總結(jié)
以上是最近的思考結(jié)果,初步思路先記錄一下,還不是很成熟,還需持續(xù)落地迭代,歡迎大家交流斧正。
特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺“網(wǎng)易號”用戶上傳并發(fā)布,本平臺僅提供信息存儲服務(wù)。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.