Performance 快速移动物体2D游戏(Unity3d)

Performance 快速移动物体2D游戏(Unity3d),performance,unity3d,collision-detection,rigid-bodies,Performance,Unity3d,Collision Detection,Rigid Bodies,我发现官方的团结训练 找到bug。(看分数) 我花了大约2天的时间来修复它,但失败了。 我找到了“dontgothothroughthings”脚本,并尝试重写以在2D中使用。(再次失败) 请帮帮我 这是重写脚本: public LayerMask layerMask; //make sure we aren't in this layer public float skinWidth; //probably doesn't need to be changed private float

我发现官方的团结训练 找到bug。(看分数)

我花了大约2天的时间来修复它,但失败了。 我找到了“dontgothothroughthings”脚本,并尝试重写以在2D中使用。(再次失败)

请帮帮我

这是重写脚本:

public LayerMask layerMask; //make sure we aren't in this layer 
public float skinWidth; //probably doesn't need to be changed 

private float minimumExtent; 
private float partialExtent; 
private float sqrMinimumExtent; 
private Vector2 previousPosition; 
private Rigidbody2D myRigidbody; 


//initialize values 
void Awake() 
{ 
    myRigidbody = GetComponent<Rigidbody2D>(); 
    previousPosition = myRigidbody.position;
    minimumExtent = Mathf.Min(Mathf.Min(GetComponent<Collider2D>().bounds.extents.x, GetComponent<Collider2D>().bounds.extents.y)); 
    partialExtent = minimumExtent * (1.0f - skinWidth); 
    sqrMinimumExtent = minimumExtent * minimumExtent; 
} 

void FixedUpdate() 
{ 
    //have we moved more than our minimum extent? 
    Vector2 movementThisStep = myRigidbody.position - previousPosition; 
    float movementSqrMagnitude = movementThisStep.sqrMagnitude;

    if (movementSqrMagnitude > sqrMinimumExtent) 
    { 
        float movementMagnitude = Mathf.Sqrt(movementSqrMagnitude);
        //RaycastHit2D hitInfo; 

        //check for obstructions we might have missed 
        if (Physics2D.Raycast(previousPosition, movementThisStep, movementMagnitude, 0, layerMask.value)) 
            myRigidbody.position = (movementThisStep/movementMagnitude)*partialExtent;
        Debug.DrawLine(myRigidbody.position, myRigidbody.position - previousPosition, Color.green);
    } 

    previousPosition = myRigidbody.position; 
}
public LayerMask LayerMask//确保我们不在这一层
公共浮标宽度//可能不需要改变
私人浮动最小范围;
私人浮动部分帐篷;
私人浮动sqrmimextent;
私有向量2先前位置;
私人刚体;
//初始化值
无效唤醒()
{ 
myRigidbody=GetComponent();
previousPosition=myRigidbody.position;
minimumExtent=Mathf.Min(Mathf.Min(GetComponent().bounds.extends.x,GetComponent().bounds.extends.y));
partialExtent=最小范围*(1.0f-皮肤宽度);
SQrMinimExtent=最小范围*最小范围;
} 
void FixedUpdate()
{ 
//我们的行动是否超过了我们的最低限度?
Vector2 movementThisStep=myRigidbody.position-previousPosition;
浮动移动sqrMagnitude=移动ThisStep.sqrMagnitude;
如果(移动SQRMagnitude>SQRMimumExtent)
{ 
float movementMagnitude=数学Sqrt(movementSqrMagnitude);
//RaycastHit2D hitInfo;
//检查我们可能错过的障碍物
if(Physics2D.Raycast(上一个位置,移动此步骤,移动幅值,0,layerMask.value))
myRigidbody.position=(movementThisStep/movementMagnitude)*PartialContent;
DrawLine(myRigidbody.position,myRigidbody.position-previousPosition,Color.green);
} 
previousPosition=myRigidbody.position;
}
这是unitypackage


对我的英语很抱歉,谢谢你的帮助

以下是我重写的该脚本的2D版本(适用于Unity 4.6):

