前言

用来记录一些unity的好看的效果实现哈哈,话不多说,开撸

流动虚线框

用四个LineRender来实现流动虚线框的效果,看起来很简单,但是如果没做过确实有点无从下手。

先看效果:

1713796248375.gif

首先准备一个

虚线3 (1).png

这样的一节的虚线png文件,然后创建一个这样的材质:

屏幕截图 2024-04-22 222750.png

然后把材质设置成:

屏幕截图 2024-04-22 224109.png
(注意贴图间的拼接模式)

要注意Shader的选择,然后把png拖进纹理中

然后按以下的图来完成布局:
屏幕截图 2024-04-22 222843.png
屏幕截图 2024-04-22 222855.png
屏幕截图 2024-04-22 222809.png

最后把代码写进脚本

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
using UnityEngine;

public class LineCtrler : MonoBehaviour
{
[SerializeField] public LineRenderer lineRenderer1;
[SerializeField] public LineRenderer lineRenderer2;
[SerializeField] public LineRenderer lineRenderer3;
[SerializeField] public LineRenderer lineRenderer4;
private Material material1;
private Material material2;
private Material material3;
private Material material4;
private Vector2 tiling;
private Vector2 offset;
private int mainTexProperty;
private float timer = 0;

// 频率间隔
[SerializeField]
private float frequency = 0.03f;

//流动速度
[SerializeField]
private float moveSpeed = 0.04f;

void OnEnable()
{
// 缓存材质实例
material1 = lineRenderer1.material;
material2 = lineRenderer2.material;
material3 = lineRenderer3.material;
material4 = lineRenderer4.material;

// 缓存属性id,防止下面设置属性的时候重复计算名字的哈希
mainTexProperty = Shader.PropertyToID("_MainTex");

offset = Vector2.zero;
}

private void Update()
{
timer += Time.deltaTime;
if(timer >= frequency)
{
timer = 0;
offset -= new Vector2(moveSpeed, 0);
material1.SetTextureOffset(mainTexProperty, offset);
material2.SetTextureOffset(mainTexProperty, offset);
material3.SetTextureOffset(mainTexProperty, offset);
material4.SetTextureOffset(mainTexProperty, offset);
}
}
}

然后把几个物体的linerender拖进脚本,就得到了一个简单的虚线流动框了!

可折叠与动态添加任务的任务栏

先看效果

示例

任务的模板是在Unity的滑动视图中的content操作。
先给Content物体添加Vertical Layout Group和Content Size Fitter组件来适应Idea的变化。

在下图中,Idea_Content是一个滑动视图,然后再Content中进行了任务的编写,符合人们的逻辑,Idea为整个分级任务,然后Idea_Content用来生成子任务。其中Idea和Idea_Content都有Vertical Layout Group组件,不添加Content Size Fitter组件的原因是因为如果两个相同的Content Size Fitter组件在父子级关系的物体上,就会出现计算异常的BUG,出现计算错误甚至报错的情况。

层级

源码如下:

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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Idea : MonoBehaviour
{
private float time = 0;
private float IdeaContentHeight; //子任务高度

public MyState state;

public Transform content_F;
public List<GameObject> childObject;
public GameObject IdeaPra; //子任务的预制体

private void Start()
{
state = MyState.Selected;
childObject = new List<GameObject>();
IdeaContentHeight = IdeaPra.GetComponent<RectTransform>().sizeDelta.y;
}

private void Update()
{
if (time - 5 > 0)
{
time = 0;
AddItemContent("建筑");
}

time += Time.deltaTime;
}


//折叠按钮的代码
public void OnButtonDown()
{
if (state == MyState.Selected)
{
state = MyState.Unselected;
foreach (var item in childObject)
{
item.SetActive(false);
SetContentSize();
}
}
else
{
state = MyState.Selected;
foreach (var item in childObject)
{
item.SetActive(true);
SetContentSize();
}
}
}

//加入新的子任务
public void AddItemContent(string name)
{
if (content_F == null)
{
content_F = transform.GetChild(1);
}

GameObject idea = Instantiate<GameObject>(IdeaPra, content_F);
idea.GetComponent<Text>().text = name;
childObject.Add(idea);
if (state == MyState.Unselected)
{
idea.SetActive(false);
}

SetContentSize();
}


//以下代码为动态更新高度来适应Vertical Layout Group和Content Size Fitter组件
public void ChangeHeight(GameObject item, float height)
{
RectTransform rectTransform = item.GetComponent<RectTransform>();

if (rectTransform != null)
{
rectTransform.sizeDelta = new Vector2(rectTransform.sizeDelta.x, height);
}
}

public void SetContentSize()
{
if (state == MyState.Selected)
{
ChangeHeight(content_F.gameObject, childObject.Count * IdeaContentHeight);
SetSize();
}
else
{
ChangeHeight(content_F.gameObject,0);
SetSize();
}
}

public void SetSize()
{
float height = 0;
for (int i = 0; i < this.transform.childCount; i++)
{
RectTransform rectTransform = transform.GetChild(i).GetComponent<RectTransform>();

if (rectTransform != null)
{
height += rectTransform.sizeDelta.y;
}
}

ChangeHeight(this.gameObject, height);
}
}