測試環境很簡單,一面牆,紅色方塊不停向前
然后,由於剛體是FixedUpdate執行的,把FixedUpdate執行間隔調慢一些方便Debug:
OK,下面還原一次經典的穿透問題:
測試腳本:
void Update() { transform.Translate(0, 0, 10 * Time.deltaTime); }
OK,然后我測試了幾種方法,最后發現直接改速率最為有效,AddForceAtPosition雖然也可以但是不常用:(注釋掉的方法都測試失敗,碰撞檢測"連續/非連續"都測過)
void FixedUpdate() { //transform.Translate(0, 0, 10 * Time.deltaTime); //transform.Translate(0, 0, 10 * Time.fixedDeltaTime); //GetComponent<Rigidbody>().position += transform.forward; //GetComponent<Rigidbody>().MovePosition(transform.position + transform.forward * 10 * Time.deltaTime); //GetComponent<Rigidbody>().MovePosition(transform.position + transform.forward); GetComponent<Rigidbody>().AddForceAtPosition(new Vector3(0, 0, 30000), transform.position + transform.forward, ForceMode.VelocityChange); GetComponent<Rigidbody>().velocity = transform.forward * 100000f; }
但這只是防止FixedUpdate更新頻率低的解決方法,我極限測試了一下,又穿透了:
void FixedUpdate() { GetComponent<Rigidbody>().velocity = transform.forward * 100000f; }
然后我嘗試把碰撞檢測改為連續:
終於,沒有出現穿透:
再補上一個夾角測試:(卡是因為我把FixedUpdate頻率調低了)
測試腳本:

void Update() { if(Input.GetKey( KeyCode.A)) { GetComponent<Rigidbody>().velocity = transform.right * -20f; } if (Input.GetKey(KeyCode.D)) { GetComponent<Rigidbody>().velocity = transform.right * 20f; } if (Input.GetKey(KeyCode.W)) { GetComponent<Rigidbody>().velocity = transform.forward * 20f; } if (Input.GetKey(KeyCode.S)) { GetComponent<Rigidbody>().velocity = transform.forward * -20f; } }
另外測了一下Animator的穿透情況,打開根運動造成的位移不會穿透。如果是動畫控制的位移會穿透,但除非你強制移除Animator,動畫位移不會有什么影響
並且和UpdateMode的具體模式無關