首页 > 解决方案 > 如何在没有 SphereCollider.Create() 工厂方法调用的情况下对 Unity.Physics.SphereCollider 结构进行 CastRay()

问题描述

如何在没有 SphereCollider.Create() 工厂方法调用的情况下对 Unity.Physics.SphereCollider 结构进行 CastRay()(我认为会导致堆分配)。

下面的代码不起作用,也不知道究竟是为什么:

using Physics = Unity.Physics;
 
bool TraceRaySphere
(
    float3 spherePos ,
    float sphereRadius ,
    float3 rayStart ,
    float3 rayEnd ,
    out Physics.RaycastHit raycastHit
)
{
    var ray = new Physics.RaycastInput{
        Start   = rayStart ,
        End     = rayEnd ,
        Filter  = Physics.CollisionFilter.Default
    };
    var geometry  = new Physics.SphereGeometry{
        Center  = spherePos ,
        Radius  = sphereRadius
    };
    var sphere = new Physics.SphereCollider{
        Geometry    = geometry ,
        Filter      = Physics.CollisionFilter.Default
    };
    return sphere.CastRay( ray , out raycastHit );
}

这可行,但使用SphereCollider.Create(geometry)了我想摆脱的提到的工厂方法(如果可能的话):

public static bool TraceRaySphere
(
    float3 spherePos ,
    float sphereRadius ,
    float3 rayStart ,
    float3 rayEnd ,
    out RaycastHit raycastHit
)
{
    var ray = new RaycastInput{
        Start   = rayStart ,
        End     = rayEnd ,
        Filter  = CollisionFilter.Default
    };
    var geometry  = new SphereGeometry{
        Center  = spherePos ,
        Radius  = sphereRadius
    };
    var sphereBlobAsset = SphereCollider.Create( geometry );
    bool didHit = sphereBlobAsset.Value.CastRay( ray , out raycastHit );
    sphereBlobAsset.Dispose();
    return didHit;
}

标签: unity3dphysics

解决方案


在我的项目中,我使用以下辅助方法来投射任何碰撞器(需要不安全的代码执行标志,因为它与指针一起工作)

public static unsafe bool ColliderCast(float3 rayFrom, float3 rayTo, quaternion rotation, CollisionWorld collisionWorld, PhysicsCollider collider)
{
    ColliderCastInput input = new ColliderCastInput()
    {
        Collider = (Collider*)collider.Value.GetUnsafePtr(),
        Orientation = rotation,
        Start = rayFrom,
        End = rayTo
    };

    return collisionWorld.CastCollider(input);
}

而且我还有一个包含这个的 CollisionGeome trySingleton 类

//Cache geometries (float3 = size, float3 = center)
private IDictionary<Tuple<float3, float3>, BoxGeometry> boxGeometries;

public BoxGeometry CreateOrGetBoxGeometry(float3 size, float3 center)
{
   
    if(this.boxGeometries == null)
    {
        this.boxGeometries = new Dictionary<Tuple<float3,float3>, BoxGeometry>();
    }

    Tuple<float3, float3> key = new Tuple<float3, float3>(size, center);

    if(!this.boxGeometries.ContainsKey(key))
    {
        this.boxGeometries.Add(key, new BoxGeometry { Size = key.Item1, Center = key.Item2, Orientation = quaternion.identity });
    }

    return this.boxGeometries[key];
}

这允许我使用

BoxCollider.Create
(
    CollisionGeomeotrySingleton.Instance.CreateOrGetBoxGeometry(5, 5), 
    CollisionFilterSingleton.Instance.CollidesWithPlayerFilter
)

您现在可以更进一步,将 BoxCollider 也存储在 CollisionGeometrySingleton 中


推荐阅读