最好的方式来扩展Unity3d刚体?

1dkrff03  于 2023-04-07  发布在  其他
关注(0)|答案(1)|浏览(190)

我正在为Unity3d设计一个物理类库,并希望能够将功能挂接到Unity3d的Rigidbody类中,但我的理解是,没有办法直接做到这一点,同时仍然能够针对所有平台。
我认为下一个最好的事情可能是创建一个直接从Rigidbody继承的新类。然而,看起来Unity已经阻止了这在UnityEngine命名空间之外的任何地方发生,因为它要求在继承本机类的任何地方都使用internal sealed ExtensionOfNativeClassAttribute。此外,Unity没有很好地密封继承的类。
所以,在回顾中,我不能直接挂钩到Rigidbody(如果这是错误的,请纠正我!),我不能直接从Rigidbody继承(如果这是错误的,请纠正我!)。我认为下一个最好的选择是:
1.创建一个新的Monobehavior,假设它被称为ModRigidbody,它使Rigidbody的所有成员的并行实现。这个类实际上并不继承自Rigidbody,而只是拥有与Rigidbody相同名称/签名的成员。
1.在ModRigidbody上添加属性[RequireComponent(typeof(Rigidbody))]。现在我可以根据需要为ModRigidbody的一些成员添加功能,并让其他成员简单地“传递”到transform.GetComponent<Rigidbody>()
1.让任何最终用户(程序员)将他们对Rigidbody的所有引用更改为ModRigidbody
对我来说,这感觉相当草率。有没有一种方法可以修改Rigidbody的功能,这样这个库的未来用户就不需要将他们所有的Rigidbody都更改为ModRigidbody

ctehm74n

ctehm74n1#

考虑到Unity所施加的限制,您的提议似乎是合理的,但为什么不创建一个extension method呢?
扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。
首先我会说,即使直接扩展Rigidbody也会导致你的消费者在他们的实现中迁移到使用新类型,所以创建proxy当然是一个好的开始。但是,如果你想促进消费者直接使用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的功能的函数。

相关问题