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