2D Object Collison Unity

时间:2017-09-10 15:45:08

标签: c# unity5 game-physics unity2d

我在Unity中开发了一个简单的2D游戏,在处理碰撞时我遇到了一个问题。我有两个对象,一棵树和一个玩家。树不会移动,并由一些精灵和多边形对撞机表示。玩家使用自定义脚本(不是角色控制器)移动,并附加运动学 Ridgidbody和多边形对撞机。

我的预期行为是让玩家“碰撞”。与树一起被它阻挡,所以没有任何物体可以移动。但是,它似乎并不是一种简单的方法。

将树的RidgidBody组件设置为'静态'或者'动态'导致没有检测到碰撞。我考虑让玩家成为一个充满活力的玩家。刚体,但unity docs表明动态刚体不应该被它们的变换组件移动,这就是我当前系统的工作方式。此外,将其设置为动态会导致玩家无缘无故地冻结的意外行为,并且由于没有物理将应用于播放器对象,因此它似乎是动态的不良用例。我可能只是错了。

我可以使用脚本以某种方式在触发碰撞器事件时锁定玩家位置,但这看起来非常黑客。任何人都可以提供一些如何处理这个问题的见解吗?

1 个答案:

答案 0 :(得分:0)

显然,2D裂缝有点儿笨拙。以下是一些避免此问题的方法。基本上不是依靠碰撞器,它使用光线投射来检查玩家是否有障碍试图移动

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