Exemple #1
0
    public void OnInspectorGUI()
    {
        var foldout = EditorGUILayout.Foldout(SilkDebug.GetFoldoutValue(DebugName), DebugName);

        SilkDebug.SetFoldoutValue(DebugName, foldout);
        if (foldout || true)
        {
            EditorGUILayout.ObjectField("MySilk", MySilk, typeof(Silk), true);
            EditorGUILayout.IntField("IndexOnSilk", IndexOnSilk);
            EditorGUILayout.ObjectField("Joint", Joint, typeof(ConfigurableJoint), true);
            EditorGUILayout.FloatField("_jointLength", _jointLength);
            EditorGUILayout.FloatField("RealLength", RealLength);
        }
    }
Exemple #2
0
    void FixedUpdate()
    {
        var        curPos = transform.position.ToVector2();
        RaycastHit hit;

        if (Physics.SphereCast(_lastPos, _sphereCollider.radius, (curPos - _lastPos).normalized, out hit,
                               (curPos - _lastPos).magnitude, LayerManager.LayerMask.Ground))
        {
            SilkDebug.DrawCross(_lastPos, 10, Color.cyan, 1);
            SilkDebug.DrawCross(curPos, 10, Color.cyan, 1);
            Debug.DrawLine(_lastPos, curPos, Color.gray, 1);
            Debug.Break();
        }
        _lastPos = curPos;
    }
Exemple #3
0
    /// <summary>
    /// 如果没有相切的错误,就返回true,否则返回false
    /// </summary>
    /// <returns></returns>
    public bool CheckSeperate()
    {
        var dir = (FarPoint.Position - NearPoint.Position).normalized;
        var hit = Physics2D.Raycast(NearPoint.Position, dir, (FarPoint.Position - NearPoint.Position).magnitude,
                                    LayerManager.LayerMask.SilkJoint);

        if (hit)
        {
            SilkDebug.DrawCross(hit.point, 0.3f, Color.red);

            var curLine = new Vector4(NearPoint.Position.x, NearPoint.Position.y, FarPoint.Position.x, FarPoint.Position.y);
            SilkDebug.DrawLine(LastLine, Color.green);
            SilkDebug.DrawLine(curLine, Color.black);
            LineCollisionHit lineHit;
            var bl = LineCollision.TryGetLineCollisionPoint(LastLine, curLine, out lineHit, LayerManager.LayerMask.SilkJoint,
                                                            PhysicsConfig.SurfaceLayerThickness);
            var tmpDrawer = lineHit.Collider.GetComponent <TmpDrawCircleCollider2D>();
            if (tmpDrawer != null)
            {
                tmpDrawer.DrawArc(lineHit.Point);
                Debug.LogFormat("line to circle distance:{0} @{1}",
                                Vector2.Distance(lineHit.Point, tmpDrawer.transform.position.ToVector2()) -
                                tmpDrawer.GetComponent <CircleCollider2D>().radius, Time.frameCount);
            }

            SilkDebug.DrawCross(lineHit.Point, 0.4f, Color.black);

            if (bl)
            {
                var jointItem = lineHit.Collider.gameObject.layer == LayerManager.Layer.Ground
                                    ? null
                                    : lineHit.Collider.GetComponent <Rigidbody2D>();
                MySilk.SeperateSegment(IndexOnSilk, lineHit.Point, jointItem);
            }
            else
            {
                Debug.LogWarningFormat("Tangency Error[{0}]", IndexOnSilk);
                return(false);
            }
        }

        return(true);
    }
