Unity-Technologies / com.unity.cinemachine

Smart camera tools for passionate creators
505 stars 117 forks source link

CinemachineConfiner2D is literally cutting corners #259

Open johanolofsson opened 3 years ago

johanolofsson commented 3 years ago

So the way this seems to work is that the client of Cinemachine providers a bounding shape of the world (in this case a polygon) in which the camera bounds should be confined, we call this "outer polygon". Cinemachine then produces a smaller polygon, we call this the "inner polygon", which defines the shape that should confine the center of the camera. For the sake of reasoning we can also imagine two points, the "outer point" which is the camera target, typically the player, and the "inner point" which is the center of the camera. The inner point wants to be as close to the other point as possible at any given time, but limited to the shape of the inner polygon. This makes a lot of sense and is a good approach to the problem as it is quite easy to figure out if a point is inside a poly and if not what is the closest point of the poly where that is the case.

However, there are some issues atm. Wherever there is a concave corner in the outer polygon, there is obviously also a concave corner in the inner polygon. Between these corners is a line. If we imagine that this line continues from the outer corner through the inner corner and beyond it will cut the inner polygon into two pieces (potentially more but that's irrelevant to the case at hand).

The thing about this line is that whenever the outer point passes it outside the inner poly - which of the two parts of the inner poly is the best fit for the inner point changes. I.e. there is a point in the other inner shape that is closer to the outer point than the part the inner point was previously in. So the camera should move there. Cinemachine does this, so far so good.

The problem is that the current implementation in CinemachineConfiner2D does this by simply cutting the corner. Either by snapping there if damping is 0, or slowly interpolating its position there displaying parts of the world which was clearly defined as undesirable by the initial outer polygon specified by the client. None of the solutions are sufficient to make up a good user experience.

Instead Cinemachine should move the inner point to the new desired inner point by gradually walking it there using the shortest possible path within the inner polygon. Just the way an actual camera man would have to do it. It should be possible to specify:

I'm pretty sure this could be improved even further by some smart look a head when the outer point is close to the line. I.e. the amount of "walking" that is performed by the inner point is relative to the distance between the line and the outer point. It's like the camera man anticipates the need to move to the other side.

Anyway I hope you acknowledge this issue and that my reasoning may help improving Cinemachine which I in general find really useful!

gaborkb commented 3 years ago

Thank you for the concise issue report! You are bringing up a very valid issue and possible solutions :slightly_smiling_face:. We'll discuss it and come up with a fix it at some point. Hopefully in the near future :wink::rocket: