迫害也需要指導理論:推拉機制及物理引擎詳解
前言
方舟已經公測一年了,然而針對其推拉系統(tǒng)仍然沒有較為深入的研究
目前較為普遍應用的僅有https://ngabbs.com/read.php?tid=17657755中針對推力算法的研究
本文將嘗試從程序層面完全揭開方舟推拉機制的原理
因涉及反編譯,部分研究過程不予放出
如有錯誤請各位大佬指正

底層:unity物理引擎
眾所周知方舟是拿unity引擎寫的,運動的底層自然也是使用的unity自帶的一些功能
在unity引擎中,剛體運動使用的是Rigidbody類型的元件
Rigidbody可以設置質量,碰撞類型等等等
方舟中敵方單位使用的是二維的剛體,即Rigidbody2D
這個剛體是dynamic類型,擬真度較高,可以模擬剛體的碰撞(雖然游戲中并不會發(fā)生),慣性,重力...等等
但有一點很特殊:在方舟中,這些剛體的質量全部被設置成了1(kg)
也就是說,只要初始狀態(tài)相同,施加的力相同,這些剛體的運動會完全一致
很顯然,方舟中是通過控制給Rigidbody2D施加力的大小和模式來控制不同的運動的
如何控制施加力的大小會在后面說到
給Rigidbody2D施加力的模式可以很多種,這里只介紹兩個方舟中用到的
第一種是Force,可以視作常規(guī)的,通過在一段時間內持續(xù)給一個剛體施加一個固定數值的力來改變其動量
第二種是Impulse,可以看做瞬時力。其原理可近似看做直接改變剛體的動量
如果想不起動量的概念請回憶高中物理,這在之后很重要
動量=mv=F關于t的積分,在F恒定時可看做Ft
Impulse模式會將t默認為1,直接為剛體增加Ft的動量
在方舟通用的m=1的情況下可得,v=F

中層:狀態(tài)機與摩擦力
中間層是鷹角自己發(fā)揮的部分,雖然是自由發(fā)揮但依然比較物理
首先需要介紹一下狀態(tài)機的概念
大體可以理解為敵人存在很多種狀態(tài),處在不同的狀態(tài)下會擁有不同的特征
比如成功的推拉本質上是對敵人施加力并使其進入unbalance狀態(tài)
只有在這個狀態(tài)下,敵人才會擁有物理碰撞箱,且每幀會更新速度并檢測狀態(tài)
按照程序算法,摩擦力=g*質量*摩擦系數,其中摩擦系數是0.5,g取默認值9.81,質量默認為1。求得摩擦力為4.9
程序每幀會根據摩擦力計算新速度并重設剛體速度
之后,程序會記錄新速度
如果((新速度小于等于0.1 且 已超過unbalance保護時間 且 無有效拉力來源) 或 (擁有UNBALANCE_IMMUNE效果))
則立刻退出unbalance狀態(tài),退出unbalance狀態(tài)時清空剛體運動速度

表層:概念聲明
表層屬于鷹角的自由發(fā)揮,這部分自由發(fā)揮使得方舟的推拉機制非常不物理
以下有很多很容易混淆的概念,先在此進行定義和聲明
力:代表unity引擎施加的力,大小和方向需要通過計算,模式根據推拉的區(qū)別有所不同
質量:代表敵人的剛體在unity引擎中設置的質量,默認為1(kg)
重量等級:代表游戲中敵人的重量等級屬性,無上下限
力量等級:代表游戲中見到的中等力度,大力等等級,其描述與等級的對應表如下

有效力量等級?= 來源力量等級?- 目標重量等級。值域為[-3, 3]

表層:推
推力本質上對敵人的剛體瞬間施加Impulse模式的力,直接改變其動量
推力的方向
推力有兩種模式,一種是relative,另一種是directional
前者的方向為推力來源到推力目標(的向量)
后者的方向一般為推力來源的朝向
但是注意,在一定情況下,directional會被裝換為relative:
當推力來源到推力目標的向量,與推力來源的朝向的夾角超過45度?或?推力來源與推力目標的坐標距離不足0.25
則directional推力會被轉換為relative推力
推力的力度計算
directional推力轉換為relative推力時有效力量等級將會減少,默認減少數值為2
有效力量等級將對應特定列表(位于gamedata中)中的編號
力的大小 = 對應后的值 * 0.02 * MOVE_MULTIPLIER(默認0.5)
下面將給出對應列表,力的大小將使用默認值進行計算

推力的執(zhí)行
大致邏輯如下:
如?力不為0 且 目標不持有UNBALANCE_IMMUNE效果
則將目標切換至unbalance狀態(tài)
隨后以impulse模式,按照剛剛計算的方向和大小施加單次的力
最后將unbalance保護時間期限調至0.1s后

表層:拉
拉力本質上對敵人的剛體持續(xù)施加Force模式的力,通過力逐漸改變其動量
拉力的方向與力度計算
方向就是拉力目標到來源的向量,這個沒啥好說的,關鍵是力度
和推力類似,拉力的有效力量等級將對應特定列表(位于gamedata中)中的編號
初始力的大小 = 對應后的值 * 1
下面將給出對應列表

細心的讀者應該注意到我在力的前面加了個初始吧
鉤子在命中目標時會記錄下目標與來源的距離
在默認情況下(easeType=6,即easeInQuart)
某一瞬間的力?= (現距離/初始距離)^4 * 初始力
(現距離/初始距離)最大為1
因此鉤子的力度會隨著距離比例的接近急速衰減
拉力的執(zhí)行
目前的機制中,拉力都是和鉤子掛鉤的
鉤子鉤中時:
如?力為0
則立刻停止鉤子
如 目標不持有UNBALANCE_IMMUNE效果
則將目標切換至unbalance狀態(tài)
然后將unbalance保護時間期限調至0.1s后
鉤子是projectile,擁有最大持續(xù)時間
當有效力量等級>=-1時,鉤子鉤中后會將最大持續(xù)時間改為linkDuration(默認為1)
否則最大持續(xù)時間將被改為0.5
鉤子勾住期間會時刻檢查目標是否位于來源阻擋范圍內
檢查位于范圍內且只有單個拉力來源時會立刻清空目標速度

一些結論
推力的公式可以沿用https://ngabbs.com/read.php?tid=17657755
位移=0.5*初速度^2/加速度
雖然機制上有一定的不準確但給出的公式沒有問題
拉力的話,我列了個微分方程

據學數學的朋友說,這個方程存在解析解,但不是初等函數
因此寫個模擬器計算大概還快一些
本文原載于NGA:https://ngabbs.com/read.php?tid=22221080
作者為本人
部分研究(反編譯)過程未轉載至專欄
本專欄以CC BY-NC-SA 4.0協(xié)議發(fā)布