扩展Unity3d刚体的最佳方式?



我正在为Unity3d设计一个物理类库,并希望能够将功能注入Unity3d的Rigidbody类,但我的理解是,没有办法直接做到这一点,同时仍然能够针对所有平台。

我认为下一个最好的事情可能是创建一个直接继承Rigidbody的新类。然而,它看起来像unity已经阻止了这种情况发生在任何事情,但UnityEngine名称空间要求internal sealed ExtensionOfNativeClassAttribute上的任何继承原生类。此外,Unity不能很好地序列化继承的类。

所以,回顾一下,我不能直接挂钩到Rigidbody(如果这是错误的,请纠正我!),我不能直接从Rigidbody继承(如果这是错误的,请纠正我!)。我认为下一个最好的选择是:

  1. 创建一个新的Monobehavior,假设它叫做ModRigidbody,它并行实现了Rigidbody的所有成员。这个类实际上并不继承Rigidbody,而只是拥有与Rigidbody具有相同名称/签名的成员。
  2. ModRigidbody上添加[RequireComponent(typeof(Rigidbody))]属性。现在我可以添加功能到一些ModRigidbody的成员,因为我认为合适,并有其他成员简单地"通过"到transform.GetComponent<Rigidbody>()
  3. 让任何最终用户(程序员)将所有对Rigidbody的引用更改为ModRigidbody

对我来说这感觉很马虎。有没有办法修改Rigidbody的功能,以便将来这个库的用户不必将所有的Rigidbody更改为ModRigidbody?

考虑到Unity所施加的限制,你的主张似乎是合理的,但为什么不创建一个扩展方法呢?

扩展方法使您能够"添加";方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。


我首先会说,即使直接扩展Rigidbody也会导致您的消费者在实现中迁移到使用新类型,因此创建代理当然是一个好的开始。但是,如果您希望直接使用Rigidbody而不是新类型来促进消费者,那么我建议创建扩展方法:

public static class ForceApplicationRigidbodyExtensions {
public static void ApplyDecayingForce(
this Rigidbody rigidbody,
Vector3 startingForce,
float decayRate,
TimeSpan lifetime) {
...
}
}

这允许消费者直接从他们的Rigidbody实例调用你的方法:

var rigidbody = transform.GetComponent<Rigidbody>();
rigidbody.ApplyDecayingForce(Vector3.up * 10, 0.05f, TimeSpan.FromSeconds(5));

如果您不是扩展方法的粉丝,那么您可以创建一些专注于突变给定Rigidbody的东西:

public class RigidbodyForceApplicator {
private reaodnly Rigidbody _rigidbody;
public RigidbodyForceApplicator(Rigidbody rigidbody) =>
_rigidbody = rigidbody;
public void ApplyDecayingForce(
Rigidbody rigidbody,
Vector3 startingForce,
float decayRate,
TimeSpan lifetime) {
...
}
}

这允许消费者在只使用他们需要的东西时是显式的:

var rigidbody = transform.GetComponent<Rigidbody>();
var forceApplicator = new RigidbodyForceApplicator(rigidbody);
forceApplicator.ApplyDecayingForce(Vector3.up * 10, 0.05f, TimeSpan.FromSeconds(5));

如果您要创建代理,那么我建议您记住以下几点:

  • 不要指望Rigidbody完全支持你想要的突变,因为这几乎从来没有像我们想要的那样工作。
  • 不要创建直接手动完成Rigidbody的直通实现,因为这只是增加了一个不必要的额外方法调用。
  • 只公开提供Rigidbody补充功能的函数。

相关内容

  • 没有找到相关文章

最新更新