Exemple #4
0
    ///// <summary>
    ///// 计算碰撞点
    ///// </summary>
    ///// <param name="vertex"></param>
    ///// <param name="sidePoint1"></param>
    ///// <param name="sidePoint2"></param>
    ///// <param name="collisionPoint"></param>
    ///// <returns>有没有碰撞</returns>
    //public static bool TryGetLineCollisionPoint(Vector2 vertex, Vector2 sidePoint1, Vector2 sidePoint2, out Vector2 collisionPoint)
    //{
    //    throw new Exception("TODO");
    //}

    /// <summary>
    /// 应该只在start时无碰撞end时有碰撞的情况返回true,给出有效hit。对运动物体会出错
    /// </summary>
    /// <param name="startLine"></param>
    /// <param name="endLine"></param>
    /// <param name="hitInfo"></param>
    /// <param name="layerMask"></param>
    /// <param name="epsilon"></param>
    /// <returns></returns>
    public static bool TryGetLineCollisionPoint(Vector4 startLine, Vector4 endLine, out LineCollisionHit hitInfo, LayerMask layerMask, float epsilon)
    {
        hitInfo = new LineCollisionHit();
        RaycastHit2D curHit;

        if (!CheckLineCollision(endLine, out curHit, layerMask))
        {
            Debug.LogWarning("Penetration may happen!");
            return(false); //endLine没撞到就别调用这个方法
        }
        var startLineRay = new Ray2D(startLine.P1(), startLine.Direction());

        RaycastHit2D startLineHit;//活动物体就不考虑碰撞了,现在只考虑地形

        if (curHit.collider.Raycast(startLineRay, out startLineHit, startLine.Length()))
        {
            SilkDebug.DrawCross(startLineHit.point, 0.1f, new Color(0.6f, 0.6f, 0));
            Debug.LogWarningFormat("Penetration may happen at {0},{1}! startLine={2} endLine={3}, distanceToCenter={4}", startLineHit.point.x, startLineHit.point.y, startLine, endLine, CalcPointToLineVertical(startLine, curHit.collider.transform.position).magnitude);
            return(false); //startLine都碰撞到这个东西了上一帧就该处理
        }

        var latestHit      = curHit;
        var vertical       = CalcPointToLineVertical(startLine, latestHit.point);
        var iterationTimes = 0;

        while (vertical.magnitude >= epsilon)
        {
            iterationTimes++;
            if (iterationTimes > 50)
            {
                Debug.LogFormat("iteration too many times > 50!");
                break;
            }
            var midLine = Vector4.Lerp(startLine, endLine, 0.5f);
            if (CheckLineCollision(midLine, out curHit, layerMask))
            {
                latestHit = curHit;
                endLine   = midLine;
            }
            else
            {
                startLine = midLine;
            }
            vertical = CalcPointToLineVertical(startLine, latestHit.point);
        }
        var nearHitInfo = latestHit;

        #region 计算FarHit

        var vectorF2N = new Vector2(endLine.x, endLine.y) - new Vector2(endLine.z, endLine.w);
        var fnRay     = new Ray2D(new Vector2(endLine.z, endLine.w), vectorF2N); //Far->Near的射线
        var hits      = Physics2D.RaycastAll(fnRay.origin, fnRay.direction, vectorF2N.magnitude, layerMask);
        if (hits.Length == 0)                                                    //不可能没有的
        {
            SilkDebug.DrawCross(new Vector2(endLine.x, endLine.y), 0.1f, new Color(0.5f, 0.5f, 0.1f));
            SilkDebug.DrawCross(new Vector2(endLine.z, endLine.w), 0.1f, new Color(0.4f, 0.4f, 0.3f));
            Debug.LogError("Error Cannot find farHit @" + Time.frameCount);
            Debug.LogWarningFormat("hits.Length == 0; startLine={0} endLine={1}, distanceToCenter={2}", startLine, endLine, CalcPointToLineVertical(startLine, curHit.collider.transform.position).magnitude);
            return(false);
        }
        if (hits.Length > 1)//很少见,穿透了多次地形
        {
            Debug.LogWarning("hits.Length > 1 ! Very rare!");
            var rightHits = hits.Where(x => x.collider == nearHitInfo.collider).ToList(); //取出碰撞到指定碰撞器的
            rightHits.Sort((x, y) => (int)Mathf.Sign(x.distance - y.distance));           //按到FarPoint的远近排序
        }
        var farHitInfo = hits[hits.Length - 1];                                           //取出最远的

        #endregion

        SilkDebug.DrawCross(nearHitInfo.point, 0.2f, Color.yellow);
        SilkDebug.DrawCross(farHitInfo.point, 0.2f, Color.yellow);

        #region 计算尖点和角平分线

        Vector2 c1  = nearHitInfo.point;
        Vector2 c2  = farHitInfo.point;
        var     n1  = nearHitInfo.normal;
        var     n2  = farHitInfo.normal;
        var     n1v = new Vector2(-n1.y, n1.x); //n1的垂线,右手螺旋,即c1所在边
        var     n2v = new Vector2(-n2.y, n2.x); //n2的垂线,右手螺旋,即c2所在边
        Vector2 vertex;                         //顶点,尖点
        if (Vector2.Dot(n2v, n1) == 0)
        {
            vertex = (c1 + c2) * 0.5f;//如果n1v,n2v平行,则无交点,取c1,c2中点。不太可能发生
        }
        else
        {
            vertex = c2 + Vector2.Dot(c1 - c2, n1) / Vector2.Dot(n2v, n1) * n2v;     //找到尖点
        }
        var bisector = (n2v - n1v).normalized;                                       //角平分线,不保证方向

        var bv = new Vector2(-bisector.y, bisector.x);                               //角平分线的垂线
        //找startLine与角平分线的交点
        var p1   = new Vector2(startLine.x, startLine.y);                            //p1,p2是startLine线段的两个端点
        var p2   = new Vector2(startLine.z, startLine.w);                            //p1,p2是startLine线段的两个端点
        var p1p2 = p2 - p1;
        var v    = p1 + Vector2.Dot(vertex - p1, bv) / Vector2.Dot(p1p2, bv) * p1p2; //那个我们需要的碰撞点,浮于碰撞器表面一个缓冲值以内

        //如果碰撞点离碰撞器过近(小于SurfaceLayerMinThickness),则强行拉回此值之外
        var vertex2v = v - vertex;
        if (vertex2v.magnitude < PhysicsConfig.SurfaceLayerMinThickness)
        {
            //找endLine与角平分线的交点
            var p1endLine   = new Vector2(endLine.x, endLine.y);
            var p2endLine   = new Vector2(endLine.z, endLine.w);
            var p1p2endLine = p2endLine - p1endLine;
            var vendLine    = p1endLine + Vector2.Dot(vertex - p1endLine, bv) / Vector2.Dot(p1p2endLine, bv) * p1p2endLine;

            Debug.LogFormat("OutPush vertex={0} v={1} distance={2}", vertex, v, vertex2v.magnitude);
            v = v + (v - vendLine).normalized * PhysicsConfig.SurfaceLayerMinThickness;
        }

        SilkDebug.DrawCross(vertex, 0.3f, Color.magenta);
        Debug.DrawRay(vertex, bisector);
        SilkDebug.DrawLine(startLine, Color.blue);
        SilkDebug.DrawLine(endLine, Color.blue);
        #endregion

        hitInfo = new LineCollisionHit(nearHitInfo.collider, (v - p1).magnitude, (v - vertex).normalized, v);

        return(true);
    }