0
\$\begingroup\$

I've been trying to get a swept collision detection up and running now for almost a week and I can't for the life of me get it working.

Example image

There is a answer on this linked here below: Swept AABB vs Line Segment 2D

I've translated this into Go which will be running the game server and needs this logic:

func SweepRectLine(rectX, rectY, rectW, rectH, rectHSpeed, rectVSpeed, lineX1, lineY1, lineX2, lineY2 float64) (bool, float64) {
    outVel := [2]float64{}
    // hitNormal := [2]float64{}
    lineNX, lineNY := lineX2-lineX1, lineY2-lineY1
    // lineMinX, lineMaxX, lineMinY, lineMaxY := math.Min(lineX1, lineX2), math.Max(lineX1, lineX2), math.Min(lineY1, lineY2), math.Max(lineY1, lineY2)
    var lineMinX, lineMaxX, lineMinY, lineMaxY float64
    if lineNX > 0 {
        lineMinX, lineMaxX = lineX1, lineX2
    } else {
        lineMinX, lineMaxX = lineX2, lineX1
    }
    if lineNY > 0 {
        lineMinY, lineMaxY = lineY1, lineY2
    } else {
        lineMinY, lineMaxY = lineY2, lineY1
    }
    r := (rectW/2)*math.Abs(lineNX) + (rectH/2)*math.Abs(lineNY) //radius to Line
    boxProj := (lineX1-rectX)*lineNX + (lineY1-rectY)*lineNY
    velProj := rectHSpeed*lineNX + rectVSpeed*lineNY

    if velProj < 0 {
        r *= -1
    }

    hitTime := math.Max((boxProj-r)/velProj, 0)
    outTime := math.Min((boxProj+r)/velProj, 1)
    // log.Println("start", hitTime, outTime)

    rectXMax, rectXMin := rectX+rectW/2, rectX-rectW/2
    if rectHSpeed < 0 { // left
        if rectXMax < lineMinX {
            return false, 0
        }
        hitTime = math.Max((lineMaxX-rectXMin)/rectHSpeed, hitTime)
        outTime = math.Min((lineMinX-rectXMax)/rectHSpeed, outTime)
    } else if rectHSpeed > 0 { // right
        if rectXMin > lineMaxX {
            return false, 0
        }
        hitTime = math.Max((lineMinX-rectXMax)/rectHSpeed, hitTime)
        outTime = math.Min((lineMaxX-rectXMin)/rectHSpeed, outTime)
        // log.Println("right", hitTime, outTime)
    } else {
        if lineMinX > rectXMax || lineMaxX < rectXMin {
            return false, 0
        }
    }

    if hitTime > outTime {
        return false, 0
    }

    rectYMax, rectYMin := rectY+rectH/2, rectY-rectH/2
    if rectVSpeed < 0 { // up
        if rectYMax < lineMinY {
            return false, 0
        }
        hitTime = math.Max((lineMaxY-rectYMin)/rectVSpeed, hitTime)
        outTime = math.Min((lineMinY-rectYMax)/rectVSpeed, outTime)
    } else if rectVSpeed > 0 { // down
        if rectYMin > lineMaxY {
            return false, 0
        }
        hitTime = math.Max((lineMinY-rectYMax)/rectVSpeed, hitTime)
        outTime = math.Min((lineMaxY-rectYMin)/rectVSpeed, outTime)
    } else {
        if lineMinY > rectYMax || lineMaxY < rectYMin {
            return false, 0
        }
    }

    if hitTime > outTime {
        return false, 0
    }

    outVel[0] = rectHSpeed * hitTime
    outVel[1] = rectVSpeed * hitTime
    return true, hitTime
}

I also put up a Gist with a executable UI here: https://gist.github.com/KidLinus/3f847c46b0e6dc1addac7252d9cb54ab

I can't for the life of me figure out what all class variables stand for. I think that some of them are native to Unity but that's just a guess. I've come so far as to figure out that the extent is half of the width/height in said direction. What the "line.n" stands for is anyones guess, I assume its the direction and have no idea if it's normalized or not.

There are also a couple of dead variables just laying there.

\$\endgroup\$
5
  • \$\begingroup\$ Line.n looks like a unit normal to the line — a direction vector perpendicular to the line and 1 unit in length. Anything else you're having trouble with? \$\endgroup\$
    – DMGregory
    May 4 at 11:25
  • \$\begingroup\$ Well, to start off I don't know which of the normals :/ I've tried it as both normals but have no luck. The same wierd collisions still happends. \$\endgroup\$
    – Linus
    May 4 at 11:56
  • \$\begingroup\$ Might want to add that detail to your question then. \$\endgroup\$
    – DMGregory
    May 4 at 11:57
  • 1
    \$\begingroup\$ Please reduce your code to a mcve and include it in your question. Not only does it better follow the community guidelines (in that questions should be relatively self contained), but increases the number of people who will actually look at your code (as fewer users are going to click through & sift through your project). \$\endgroup\$
    – Pikalek
    May 4 at 14:09
  • \$\begingroup\$ My snippet is a single 160 line file with the minimal amount of boiler required to actually fire up it and view if it is working. \$\endgroup\$
    – Linus
    May 4 at 15:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.