Unity实现布料效果(软体效果)

原理

很好奇糖豆人这种软体效果是怎么实现的,于是查看了一些资料了解到可以通过改变mesh来使物体产生不一样的渲染效果。
主要通过类似弹簧的效果,点击物体后改变该物体的vertices,某个点离施力点越近则给它的初速度越大。初速度根据该点移动的距离慢慢减小,当减小为0后再次反弹至原点。

实现

外部接口为AddForce函数

using UnityEngine;
public class softBodyTest : MonoBehaviour {
    Mesh mesh;
    Vector3[] originalVertices;//原来的点
    Vector3[] displacedVertices;//改变后的点
    Vector3[] vertexVelocities;//每个点的当前速度
    [Header("弹簧力")]
    public float springForce = 20f;
    [Header("弹簧阻尼")]
    public float damping = 5;

    // Use this for initialization
    void Start() {
        mesh = GetComponent<MeshFilter>().mesh;
        originalVertices = mesh.vertices;
        displacedVertices = new Vector3[originalVertices.Length];
        for (int i = 0; i < displacedVertices.Length; i++)
        {
            displacedVertices[i] = originalVertices[i];
        }
        vertexVelocities = new Vector3[originalVertices.Length];
    }
	
	void Update () {
        for (int i = 0; i < displacedVertices.Length; i++)
        {
            var velocity = vertexVelocities[i];
            Vector3 displacement = displacedVertices[i] - originalVertices[i];
            velocity -= displacement * springForce * Time.deltaTime;//减小的加速度与弹簧力有关 该点与原点的距离相当于弹簧的压缩量
            velocity *= 1f - damping * Time.deltaTime;//防止弹簧反复横跳,增加阻尼
            vertexVelocities[i] = velocity;
            displacedVertices[i] += velocity * Time.deltaTime;
        }
        mesh.vertices = displacedVertices;
        mesh.RecalculateNormals();
	}

    public void AddForce(Vector3 point, Vector3 direction, float force)
    {
        Debug.DrawLine(Camera.main.transform.position, point);
        point = transform.InverseTransformPoint(point);
        for (int i = 0; i < displacedVertices.Length; i++)
        {
            AddForceToVertex(i, point, direction, force);
        }
    }

    private void AddForceToVertex(int i, Vector3 point,Vector3 direction, float force)
    {
        var pointToVertex = displacedVertices[i] - point;
        float attenuateForce = force / (0.1f + pointToVertex.sqrMagnitude); //距离越近力越大
        float velocity = attenuateForce * Time.deltaTime;
        vertexVelocities[i] -= direction.normalized * velocity; //初速度
    }
}

测试代码

if (Input.GetMouseButton(0))
        {
            Ray inputRay = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
            if (Physics.Raycast(inputRay, out hit))
            {
                var testScript = hit.collider.GetComponent<softBodyTest>();
                if (testScript)
                {
                    var point = hit.point;
                    testScript.AddForce(point, hit.normal, force);
                }
            }
        }

最终效果
在这里插入图片描述 在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张_0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值