Box Carry Overhaul (Again)
Several weeks ago, I overhauled the object carrying system, switching from a method that used a spring to carry the object to one that used a series of raycasts to position it.
I thought this had solved all of my problems, because I was able to free fall with the box, release it in mid-air and catch it again, and this opened up a lot of really interesting gameplay possibilities.
However, I soon discovered a problem.
Raycast Method Problem
When playing around a few days ago, I noticed that this:
What’s happening here is that there is a gap between the yellow block and the wall. The player is carrying the blue box, and the initial raycast is hitting the wall behind the yellow block, and then positioning the blue block according to that, hence the overlap into the yellow box.
Now, a solution to avoid this happening would be to simply send a raycast in the direction of the wall’s surface normal to check that nothing is blocking the way. This would be a good way to detect that the block can’t be placed, but how would I determine where to place the block? Closer to the player? Above the yellow block? In front of it? There’s just way too many possibilities to consider, and the math gets way too complicated very quickly.
There’s also another edge case where the same problem happens:
It’s due to the same issue. The initial raycast is hitting the bottom surface of the higher block, and then drawing the blue box downward, causing it to overlap with the lower block. Again, I can use raycasts to detect the lower block, but how would I figure out where to correctly place the blue box?
Another solution is to simply not create such spaces. But there is nothing to stop the player from placing two boxes close to one another with a small gap, and so this problem would still happen.
With the spring method, because it’s using collision, this would be avoided. But then with the spring system, I can’t be in freefall with the box…
What to do?
Raycast and Spring Combination System
I decided that the solution would be to combine the spring and raycast systems. When the player is on the ground, I would use the spring method, which would avoid the problems stated above. And then as soon as the player goes into freefall (which is detected with a raycast pointing downward from the player), I would switch to the raycast system.
This is what it looks like:
Can you tell when it’s using which system?
Here’s the breakdown:
Whenever player is standing on ground, we use the spring system, so it’s basically a box collision:
As soon as player goes into freefall, we switch to raycast system, which allows player to carry object in mid-air. When player lands, we switch back to spring:
There’s a slight jump in movement of box when we go from spring to raycast. This is because when walking forward, the spring gets compressed, and the box is slightly closer to the player. With the raycast system, the box is at fixed distance (at least when nothing is in front of player), and so that jump is the chance in distance.
I think I can tweak the values of the spring enough such that there isn’t much compression of the spring, so that jump will be very small, or not at all.
Bonus Snap To Grid Fix of Spring Problem
One of the problems that I had before with the spring system was that because you were applying force on the box and using collision, there was the issue of mesh penetration:
Note how the orange box overlaps slightly with the blue box. This isn’t really a problem, but bothered me.
I had implemented grid snapping last time, and this fixed the issue when one box fell from another, but not really when you pushed the box in from the side or from below.
I realized though, that I could just call the SnapToGrid function whenever a collision is detected, and that would cause the box to move away from the penetration distance.
Note how the blue box never ends up penetrating the yellow box:
The grid spacing I am using is 0.125 since the entire game is built on multiples of 0.5. Using 0.125 allows all spacing to divide evening into the distance in the world. I was using 0.1, but sometimes that resulted in a slight offset in alignment of the object.
Edge Box Collision – Super Hacky Unity Fix
After the spring/raycast system was implemented, I made one other fix to another problem I noticed. This is definitely one of the ones I am simultaneously really proud of and also embarrassed by, because of how hacky it is.
Here’s the problem:
If you aligned a box next to a protrusion, and released it, the edge of the box would catch on the edge of the protrusion. I’m not exactly sure what’s going on. I think it’s a floating point issue? I think since I’ve locked the box rotation, it isn’t able to rotate and fall down.
In any case, the blue box ends up catching on the edge of the protrusion and it looks like it’s just floating in mid air.
This is pretty annoying. I spent a good while going through the code, and just could not figure out what was causing this issue.
Then, while playing around, I noticed that if I reduced the size of the collider slightly, from 1 to 0.99, the box would fall down.
Whenever the box is released, or during free fall, I changed the size of the collider box from 1x1x1 to 0.99×0.99×0.99. Once the box lands or when it is being carried, I change it back to 1x1x1 (otherwise, you’d seen penetration of the meshes)
And because of the grid snapping, the box will still get realigned.
After I implemented this, the weird edge catch problem didn’t happen anymore: