当前位置:   article > 正文

Unity 水体效果模拟_2d水体制作

2d水体制作

内容为学习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;
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

杯子接水

在这里插入图片描述
场景中添加一个杯子,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>();
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/636917
推荐阅读
相关标签
  

闽ICP备14008679号