使用UnityEngine;
使用系统集合;
公共课不做粗野的事:单一行为
{
公共委托无效CollidedLegate(Collider2D碰撞器);
公共事件发生冲突;公使国发生冲突;
public LayerMask LayerMask;//确保我们不在此层中
public float skinWidth=0.1f;//可能不需要更改
私人浮动最小范围;
私人浮动部分帐篷;
私人浮动sqrmimextent;
私有向量2先前位置;
私人刚体;
//初始化值
无效唤醒()
{
肉豆蔻体=刚体2d;
previousPosition=myRigidbody.transform.position;
minimumExtent=Mathf.Min(BoundsOf(collectedr2d).extensts.x,BoundsOf(collectedr2d).extensts.y);
partialExtent=最小范围*(1.0f-皮肤宽度);
SQrMinimExtent=最小范围*最小范围;
}
void FixedUpdate()
{
//我们的行动是否超过了我们的最低限度?
Vector2 movementThisStep=(Vector2)myRigidbody.transform.position-previousPosition;
浮动移动sqrMagnitude=移动ThisStep.sqrMagnitude;
如果(移动SQRMagnitude>SQRMimumExtent)
{
float movementMagnitude=数学Sqrt(movementSqrMagnitude);
//检查我们可能错过的障碍物
RaycastHit2D[]hitsInfo=Physics2D.RaycastAll(上一个位置,移动此步骤,移动幅度,层掩码.value);
//后退是因为我们想先看第一次碰撞,因为我们想摧毁离前一个位置更近的一次碰撞
对于(int i=hitsInfo.Length-1;i>=0;i--)
{
var hitInfo=hitsInfo[i];
如果(hitInfo&&hitInfo.rigidbody!=rigidbody2D)
{
如果(碰撞!=null)
{
碰撞(hitInfo.collider);
}
}
}
}
previousPosition=myRigidbody.transform.position;
}
//计算局部空间中的边界
公共静态边界边界(碰撞的R2D碰撞器){
var-bounds=新边界();
var bc=碰撞器,如BoxCollider2D;
国际单项体育联合会(卑诗省){
var ext=bc.size*0.5f;
封装(新向量3(-ext.x,-ext.y,0f));
封装(新向量3(ext.x,ext.y,0f));
返回边界;
}
var cc=碰撞器,如CircleCollider2D;
如果(cc){
var r=cc半径;
封装(新向量3(-r,-r,0f));
封装(新向量3(r,r,0f));
返回边界;
}
//其他:P
//Debug.LogWarning(“未知类型”+边界);
返回边界;
}
//世界空间中的返回界
公共静态边界边界准直器(GameObject obj){
变量边界=新边界(obj.transform.position,Vector3.zero);
var colliders=obj.GetComponentsInChildren();
foreach(碰撞器中的var c){
var blocal=边界(c);
var t=c.变换;
var max=t.TransformPoint(blocal.max);
封装(最大值);
var min=t.TransformPoint(blocal.min);
封装边界(min);
}
返回边界;
}
}
请让我知道它是否适合你

谢谢,
李丹解释

Unity中的连续碰撞检测不使用光线投射。因此,非常快速移动(和/或相对较小)的物体(现在我们称这种物体为投射物)仍然会穿过物体,而不会检测到碰撞。著名的组件修复了3D的问题。有一些不一致的地方,但是如果你知道你在做什么,它可以完成工作

这是我对它的2D改编

我添加了一些功能,使它对不太擅长编码或游戏物理的人更加友好

如何使用它

  • 将此组件添加到快速移动的对象和
    using UnityEngine;
    using System.Collections;
    
    public class DontGoThroughThings : MonoBehaviour
    {
        public delegate void CollidedDelegate(Collider2D collider);
        public event CollidedDelegate Collided;
    
        public LayerMask layerMask; //make sure we aren't in this layer 
        public float skinWidth = 0.1f; //probably doesn't need to be changed 
    
        private float minimumExtent;
        private float partialExtent;
        private float sqrMinimumExtent;
        private Vector2 previousPosition;
        private Rigidbody2D myRigidbody;
    
    
    
        //initialize values 
        void Awake()
        {
            myRigidbody = rigidbody2D;
            previousPosition = myRigidbody.transform.position;
            minimumExtent = Mathf.Min(BoundsOf(collider2D).extents.x, BoundsOf(collider2D).extents.y);
            partialExtent = minimumExtent * (1.0f - skinWidth);
            sqrMinimumExtent = minimumExtent * minimumExtent;
        }
    
        void FixedUpdate()
        {
            //have we moved more than our minimum extent? 
            Vector2 movementThisStep = (Vector2)myRigidbody.transform.position - previousPosition;
            float movementSqrMagnitude = movementThisStep.sqrMagnitude;
    
            if (movementSqrMagnitude > sqrMinimumExtent)
            {
                float movementMagnitude = Mathf.Sqrt(movementSqrMagnitude);
    
                //check for obstructions we might have missed 
                RaycastHit2D[] hitsInfo = Physics2D.RaycastAll(previousPosition, movementThisStep, movementMagnitude, layerMask.value);
    
                //Going backward because we want to look at the first collisions first. Because we want to destroy the once that are closer to previous position
                for (int i = hitsInfo.Length-1; i >= 0; i--)
                {
                    var hitInfo = hitsInfo[i];
                    if (hitInfo && hitInfo.rigidbody != rigidbody2D)
                    {
                        if (Collided != null)
                        {
                            Collided(hitInfo.collider);
                        }
                    }
                }
            }
    
            previousPosition = myRigidbody.transform.position;
        }
    
        // compute bounds in local space
        public static Bounds BoundsOf(Collider2D collider) {
            var bounds = new Bounds();
    
            var bc = collider as BoxCollider2D;
            if (bc) {
                var ext = bc.size * 0.5f;
                bounds.Encapsulate(new Vector3(-ext.x, -ext.y, 0f));
                bounds.Encapsulate(new Vector3(ext.x, ext.y, 0f));
                return bounds;
            }
    
            var cc = collider as CircleCollider2D;
            if (cc) {
                var r = cc.radius;
                bounds.Encapsulate(new Vector3(-r, -r, 0f));
                bounds.Encapsulate(new Vector3(r, r, 0f));
                return bounds;
            }
    
    
            // others :P
            //Debug.LogWarning("Unknown type "+bounds);
    
            return bounds;
        }
    
        // return bounds in world space
        public static Bounds BoundsColliders(GameObject obj) {
            var bounds = new Bounds(obj.transform.position, Vector3.zero);
    
            var colliders = obj.GetComponentsInChildren<Collider2D>();
            foreach(var c in colliders) {
                var blocal = BoundsOf(c);
                var t = c.transform;
                var max = t.TransformPoint(blocal.max);
                bounds.Encapsulate(max);
                var min = t.TransformPoint(blocal.min);
                bounds.Encapsulate(min);
            }
    
            return bounds;
        }
    
    
    }