Due to number of images, this post was split into 3:
Part 1
Part 2
Part 3 (this post)
Ground collision
Ground collision is more complicated; for starters, it is done in stages, whereas air collision is done in a single function.
The first stage is done at the function that checks for left/right input for acceleration/deceleration. Right after checking for input, the function performs some checks to see if the character should change to a balancing animation:
- When standing on a solid or platform object, and the character's vertical center line is past either end of the object, the character will lose balance.
- If the character is standing on terrain, sensor rays will be cast. The number and location of the ray anchors depend on the character; but at minimum, a vertical ray is cast from an anchor at the middle of the bottom edge of the character's collision box. Sonic casts more rays to determine which of his animations are to be used, while Tails and Knuckles cast only one sensor ray. These rays have no effect other than to see if the character should use a balancing animation or not.
Note, also, that character must also be still and in mostly level ground to balance.
Object/Terrain Balancing Bug: When standing at the edge of an object, characters will swap to their balancing animation even if their other "foot" is on solid ground. This is because the game does not check for the presence of a floor in this case. Fixing this is just a matter of adding the missing check.

Terrain/Object Balancing Bug: Likewise, when standing at the edge of terrain, characters will swap to their balancing animation even if their other "foot" is on a solid or platform object. Basically, the converse of the above bug. Fixing this is more involved: it requires changing object collision code to mark an object as being interacting with the character even when the 'standing on object' flag is unset, as long as the hitbox would overlap. Then, a check could be added to see if there is an object at the right place. Fixing this is probably not worth the effort.

Object/Object Balancing Bug: When standing at the edge of an object, characters will swap to their balancing animation even if their other "foot" is on another solid/platform object. Fixing this would require something similar to the
Terrain/Object Balancing Bug, but the second object would need an additional interaction slot with characters. Fixing this is probably not worth the effort.

After balancing, the function goes on to do a lot more things. Towards the end, it sets X and Y speed based on ground speed/inertia and current ground angle.
At this point, the zip anchor finally becomes relevant. If you are in a situation where the zip anchor exists, it is used at this point to check for "walls" along the way (it looks for ceilings and floors, in addition to walls, depending on your direction of motion). If a wall is found such that the zip anchor is
inside a wall, your X or Y speed (as appropriate) is adjusted so that you will move to touch the wall. If you are moving mostly horizontally, your ground speed/inertia is set to zero. This is more colloquially known as bumping into the wall and stopping.
Wall Grinding Bug: If you are moving mostly vertically and you run into a floor or ceiling, you will not lose your ground speed. You will stay grinding against the wall until you either slow down enough to fall (if moving up), or gain enough speed go through the floor (if moving down).

Zipping Bug: This is the reason why I called it "zip anchor": this is the favorite bug of speedrunners in this game. Normally, when a character bumps into a wall, the distance inside the wall is subtracted (added) from (to) the speed, in pixels, depending on your direction of motion. Under normal circumstances, you will keep just enough speed to move until your collision box is touching the wall. If you are inside the wall, however, things get interesting: pressing a direction will give you a small amount of speed in that direction (6/256 pixels/frame for non-super characters in the normal games), and will enable the zip anchor. But since you are inside the wall, the sensor ray emitted by the zip anchor will say you are 32 pixels inside the wall (for reasons I am not 100% sure, sometimes it will give only 16 pixels in). So you will end up with a speed of (32 - 6/256) pixels/frame opposite to the direction you pressed. The issue is that the games do not check for overflows or underflows when computing the new speed.
Vertical Zipping Bug: While a true vertical zip can only occur in S&K/S3&K (because the zip anchor will only appear in a perfectly vertical direction for those games), the conditions needed for a near vertical zip are achievable in S1 and S2 with only collision glitches (and perfectly vertical zips can be achieved in S&K/S3&K with the help of additional glitches).

Non-Zipping Bug: S3/S&K/S3&K have a flag that disables zipping. This flag is set by the Angel Island 1 hollow tree, and by Flying Battery rotating cylinder meshes. In some circumstances, it is possible to glitch the game into not clearing this flag. You can then freely walk through walls.
Moving Peel-Out Bug: In SCD you can perform a Moving Peel-Out by starting to charge a peel-out, pausing, holding down + forward, unpausing, quickly pausing, and switching to holding up again. This sets your inertia to the current Super Peel-Out charge, and you start moving at this speed. The Super Peel-Out charging mechanism is in the same function that handles zipping, and above it; and as long as you are charging the Super Peel-Out (pressing up or down + forward count), the function returns before reaching the wall check, allowing you to walk through walls.
Moving Through Walls Platform Bug: Most moving platform and solid objects directly adjust the character's position, and perform no checks to see if you are being moved inside a wall. Since the zip anchor only exists when the character has nonzero
speed, you can stand still on top or to the side of these objects and get dragged/pushed inside walls. The games generally add solid objects (usually, invisible) on walls to prevent this from happening.
Exception: SCD does not suffer from this issue: its default solid/platform object routine manually performs a running wall check, using the object's X speed instead of the character's. The consequences of this check depend on whether the character is standing on the object, or to its sides: if the character is standing on top of the moving object, he/she will just be ejected out of the wall. Otherwise, the character is killed if he/she is even a single pixel inside the wall. Springs are a partial exception to this exception, and will not crush characters if they are on the air.


