I am designing a physics class library for Unity3d and would love to be able to hook and inject functionality into Unity3d's Rigidbody
class, but it's my understanding that there is no way to do this directly while still being able to target all platforms.
I thought the next best thing might be to create a new class that inherits directly from Rigidbody
. However, it looks like unity has prevented this from occurring in anything but the UnityEngine namespace by requiring the internal sealed ExtensionOfNativeClassAttribute
on anything that inherits native classes. Furthermore, Unity does not searialize inherited classes well.
So, in review, I'm not able to hook into Rigidbody
directly (Please correct me if this is wrong!), and I'm not able to inhert from Rigidbody
directly (Please correct me if this is wrong!). I think the next best option is to:
ModRigidbody
, which makes a parellel implementation of all of Rigidbody
's members. This class does not actually inherit from Rigidbody
, but merely has members with all the same names / signatures as Rigidbody
.ModRigidbody
add the attribute [RequireComponent(typeof(Rigidbody))]
. Now I can add functionality to some ModRigidbody's members as I see fit, and have other members simply 'pass through' to transform.GetComponent<Rigidbody>()
.Rigidbody
over to ModRigidbody
.To me this feels quite sloppy. Is there a way to mod the functionality of Rigidbody
so that future users of this library will not have to change all of their Rigidbody
over to ModRigidbody
?
Your proposition seems reasonable given the constraints imposed by Unity, but why not create an extension method?
Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type.
I'll start by saying that even extending Rigidbody
directly will cause your consumers to migrate to using a new type in their implementations so creating a proxy is certainly a good start. However, if you want to promote consumers using Rigidbody
directly instead of a new type, then I recommend creating extension methods:
public static class ForceApplicationRigidbodyExtensions {
public static void ApplyDecayingForce(
this Rigidbody rigidbody,
Vector3 startingForce,
float decayRate,
TimeSpan lifetime) {
...
}
}
This allows consumers to invoke your methods directly off of their Rigidbody
instances:
var rigidbody = transform.GetComponent<Rigidbody>();
rigidbody.ApplyDecayingForce(Vector3.up * 10, 0.05f, TimeSpan.FromSeconds(5));
If you're not a fan of extension methods, then you could create something focused on mutating a given Rigidbody
instead:
public class RigidbodyForceApplicator {
private reaodnly Rigidbody _rigidbody;
public RigidbodyForceApplicator(Rigidbody rigidbody) =>
_rigidbody = rigidbody;
public void ApplyDecayingForce(
Rigidbody rigidbody,
Vector3 startingForce,
float decayRate,
TimeSpan lifetime) {
...
}
}
This allows consumers to be explicit while using only what they need:
var rigidbody = transform.GetComponent<Rigidbody>();
var forceApplicator = new RigidbodyForceApplicator(rigidbody);
forceApplicator.ApplyDecayingForce(Vector3.up * 10, 0.05f, TimeSpan.FromSeconds(5));
If you do create a proxy instead, then I recommend keeping the following points in mind:
Rigidbody
to fully support the mutations you have in mind as that almost never works out the way we intend.Rigidbody
as this just adds an extra method invocation that isn't necessary.Rigidbody
with.