Mimic.UKCC Initial Implementation #45
Labels
open to contributors
Want to contribute? This task is available.
very difficult
This task is for the hard-core only
Mimic.UKCC
Unity’s Kinematic Character Controller package is well-liked by the community.
However, its dependence on Unity Physics means that projects which use it also
inherit the many problems of Unity Physics. We want a character controller
without the side-effects.
Task is Prerequisite For
Base Requirements
Implement a Psyshock-based kinematic character controller solution in Mimic that
provides feature-parity and feel-parity with Unity’s Kinematic Character
Controller package while supporting Psyshock’s multiple code-driven
CollisionLayer
design philosophy.The solution should not use
IAspect
, since those are anticipated to be goingaway. And the solution should also not rely on a single
CollisionLayer
for allspatial queries.
Assume that this will not be the recommended solution for massive hordes of
characters in a top-down RTS or tower defense, as a lighter-weight custom
solution would be preferred in such scenarios.
It is not the responsibility of this solution to apply forces onto external
objects. It only needs to provide a means to record such forces so that user
code may apply them.
QVVS Transforms must be supported. Unity Transforms support via
Latios.Transforms.Abstract
is not required. The justification here is thatmost if not all people using Unity Transforms are doing so because they need
Unity Physics for compatibility with other assets they are using.
The solution does not need to follow the designs outlined below. They are only
provided as a possible direction. Additionally, the name does not need to be
UKCC. That too is only a suggestion.
Solving the IAspect Problem
IAspect
allows for bundling multiple components into a single abstracted typewith an API. Without this bundling, we still need a way to provide an abstract
API, and make such an API as simple as possible to use.
This means we want to reduce the amount of component types involved as much as
possible. One way to do this would be to combine all the
IComponentData
typesinto a single
IComponentData
struct
. TheKinematicCharacterProperties
,KinematicCharacterBody
,StoredKinematicCharacterData
, and theCollider
(possibly a specific collider type like a
CapsuleCollider
) would all be fieldsin a single
KinematicCharacterController
component.Transforms will still be separate, but this will not be any surprise for a user.
The three dynamic buffers
KinematicCharacterHit
,StatefulKinematicCharacterHit
, andKinematicVelocityProjectionHit
are notexplicitly needed outside of the controller movement update and could instead be
replaced with temporary buffers. The user could then copy these temporary
buffers into dynamic buffers or other data structures if necessary. The last
dynamic buffer
KinematicCharacterDeferredImpulse
is probably better stored ina
NativeStream
. This all could be added to theKinematicCharacterUpdateContext
.With all of this established, it now becomes true that the single
KinematicCharacterController
component can now replace theKinematicCharacterAspect
.Won’t Combining Everything Hurt Performance?
For the use cases this is targeting, not really. The controller update is going
to use a large amount of the data in the component. And very few other systems
are going to interact with this data directly. We can probably guess at which
kinds of systems would actually need such interactions.
First, there’s stats and ability systems. What is interesting about these is
that they could potentially touch any data, which means the whole component is
fair game. We’d have no way of knowing in advance what the optimal way to split
it is, as that’s usually game-dependent, so it is probably better we just keep
it all together. Achievement systems generally follow the same thought process.
Lastly, there’s the animation system, which while perhaps a little more focused
in which data it needs from the character controller, will also be consuming
computation and memory resources for animation that dwarfs the cost of a
combined component for the character controller.
Solving the PhysicsWorld Problem
While
IAspect
was relatively simple to work through, thePhysicsWorld
withinKinematicCharacterUpdateContext
is much more challenging.The character controller needs to differentiate between static environment,
kinematic platforms, dynamic rigid bodies, and other kinematic character
controllers. In Unity Physics, the
PhysicsWorld
encodes this information.However, in Psyshock, it is up to the user to choose how this information is
encoded. There might be a single
CollisionLayer
that combines staticenvironment and kinematic platforms. Or there might be multiple
CollisionLayers
that each have static colliders.Most likely, the correct solution is to have a generic struct which does one of
the following:
CollisionLayers
needed for each hitCollisionLayers
and indices in layer for each AABB overlapresults in-time
To further complicate matters, this is also the most performance-sensitive part
of the whole solution. That is because Unity’s implementation performs quite a
few spatial queries on the
PhysicsWorld
. These queries are all local aroundthe character, but Unity’s implementation scans the whole world with every
query. As an optimization, it may be possible to keep a cache of nearby objects
and subcolliders (important for large terrains or mesh landscapes) using an
initial
FindObjects
(or maybe even a FindPairs pre-pass for all charactercontrollers?). If any query’s AABB fits within the cached AABB search area, it
can simply do narrow-phase tests on the cache.
Finding a solution that has both good performance and an intuitive API will
prove challenging.
Collaboration
It may be determined during development of this feature that new APIs are
required in Psyshock. It is perfectly acceptable and encouraged to request these
APIs.
The text was updated successfully, but these errors were encountered: