如何在没有 SphereCollider.Create() 工厂方法调用的情况下为 Unity.Physics.SphereCollider 结构使用 CastRay()
How to CastRay() for Unity.Physics.SphereCollider struct without SphereCollider.Create() factory method call
如何在没有 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;
}
在我的项目中,我使用以下辅助方法来转换任何 Collider(需要不安全的代码执行标志,因为它使用指针)
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 class 其中包含 this
//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
SphereCollider
结构包含一些隐藏的私有字段,需要调用 Init(args)
方法才能为它们设置正确的值:
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 sphere = default(SphereCollider);
sphere.Init( geometry , CollisionFilter.Default , Material.Default );
return sphere.CastRay( ray , out raycastHit );
}
不过
此方法是私有的 (chances are this may change)。
要使 Init
方法可用,您需要修改 ...\com.unity.physics@0.5.0-preview.1\Unity.Physics\Collision\Colliders\Physics_SphereCollider.cs
源文件并将其设为 public.
如何在没有 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;
}
在我的项目中,我使用以下辅助方法来转换任何 Collider(需要不安全的代码执行标志,因为它使用指针)
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 class 其中包含 this
//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
SphereCollider
结构包含一些隐藏的私有字段,需要调用 Init(args)
方法才能为它们设置正确的值:
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 sphere = default(SphereCollider);
sphere.Init( geometry , CollisionFilter.Default , Material.Default );
return sphere.CastRay( ray , out raycastHit );
}
不过
此方法是私有的 (chances are this may change)。
要使 Init
方法可用,您需要修改 ...\com.unity.physics@0.5.0-preview.1\Unity.Physics\Collision\Colliders\Physics_SphereCollider.cs
源文件并将其设为 public.