2012-03-13 119 views
13

我在保持包含空間內的遊戲對象時遇到問題。當他們到達邊緣時,會有一些瞬間推回,但他們會直接穿過牆壁。如何防止碰撞體相互穿過?

我在玩家身上使用了箱子對撞機,而在等級的牆上使用了網狀碰撞物。我與玩家角色(太空飛船)有問題,運動是由玩家控制的。並且拋射物是火,而且不會以恆定的速度移動。

這是我的球員的運動代碼。它正在運行在FixedUpdate()函數中。

//Movement 
    haxis = Input.GetAxis("Horizontal") * speed; 
    vaxis = Input.GetAxis("Vertical") * speed; 

    moveVector.x = haxis; 
    moveVector.z = vaxis; 

    if(moveVector.magnitude > 1) 
    { 
     moveVector.Normalize(); 
    } 

    rigidbody.MovePosition(transform.position + moveVector * speed); 

隨着子彈,它們被賦予一個速度,引擎計算他們的電影。他們使用箱子對撞機,它被設置爲觸發器,所以他們沒有物理。但我用OnTriggerEnter來摧毀它們。

//Projectiles without physics collisiions 
function OnTriggerEnter (other : Collider) { 
    Destroy(gameObject); 
} 

一些,但並不是所有的子彈擊中將網格對撞機壁時被破壞。玩家有時會擊中並停止,但通常可以通過它。我怎樣才能使網格碰撞器每次碰撞?

+0

我甚至從牆上的網格創建了一個更簡單的網格對撞機,它沒有幫助。 – Chris 2012-03-13 16:42:12

+0

您用於屏幕的網狀碰撞體有多寬,子彈和玩家的行程有多快?如果子彈或玩家可以在一幀內移動比對撞機長的距離,那麼就有了它。另外,我會避免手動移動剛體。這隻會混淆物理引擎並阻止其優化。改爲移動遊戲對象的變換。 – Elideb 2012-03-14 14:22:09

+0

@Elideb對撞機大概有8個字符和20個子彈。他們沒有完全通過一個框架中的對撞機。如果移動變換Unity將忽略所有物理,rigidbody.MovePosition將物理考慮在內。 – Chris 2012-03-14 16:23:00

回答

9

與快速移動物體的碰撞始終是一個問題。確保檢測到所有碰撞的一種好方法是使用Raycasting,而不是依靠物理模擬。這適用於子彈或小物體,但對於大型物體不會產生良好效果。 http://unity3d.com/support/documentation/ScriptReference/Physics.Raycast.html

僞codeish(我沒有在這裏的代碼完成和一個貧窮的記憶):

void FixedUpdate() 
{ 
    Vector3 direction = new Vector3(transform.position - lastPosition); 
    Ray ray = new Ray(lastPosition, direction); 
    RaycastHit hit; 
    if (Physics.Raycast(ray, hit, direction.magnitude)) 
    { 
     // Do something if hit 
    } 

    this.lastPosition = transform.position; 
} 
+0

提交了一個編輯,但它應該是Ray(lastPosition,方向),否則你可能在網格物體對撞機內部,並且雷不會從對撞機內部撞擊。看起來像一個好方法,我會檢查出來。 – Chris 2012-03-14 19:23:57

+0

我在這裏可以想到的唯一問題是我們可能會看到很多移動元素,並且我懷疑在所有這些元素上使用Raycast會比使用複合對碰者的性能更重。如果我有機會對此進行測試,我會讓你知道性能差異。 – Chris 2012-03-14 22:57:52

+0

collider.Raycast檢查單個對撞機 - 我編輯Physics.Raycast。關於表現,我認爲它不會有太大的影響,但它需要測試。你可以使用Physics.Raycast的layerMask參數來確保它僅僅得到你想要的測試(見文檔)。 – Petrucio 2012-03-15 02:34:32

1

所以我一直沒能得到網對撞機的工作。我使用簡單的盒子對撞機創建了一個複合對撞機,它的工作方式與預期完全相同。

其他測試與簡單的網格碰撞器都出來了。

看起來最好的答案是用簡單的盒子/球體對撞機構建一個複合對撞機。

對於我的具體情況,我寫了一個嚮導,它創建了一個管形複合對撞機。

