Unity 水体效果模拟

内容为学习siki学院课程后做的笔记,感兴趣可以查看原课程。

制作水滴

水体是由一个个水滴构成的,所以先实现一个水滴。
2D Object -> Sprites ->Circle创建一个2D circle作为一个水滴,调整到适合大小,修改颜色为蓝色。
在这里插入图片描述
添加三个Sorting Layers,用于控制显示的先后顺序,下面的优先级高,显示在前面,水滴的Sorting Layers改为Water。
添加Circle Collider 2D,Rigidbody 2D,Trail Renderer三个组件。
在这里插入图片描述
Circle Collider 2D的碰撞体范围改小一些,使得多个水滴接触时有相溶的感觉。
在这里插入图片描述
在这里插入图片描述
Rigidbody 2D主要是添加重力效果,新建一个2D物理材质添加到这个Rigidbody 2D的材质上,修改弹性为0.2,使得它落到障碍物上时有一点弹性。
在这里插入图片描述
Trail Renderer用于实现水滴掉落时拖尾的效果,修改颜色和水滴一致,调整拖尾线的宽度,前面粗后面细,Time是拖尾存在时间,改短一点即可,材质使用默认材质。
在这里插入图片描述
将这个水滴保存为prefab。

水龙头生成水

在这里插入图片描述
弄一个简单场景,上面水龙头用来指示出水的地方,下面的Square用做障碍物,添加Box Collider 2D,Sorting Layers改为Block,新建如下脚本挂在相机上。

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;

public class WaterSimulation : MonoBehaviour
{
    //水龙头
    public GameObject tap;
    //水滴
    public GameObject water;
    public int waterNum;

    private Vector3 _tapPos;
    private WaitForSeconds _waitForSeconds = new WaitForSeconds(0.02f);
    
    void Start()
    {
        _tapPos = tap.transform.position;
    }

    private void OnGUI()
    {
        if (GUI.Button(new Rect(0, 0, 100, 50),"生成水"))
        {
            StartCoroutine(SpawnWater());
        }
    }
    
    private IEnumerator SpawnWater()
    {
        for (int i = 0; i < waterNum; ++i)
        {
            Vector3 pos = new Vector3(Random.Range(_tapPos.x - 0.03f, _tapPos.x - 0.03f), 
            	_tapPos.y - 0.3f, 0);
            Instantiate(water, pos, Quaternion.identity, transform);
            yield return _waitForSeconds;
        }
    }
}

杯子接水

在这里插入图片描述
场景中添加一个杯子,Sorting Layers改为Glass,加上刚体和Edge Colloder 2D,刚体质量改大一些,防止被水冲走,边缘碰撞器由线段组成,可以自由调整成任何形状,首尾不需要相连。
在这里插入图片描述
在这里插入图片描述
在场景中添加一个圆和菱形,分别添加Circle Collider 2D和Polygon Collider 2D,都添加Rigidbody 2D,圆的mass设为50,菱形的mass设为1,质量大的不容易被推动。

铰链

在这里插入图片描述
新建两个Square和一个Circle,分别添加对应的Collider ,置于一个空物体下面,在根节点上添加Rigidbody 2D和Hinge Joint 2D,铰链的Anchor要对齐到圆中心。
在这里插入图片描述
铰链可以使两个有刚体的GameObject产生相互作用,发生碰撞时会有旋转的效果。

使用LineRenderer绘制障碍物

在这里插入图片描述
原理是在LineRenderer相邻点之间添加碰撞体,根节点上添加刚体,补充上面代码如下:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;

public class WaterSimulation : MonoBehaviour
{
    //水龙头
    public GameObject tap;
    //水滴
    public GameObject water;
    public int waterNum;
    public LineRenderer lineRenderer;

    private Vector3 _tapPos;
    private WaitForSeconds _waitForSeconds = new WaitForSeconds(0.02f);
    private Camera _camera;
    private List<Vector2> _pointList = new List<Vector2>();
    private HashSet<Vector2> _pointHashSet = new HashSet<Vector2>();
    private bool _canDraw = true;
    