After the wall check, there is a rolling check, level bounds check, the character is finally moved according to X/Y speeds, and we arrive at the next part related to collision: adjusting the position and angle of the character so that he/she is not inside terrain.
If the character is standing on an object (the 'standing on object' flag is set), terrain will be ignored at this stage, and you keep whatever angle you had before.
Slope Glitch: If you manage to despawn some solid or platform objects, they will not always clear the 'standing on object' flag. When you land on terrain, you get the angle from the spot you landed. Since the 'standing on object' flag prevents further updates of the angle, and your position is not also adjusted to keep you on the terrain, you will walk at whatever angle you have, even walking on air or through ground. The "correct" way of fixing the bug is to make sure all solid and platform objects properly clear the 'standing on object' flag on all cases. Another workable (partial) fix is to always clear this flag when a character lands, and move the location where the flag is set in the object collision routine to after the landing code.
Moving Through Floors Platform Bug: Since being on a platform or solid object disables floor position adjustments, moving platform and solid objects can simply pull you through floors. Since the zip anchor only exists when the character has nonzero
speed, you can stand still on top of these objects and get dragged inside walls and floor. The games are really bad at accounting for this case.
Exceptions: SCD does not suffer from this issue: its default solid/platform object routine manually performs a floor check whenever the object is not moving up. Springs are an exception to this exception, and will not drop characters on the floor.
In S2, the moving lava floors is also an exception: it checks if the characters should be dropped on the floor, but it is not a normal floor check: it just casts a single sensor ray from the bottom center of the collision box. The checks for both characters are done in the same function, which is called after the normal solid object routine, by the object itself.
In S&K/S3&K, the falling mushrooms in Mushroom Hill, the elevators in Flying Battery, the tilting block bridge in Death Egg, all call an function identical to that of S2. The rising floor in Marble Garden, and the rising sand in Sandopolis, also call this function to drop each character. It loads the object player 1 is standing on (if any), calls the function, then loads the object player 2 is standing on (if any), and calls the function.
In S3, the rising floor in Marble Garden does not work like in S3&K.

Otherwise, position and angle are adjusted by performing a walking ground check. This check will return 2 distances and 2 angles (1 of each per sensor ray). The games will pick the smaller distance (including sign, it is not absolute distance — meaning the distance that is deeper inside terrain) and the associated angle. If the new angle is no more than 45 degrees from the old angle, it will be used; otherwise, 45 degrees will be added to the current angle, and it will be rounded to the nearest multiple of 90 degrees.
After this, if the character is less than 14 pixels inside the ground, he/she is ejected out.
Angle Bug: This causes a bug that leaves the character lodged into the terrain: with the right speed, position, and sloped terrain, the character may end up more 14 pixels or more inside the terrain. This is typically incorrectly attributed to the angle not changing fast enough (and I believed this until I started writing this). Disabling this check fixes the issue, but I have no idea if it causes undesirable side effects, or why this check is there to begin with.

If the character is not touching terrain anymore (because of sloped terrain, or going off a ledge), and if either
max(abs(X or Y speed) + 4, 14) <= distance to ground
(where X speed is used for floor/ceiling, Y speed is used for walls) or the 'stick to convex' flag is set, then the character will be moved back to touching the ground.
Tube Rejection Bug: When going through spin tunnels, you can sometimes be "rejected": a sudden loss of speed, sometimes to the point that you start going back from where you came. One of the reasons that this happens is that the character is moving fast enough to lose contact with the ground per the above equation. I believe that the zip anchor may also play a part in tube rejection, but I haven't been able to confirm this. I have no fix for this one, partial or otherwise, because I don't know yet all factors involved in causing it.
Wheel Glitch: The Scrap Brain 2, Metallic Madness, and Carnival Night wheels/discs you can run around on have a huge "capture" area around them which sets the 'stick to convex' flag to true. If there is a solid or platform object inside this area, you can stand on it and walk off its edge to escape from the wheel's influence while keeping the 'stick to convex' flag set. While in this state, whenever you run off a ledge, you will still be considered to be standing on terrain, and you will "fall" 16 pixels/frame towards where the game thinks "ground" is for your current angle.
S&K/S3&K have additional floor, left and right wall checks after this. These checks are enabled only in some cases (moving wall in Hydrocity 2, during earthquakes and rising floors in Marble Garden 1 & 2, rising sands in Sandopolis 2). If the floor check detects that the character is inside a wall, the character is summarily executed; this check only casts a single ray from the bottom middle of the collision box. The left and right wall checks eject the character as normal.
Moving Through Ceilings Platform Bug: Because there are no sensor rays being cast up when you are on the ground, moving platform and solid objects can push you inside terrain without any issue. The games generally add solid objects (usually, invisible) on walls to crush you in this case, but they do miss some cases.
*Exception:* SCD does not suffer from this issue: its default solid/platform object routine manually performs a modified ceiling check whenever the object is moving up. Specifically, it casts a sensor ray from the top center of the collision box. The character is killed if he/she is even a single pixel inside the ceiling. Springs are an exception to this exception, and will not crush characters.

This post has been edited by flamewing: 04 May 2018 - 12:08 PM