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.
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.
-
\$\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– DMGregory ♦2021年05月04日 11:25:07 +00:00Commented May 4, 2021 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– Linus2021年05月04日 11:56:20 +00:00Commented May 4, 2021 at 11:56
-
\$\begingroup\$ Might want to add that detail to your question then. \$\endgroup\$DMGregory– DMGregory ♦2021年05月04日 11:57:11 +00:00Commented May 4, 2021 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– Pikalek2021年05月04日 14:09:04 +00:00Commented May 4, 2021 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– Linus2021年05月04日 15:22:26 +00:00Commented May 4, 2021 at 15:22