Mesh网格撞击变形

物理碰撞

  • 两个游戏物体发生碰撞的必要条件:
  1. 发生碰撞的两个游戏物体有Collider(碰撞器)组件;
  2. 其中一个物体有Rigidbody(刚体)组件。
  • MonoBehaviour中的相关回调函数:
回调函数 详解
OnCollisionEnter (Collision) 当前碰撞器开始接触另一个碰撞器时被调用。
OnCollisionStay (Collision) 当前碰撞器持续接触另一个碰撞器时被调用。
OnCollisionExit (Collision) 当前碰撞器停止接触另一个碰撞器时被调用。

碰撞数据

物体发生碰撞时的碰撞数据存储于Collision对象中,相关属性:

  • articulationBody:与当前碰撞器发生碰撞的物体上的Articulation Body组件;
  • body:与当前碰撞器发生碰撞的物体上的Rigidbody或Articulation Body组件;
  • collider:与当前碰撞器发生碰撞的碰撞器;
  • contactCount:碰撞接触点的数量;
  • contacts:碰撞接触点数组,碰撞接触点包含位置和法线数据;
  • gameObject:与当前碰撞器发生碰撞的物体;
  • impulse:碰撞冲量;
  • relativeVelocity:两个碰撞对象的相对线性速度;
  • rigidbody:与当前碰撞器发生碰撞的物体上的Rigidbody组件;
  • transform:与当前碰撞器发生碰撞的物体的Transform组件。

撞击变形

  • 撞击判定:当relativeVelocity的长度大于一定阈值时,可以判定为撞击;
  • 网格变形:通过调整撞击物体上的网格顶点,使网格发生形变:
  1. 顶点位移量:计算网格顶点到碰撞接触点的距离,距离越近的变形程度应该越大,顶点位移量也就相应越大。
  2. 顶点位移方向:通过将relativeVelocity从世界空间转换到被撞击物体的局部空间获得顶点位移方向。
//变形发生的阈值
[SerializeField] private float deformationThreshold = 5f;
//变形影响的半径
[SerializeField] private float deformationRadius = .5f;

private void OnCollisionEnter(Collision collision)
{
    
    
    //两个碰撞对象的相对线性速度足够大时网格变形
    if (collision.relativeVelocity.magnitude > deformationThreshold)
    {
    
    
        //撞击的物体
        GameObject collideGameObject = collision.gameObject;
        //物体上的网格
        Mesh mesh = collideGameObject.GetComponent<MeshFilter>().sharedMesh;
        //网格上的顶点数组
        Vector3[] vertices = mesh.vertices;
        //遍历撞击接触点
        for (int i = 0; i < collision.contactCount; i++)
        {
    
    
            ContactPoint contactPoint = collision.GetContact(i);
            //全局坐标转撞击物体的局部坐标
            Vector3 world2LocalPoint = collideGameObject.transform.InverseTransformPoint(contactPoint.point);
            //遍历网格顶点 顶点移位形成变形
            for (int j = 0; j < vertices.Length; j++)
            {
    
    
                //网格顶点到撞击接触点的距离
                float magnitude = (world2LocalPoint - vertices[j]).magnitude;
                //在影响范围内
                if (magnitude < deformationRadius)
                {
    
    
                    //位移量
                    float delta = (deformationRadius - magnitude) / deformationRadius * .1f;
                    //位移
                    vertices[j] -= collideGameObject.transform
                        .InverseTransformDirection(collision.relativeVelocity) * delta;
                }
            }
        }
        //更新网格顶点
        mesh.vertices = vertices;
        mesh.RecalculateNormals();
        mesh.RecalculateBounds();
        //重启碰撞
        collision.collider.enabled = false;
        collision.collider.enabled = true;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42139931/article/details/135221137