2017-09-10 184 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

感谢您接受它 –