2017-09-10 182 views
2

我正在Unity開發一個簡單的2D遊戲,並且在處理碰撞時遇到了問題。我有兩個對象,一棵樹和一個玩家。樹不移動,並由一些精靈和多邊形對撞機表示。玩家使用自定義腳本(不是字符控制器)移動,並且附有Ridgidbody和多邊形對撞機。2D對象碰撞Unity

我的預期行爲是讓玩家與樹'碰撞'並被它阻擋,所以沒有任何物體能夠移動。但是,這似乎並不是一個簡單的方法。

將樹的RidgidBody組件設置爲「靜態」或「動態」會導致檢測不到碰撞。我認爲讓玩家成爲一個「動態」剛體,但unity docs表明,動態剛體不應該被它們的變換組件所移動,這就是我現有系統的工作原理。此外,將其設置爲動態結果會導致玩家無故凍結的意外行爲,並且由於沒有物理效果會應用於玩家對象,因此對於動態玩家來說似乎是一個糟糕的用例。但我可能只是錯了。

我可能會使用腳本以某種方式鎖定玩家位置,當碰撞事件被觸發時,但這看起來很詭異。任何人都可以提供一些關於如何處理這個問題

+1

添加使用的是移動 –

回答

0

很明顯,2D的colissions是有點bug。這裏有一些方法可以避免這個問題。基本上,而不是依賴於對撞機,它採用了光線投射到檢查是否有玩家爲試圖移動

using UnityEngine; 
using System.Collections; 
using UnityEngine.UI; 

public class Player : MovingObjects { 

    protected override void AttemptMove<T> (int xDir, int yDir) 
    { 
     base.AttemptMove<T> (xDir, yDir); 
     RaycastHit2D hit;  
    } 
    protected override void onCantMove<T>(T component) 
    { 
     Wall hitwall = component as Wall; 
     hitwall.DamageWall (wallDamage);   
    } 

    // Update is called once per frame 
    void Update() { 

     int horizontal = 0; 
     int vertical = 0; 

     horizontal = (int)Input.GetAxisRaw ("Horizontal"); 
     vertical = (int)Input.GetAxisRaw ("Vertical"); 

     if (horizontal != 0) 
      vertical = 0; 

     if (horizontal != 0 || vertical != 0) 
      AttemptMove<Wall> (horizontal, vertical); 
    } 
} 

從繼承的障礙:

using UnityEngine; 
using System.Collections; 

public abstract class MovingObjects : MonoBehaviour { 

    public float moveTime = 0.1f; 
    public LayerMask blockingLayer; 

    private BoxCollider2D boxCollider; 
    private Rigidbody2D rb2D; 
    private float inverseMoveTime; 

    protected virtual void Start() 
    { 
     boxCollider = GetComponent<BoxCollider2D>(); 
     rb2D = GetComponent <Rigidbody2D>(); 
     inverseMoveTime = 1f/moveTime; 

    } 


    protected IEnumerator SmoothMovement(Vector3 end) 
    { 
     float sqrRemaininDistance = (transform.position - end).sqrMagnitude; 

     while (sqrRemaininDistance > float.Epsilon) { 

      Vector3 newPosition = Vector3.MoveTowards(rb2D.position, end, inverseMoveTime*Time.deltaTime); 

      rb2D.MovePosition(newPosition); 
      sqrRemaininDistance = (transform.position - end).sqrMagnitude; 

      yield return null; 
     } 
    } 

    protected bool Move(int xDir, int yDir, out RaycastHit2D hit) 
    { 
     Vector2 start = transform.position; 
     Vector2 end = start + new Vector2 (xDir, yDir); 

     boxCollider.enabled = false; 

     hit = Physics2D.Linecast (start, end, blockingLayer); 

     boxCollider.enabled = true; 

     if (hit.transform == null) { 

      StartCoroutine(SmoothMovement(end)); 
      return true; 
     } 

     return false; 
    } 

    protected virtual void AttemptMove<T>(int xDir, int yDir) 
          where T : Component 
    { 

     RaycastHit2D hit; 
     bool canMove = Move (xDir, yDir, out hit); 

     if (hit.transform == null) 
      return; 


     Debug.Log ("Something hit", gameObject); 

     T hitComponent = hit.transform.GetComponent<T>(); 

     if (!canMove && hitComponent != null) 
      onCantMove (hitComponent); 


    } 

    protected abstract void onCantMove<T>(T component) 
         where T: Component; 

} 

這個腳本屬於教程Unity官方網站。一款名爲Rogue的2D遊戲。這裏是鏈接以防萬一你打算做同樣的事情:

https://unity3d.com/es/learn/tutorials/projects/2d-roguelike-tutorial

+1

我已經被身體類型設置爲動態,並利用剛體解決了這個問題玩家腳本.MovePosition結合Vector2來處理玩家移動。謝謝您的回答。 – Jeremy

+0

感謝您接受它 –