C# 统一限制平面上的运动对象
我想限制平面上的移动对象(平面可能是或不是正方形),这是原型: 我在平面上附加了一个网格碰撞器,希望用它来限制球体的移动,球体将随机移动,其想法是当球移动到边缘时,速度将被反射,这样它就不会从平面上掉落,如下所示:C# 统一限制平面上的运动对象,c#,unity3d,C#,Unity3d,我想限制平面上的移动对象(平面可能是或不是正方形),这是原型: 我在平面上附加了一个网格碰撞器,希望用它来限制球体的移动,球体将随机移动,其想法是当球移动到边缘时,速度将被反射,这样它就不会从平面上掉落,如下所示: public class BallScript : MonoBehaviour { // Use this for initialization void Start () { GetComponent<Rigidbody>().vel
public class BallScript : MonoBehaviour {
// Use this for initialization
void Start () {
GetComponent<Rigidbody>().velocity = new Vector3(0.1f,0,0.1f);
}
private void OnCollisionExit(Collision collision)
{
GetComponent<Rigidbody>().velocity = -GetComponent<Rigidbody>().velocity;
}
}
公共类BallScript:monobhavior{
//用于初始化
无效开始(){
GetComponent().速度=新矢量3(0.1f,0,0.1f);
}
私有void OnCollisionExit(碰撞)
{
GetComponent().velocity=-GetComponent().velocity;
}
}
但球一直落在边缘
我无法制作边缘碰撞器,因为直到运行时才确定平面的形状
有没有办法做到这一点?当对象不再与另一个对象碰撞时,调用
OnCollisionExit
函数。在您的情况下,当球不再接触平面时,而不是当球位于平面边缘时,将调用它
最安全的方法是使用BoxCollider。我建议您只使用Unity的立方体原语,它带有BoxCollider。其上的网格将非常有用,并且在调整BoxCollider的大小时应作为视觉指南
1。转到GameObject-->3D Object-->Cube并创建新的多维数据集对象。查看飞机的形状,您将需要6个BoxCollider,这意味着您需要6个立方体
2。调整、移动和旋转每一个,直到它们覆盖平面的每一侧
3。创建新层并将其称为“边界”。选择每个立方体并将层设置为“边界”
4。需要编辑-->项目设置-->物理,并使用层碰撞矩阵确保“边界”不能与“边界”碰撞
5。禁用或删除每个多维数据集的MeshRenderer
,仅此而已
问题中的代码是不必要的,但如果您仍希望它反映出来,请使用OnCollisionCenter
并检查球何时撞到墙上
连接到球上:
Rigidbody rb;
public float force = 50;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void OnCollisionEnter(Collision col)
{
if (col.collider.CompareTag("Boundary"))
rb.AddForce(col.contacts[0].normal * force, ForceMode.Impulse);
}
刚体rb;
公众浮力=50;
void Start()
{
rb=GetComponent();
}
无效碰撞中心(碰撞柱)
{
if(col.collider.CompareTag(“边界”))
rb.AddForce(col.contacts[0]。正常*力,力模式。脉冲);
}
当对象不再与另一个对象碰撞时,调用OnCollisionExit
函数。在您的情况下,当球不再接触平面时,而不是当球位于平面边缘时,将调用它
最安全的方法是使用BoxCollider。我建议您只使用Unity的立方体原语,它带有BoxCollider。其上的网格将非常有用,并且在调整BoxCollider的大小时应作为视觉指南
1。转到GameObject-->3D Object-->Cube并创建新的多维数据集对象。查看飞机的形状,您将需要6个BoxCollider,这意味着您需要6个立方体
2。调整、移动和旋转每一个,直到它们覆盖平面的每一侧
3。创建新层并将其称为“边界”。选择每个立方体并将层设置为“边界”
4。需要编辑-->项目设置-->物理,并使用层碰撞矩阵确保“边界”不能与“边界”碰撞
5。禁用或删除每个多维数据集的MeshRenderer
,仅此而已
问题中的代码是不必要的,但如果您仍希望它反映出来,请使用OnCollisionCenter
并检查球何时撞到墙上
连接到球上:
Rigidbody rb;
public float force = 50;
void Start()
{
rb = GetComponent<Rigidbody>();
}
void OnCollisionEnter(Collision col)
{
if (col.collider.CompareTag("Boundary"))
rb.AddForce(col.contacts[0].normal * force, ForceMode.Impulse);
}
刚体rb;
公众浮力=50;
void Start()
{
rb=GetComponent();
}
无效碰撞中心(碰撞柱)
{
if(col.collider.CompareTag(“边界”))
rb.AddForce(col.contacts[0]。正常*力,力模式。脉冲);
}
所以这里有一个想法,因为OP同意将此作为答案
public Layer[] layerPriorities =
{
Layer.Enemy,
Layer.Walkable
};
[SerializeField] float distanceToBackground = 100f;
public delegate void OnLayerChange(Layer newLayer); // declare new delegate type
//lets use event for the protection of the layerchanges
public event OnLayerChange onlayerChange; // instantiate a observer set
//Look for and return priority layer hit
foreach (Layer layer in layerPriorities)
{
var hit = RaycastForLayer(layer);
if (hit.HasValue)
{
raycastHit = hit.Value;
if(layerHit != layer){ //if layer has changed
layerHit = layer;
onlayerChange(layer); //call the delegate
}
layerHit = layer;
return;
}
}
// otherwise return background hit
raycastHit.distance = distanceToBackground;
layerHit = Layer.RaycastEndStop;
}
//? is a nullable parameter
RaycastHit? RaycastForLayer(Layer layer)
{
/*(Use a bitshift) <<*/
int layerMask = 1 << (int)layer; // lets do masking formation
Ray ray = viewCamera.ScreenPointToRay(Input.mousePosition);
RaycastHit hit; //used as an out parameter
bool hasHit = Physics.Raycast(ray, out hit, distanceToBackground, layerMask);
if (hasHit)
{
return hit;
}
return null;
}
作为Layer.敌军,
您可以将其设置为NotWalkable
这取决于您
因此,这里缺少的小部分只是计算球到平面边缘的距离,而不是单击它。这就是我要告诉你的关于
SqrMagnitude
的内容,所以这里有一个想法,OP同意将此作为答案
public Layer[] layerPriorities =
{
Layer.Enemy,
Layer.Walkable
};
[SerializeField] float distanceToBackground = 100f;
public delegate void OnLayerChange(Layer newLayer); // declare new delegate type
//lets use event for the protection of the layerchanges
public event OnLayerChange onlayerChange; // instantiate a observer set
//Look for and return priority layer hit
foreach (Layer layer in layerPriorities)
{
var hit = RaycastForLayer(layer);
if (hit.HasValue)
{
raycastHit = hit.Value;
if(layerHit != layer){ //if layer has changed
layerHit = layer;
onlayerChange(layer); //call the delegate
}
layerHit = layer;
return;
}
}
// otherwise return background hit
raycastHit.distance = distanceToBackground;
layerHit = Layer.RaycastEndStop;
}
//? is a nullable parameter
RaycastHit? RaycastForLayer(Layer layer)
{
/*(Use a bitshift) <<*/
int layerMask = 1 << (int)layer; // lets do masking formation
Ray ray = viewCamera.ScreenPointToRay(Input.mousePosition);
RaycastHit hit; //used as an out parameter
bool hasHit = Physics.Raycast(ray, out hit, distanceToBackground, layerMask);
if (hasHit)
{
return hit;
}
return null;
}
作为Layer.敌军,
您可以将其设置为NotWalkable
这取决于您
因此,这里缺少的小部分只是计算球到平面边缘的距离,而不是单击它。这就是我告诉你的
SqrMagnitude
当你说边缘碰撞器时,你的意思是吗?不,我注意到有一个精确的2d边缘碰撞器,但不是3d,我的意思是建造某种“墙”在平面边缘周围使用碰撞器将球保持在内部HMMM你试过做吗?@TheGinxx009你是说从球上进行光线投射并检测平面的边缘面吗?你可以使用SqrMagnitude
和raycast
当你说边缘碰撞器时,你的意思是?不,我注意到有一个精确的2d边缘碰撞器,但不是3d,我的意思是建造某种“墙”使用collidersHmmm在平面边缘周围使球保持在内部你尝试过做一次吗?@TheGinxx009你是说从球上进行光线投射并检测平面的边缘面吗?你可以使用SqrMagnitude
和raycast
来做,谢谢你的建议,但是平面的大小(即,平面的边界形状)直到运行时才会确定,实际上它可能会在运行时更改。因此,我无法在编辑器中编辑边界,并在运行时使用