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
来做,谢谢你的建议,但是平面的大小(即,平面的边界形状)直到运行时才会确定,实际上它可能会在运行时更改。因此,我无法在编辑器中编辑边界,并在运行时使用