    void Start()
    {
        _tapPos = tap.transform.position;
        lineRenderer.positionCount = 0;
        _camera = Camera.main;
    }

    private void OnGUI()
    {
        if (GUI.Button(new Rect(0, 0, 100, 50),"生成水"))
        {
            StartCoroutine(SpawnWater());
        }
    }
    
    private IEnumerator SpawnWater()
    {
        for (int i = 0; i < waterNum; ++i)
        {
            Vector3 pos = new Vector3(Random.Range(_tapPos.x - 0.03f, _tapPos.x - 0.03f), _tapPos.y - 0.3f, 0);
            Instantiate(water, pos, Quaternion.identity, transform);
            yield return _waitForSeconds;
        }
    }

    private void Update()
    {
        if (Input.GetMouseButton(0) && _canDraw)
        {
            //鼠标的位置从屏幕空间转换到世界空间
            Vector2 pos = _camera.ScreenToWorldPoint(Input.mousePosition);
            if (!_pointHashSet.Contains(pos))
            {
                _pointHashSet.Add(pos);
                _pointList.Add(pos);
                //添加点
                int pointCount = ++lineRenderer.positionCount;
                lineRenderer.SetPosition(pointCount - 1, pos);
                
                //在两点之间添加碰撞体
                if (pointCount > 1)
                {
                    Vector2 point1 = _pointList[pointCount - 2];
                    Vector2 point2 = _pointList[pointCount - 1];
                    GameObject go = new GameObject("Collider");
                    go.transform.parent = lineRenderer.transform;
                    //碰撞体中心在两点之间
                    go.transform.localPosition = (point1 + point2) / 2;
                    var boxCollider = go.AddComponent<BoxCollider2D>();
                    //碰撞体长度等于两点之间连线的长度,宽度等于线的宽度
                    boxCollider.size = new Vector2((point2 - point1).magnitude, lineRenderer.startWidth);
                    //碰撞体的右侧朝向线的方法
                    go.transform.right = (point2 - point1).normalized;
                }
            }
        }

        if (Input.GetMouseButtonUp(0))
        {
            _canDraw = false;
            if (lineRenderer.gameObject.GetComponent<Rigidbody2D>() == null) 
                lineRenderer.gameObject.AddComponent<Rigidbody2D>();
        }
    }
}
  • 3
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity是一款强大的游戏开发引擎,它在物理模拟和图形渲染方面具有出色的表现。在Unity中,我们可以通过使用材质、纹理和粒子系统等功能来实现动态水体涟漪效果。 首先,我们需要创建一个水面模型,可以使用Unity内置的平面网格,或者导入自定义的水体模型。然后,我们可以为水面添加一个适用于涟漪效果的材质。这个材质应该包括透明度、反射和折射等属性,以实现真实的水体效果。 为了实现动态涟漪效果,我们可以使用Unity的粒子系统。在水体表面的特定位置,通过发射水滴粒子,我们可以模拟水面上的涟漪效果。这些粒子应该具有适当的速度和角度,以便能够溅起涟漪效果。 此外,我们还可以利用Unity的碰撞检测功能,使得水滴粒子与水体表面发生碰撞时产生涟漪效果。当水滴粒子与水面碰撞时,我们可以通过修改水面的顶点位置,以及更新法线和切线来实现漂移和波纹的效果。这样,当水滴在水面上溅起时,周围的水面将产生波动,并形成涟漪效果。 为了增强涟漪效果的真实感,我们可以通过调整涟漪的扩散范围、持续时间和淡化效果来控制涟漪的外观。另外,还可以使用图形着色器和纹理贴图来增加水体的细节和真实感。 总之,在Unity中实现动态水体涟漪效果,我们可以使用材质、粒子系统、碰撞检测和纹理贴图等功能来模拟真实的涟漪效果。这些功能可以帮助我们创造出逼真的水体效果,提升游戏或仿真场景的视觉体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值