@script AddComponentMenu("Colliders/Pipe Collider"); 
class WizardCreatePipeCollider extends ScriptableWizard 
{ 
    public var outterRadius : float = 200; 
    public var innerRadius : float = 190; 
    public var sections : int = 12; 
    public var height : float = 20; 

    @MenuItem("GameObject/Colliders/Create Pipe Collider") 
    static function CreateWizard() 
    { 
     ScriptableWizard.DisplayWizard.<WizardCreatePipeCollider>("Create Pipe Collider"); 
    } 

    public function OnWizardUpdate() { 
     helpString = "Creates a Pipe Collider"; 
    } 

    public function OnWizardCreate() { 
     var theta : float = 360f/sections; 
     var width : float = outterRadius - innerRadius; 

     var sectionLength : float = 2 * outterRadius * Mathf.Sin((theta/2) * Mathf.Deg2Rad); 

     var container : GameObject = new GameObject("Pipe Collider"); 
     var section : GameObject; 
     var sectionCollider : GameObject; 
     var boxCollider : BoxCollider; 

     for(var i = 0; i < sections; i++) 
     { 
      section = new GameObject("Section " + (i + 1)); 

      sectionCollider = new GameObject("SectionCollider " + (i + 1)); 
      section.transform.parent = container.transform; 
      sectionCollider.transform.parent = section.transform; 

      section.transform.localPosition = Vector3.zero; 
      section.transform.localRotation.eulerAngles.y = i * theta; 

      boxCollider = sectionCollider.AddComponent.<BoxCollider>(); 
      boxCollider.center = Vector3.zero; 
      boxCollider.size = new Vector3(width, height, sectionLength); 

      sectionCollider.transform.localPosition = new Vector3(innerRadius + (width/2), 0, 0); 
     } 
    } 
} 
12

我有一個彈球的原型,也給了我在同一地區的麻煩。這些都是我已經採取的步驟差不多(但尚未完全)解決這些問題:

對於快速移動的物體:

  • 設置剛體的插值計算,以「插值」(這不影響實際物理模擬,但正確更新對象的渲染 - 僅從渲染的角度使用此對象,如播放器或彈球,但不適用於投射物)

  • 將碰撞檢測設置爲連續動態

  • 將腳本DontGoThroughThings(https://www.auto.tuwien.ac.at/wordpress/?p=260)附加到您的對象。這個腳本巧妙地使用我在其他回答中發佈的Raycasting解決方案將衝突點拖回到碰撞點之前。

Edit -> Project Settings -> Physics

  • 設置最小滲透率處罰,以非常低的值。我已將其設置爲0.001

  • 將求解器迭代計數設置爲更高的值。我已經把我的設置爲50,但你可以做得更少。

所有這一切都將在服務表現一個點球,但那是不可避免的。默認值在性能上很軟,但並不真正用於對小而快的物體進行適當的模擬。

+0

嗨,我無法找到DontGoThroughtThings腳本你可以提供它。可能是用戶從上面刪除了鏈接。 – 2013-09-09 12:29:40

+0

我發現了DontGoThroughtThings Scripte的鏈接 http://code.google.com/p/lava-in-antarctica/source/browse/trunk/DontGoThroughThings.cs?spec=svn2&r=2 – 2013-09-10 06:24:13

+0

我在使用Unity 5並閱讀後雖然我找不到'Minnetnetration for Penalty',但我試着將'默認接觸偏移量'改爲1.現在,快速移動的物體正在被檢測到:) – Kunalxigxag 2015-04-01 05:54:13

1
  • 編輯--->項目設置 - >時間...... decrese「固定時間步長」值。這將解決這個問題,但它可以產生負面影響性能。

  • 另一種解決方案是可以計算座標(例如,你有一個球和牆壁。球會打牆,所以計算牆的座標,並設定根據這些cordinates擊球過程)

0

1.)切勿使用MESH COLLIDER。使用盒子和膠囊碰撞器的組合。

2.)檢查RigidBody中的約束條件。如果您勾選了凍結位置X,那麼它將穿過X軸上的對象。 (y軸相同)。

0

老問題,但也許它可以幫助某人。

轉到項目設置>時間並嘗試將固定時間步和最大允許時間步分爲兩或四。

我有問題,我的球員能夠通過比球員對撞機更小的開口擠壓,並解決了它。它也有助於阻止快速移動的物體。

+0

舊的答案,但謝謝! – Deniss 2016-09-13 16:23:27