废话不多直接上结果,如果需要的是这种结果的话,请跟我一步步做完以下步骤,没有耐心可以直接看代码
下面就简单介绍一下思路
需求分析
1.点随机产生并向随机方向以随机的速度匀速移动
2.点与点之间在一定距离内有细线连接,并且有淡入淡出的效果。
3.鼠标在画面中移动时,能够与其他点产生互动
1.1点的实现,如何绘制一个点?
在Js里,我们需要用代码绘制这个点,但在Unity中,我们完全可以通过预制件来完成这项工作 XD。
点的本质就是一个圆,所以我们只需要创建一个空物体,添加Canvas组件,并将Canvas UI Scale Mode设置为World Space,里面放上一张image图片,这个点就制作完毕了。但是注意,我们需要用它来做连线效果,所以我们也要给它加上LineRender组件。
1.2现在我们该让这个点动起来啦!
首先我们需要一个速度,来控制点的移动快慢
public struct gamectrl
{
public static float speed = 0.3f;
}
其次我们需要一个init的函数,在初始化时,给这个点一个随机的位置和一个随机的方向
void Init()
{
thispoint.position = new Vector2(Random.Range(-9.0f, 9.0f), Random.Range(-5.0f, 5.0f));
way = new Vector2(Random.Range(-1.0f, 1.0f), Random.Range(-1.0f, 1.0f));
way = way.normalized;
}
2.1在动起来的点与点之间,我们需要一根连线。
首先建立一个泛型,来管理这个点周围的点
private List<Transform> points = new List<Transform>();
然后我们使用触发器,来在合适的时候执行连线事件,当触发器接触的时候,触发OnTriggerEnter2D事件,在各个事件中我们把碰撞到的点添加到泛型中;当有点离开碰撞器范围之后,触发OnTriggerExit2D时间,把这个点从泛型中移出去。
private void OnTriggerEnter2D(Collider2D collision)
{
points.Add(collision.transform);
}
private void OnTriggerExit2D(Collider2D collision)
{
int i = 0;
foreach (Transform ts in points)
{
if (collision.gameObject.name == ts.name)
{
if (points.Count == 1) { points.Remove(points[points.Count - 1]); return; }
for (int n = i; n < points.Count - 1; n++)
{
points[n] = points[n + 1];
}
points.Remove(points[points.Count - 1]);
return;
}
i++;
}
}
我们在Update函数中处理线段,我们把list中的所有点与当前点连接起来。这里需要注意的是,要把用不到的线段处理好,比如我们设置线段节数是30,那最后把不需要用到的线段节点藏到当前点的下面( LR.SetPosition(i, thispoint.position);)。
LR.SetPosition(0, thispoint.position);
foreach (Transform tr in points)
{
LR.SetPosition(i * 2 - 1, tr.position);
if (i == 15) break;
LR.SetPosition(i * 2, thispoint.position);
i++;
}
for (i = (i - 1) * 2; i <= 29; i++)
{
LR.SetPosition(i, thispoint.position);
}
这样就完成点与点之间的连线了啦!有的小伙伴可能急眼了:“哪有!场景里根本什么都没出现~!” XDXD,那是因为此时此刻我们场景里只有一个孤零零的点,小伙伴们可以根据自己的需求,自由复制这个点在场景中(最简单的就是Ctrl+D),来控制点的数量。
2.2如何实现淡出淡入?
原则上,设置rgba颜色值可实现带透明度的颜色,透明度的计算方式为,(临界值距离 - 实际距离) / 临界值距离,这样就可以实现两点距离越远线条颜色越淡。再通过动画不停渲染,就可以造成视觉上淡入淡出的效果。
但在unity中,我们可以不使用代码,来实现这件事情
在LineRender组件中,有个Color选项,点开后有四个滑块,点击上方的两个滑块,就可以设置开端和末尾的Alpha值了。
3.如何实现鼠标在canvas中移动的交互效果?
思路:就是我们拎出一个点,只要将其位置与鼠标位置对齐,便可以实现这个效果了。
具体做法就是
添加一个新预制件,配置和点的内容相同,但是要使用一个新脚本用于更新需要跟踪鼠标移动的点的位置,注意隐藏掉这个预制件的圆形图片,因为鼠标并不是一个点XD
以上就是全部内容了,下面附上源码
请挂载至预制件身上的
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public struct gamectrl
{
public static float speed = 0.3f;
}
public class DrawLine1 : MonoBehaviour
{
private Transform thispoint;
private Vector2 way;
private LineRenderer LR;
private List<Transform> points = new List<Transform>();
// Use this for initialization
void Start()
{
LR = this.GetComponent<LineRenderer>();
thispoint = this.transform;
Init();
LR.SetVertexCount(30);
LR.SetWidth(0.05f, 0.05f);
}
void Init()
{
thispoint.position = new Vector2(Random.Range(-9.0f, 9.0f), Random.Range(-5.0f, 5.0f));
way = new Vector2(Random.Range(-1.0f, 1.0f), Random.Range(-1.0f, 1.0f));
way = way.normalized;
this.GetComponent<CircleCollider2D>().enabled = true;
}
private void FixedUpdate()
{
thispoint.Translate(way * gamectrl.speed * Time.fixedDeltaTime);
}
private void Update()
{
int i = 1;
checkside();
LR.SetPosition(0, thispoint.position);
foreach (Transform tr in points)
{
LR.SetPosition(i * 2 - 1, tr.position);
if (i == 15) break;
LR.SetPosition(i * 2, thispoint.position);
i++;
}
for (i = (i - 1) * 2; i <= 29; i++)
{
LR.SetPosition(i, thispoint.position);
}
}
private void checkside()
{
if (Mathf.Abs(thispoint.position.x) >= 9 || Mathf.Abs(thispoint.position.y) >= 5)
{
if (thispoint.position.x >= 9)
{
// way = (2 * Vector2.Dot(-way, new Vector2(-1, 0)) * new Vector2(-1, 0) + way).normalized;
this.GetComponent<CircleCollider2D>().enabled = false;
Init();
}
else if (thispoint.position.x <= -9)
{
// way = (2 * Vector2.Dot(-way, new Vector2(-1, 0)) * new Vector2(-1, 0) + way).normalized;
this.GetComponent<CircleCollider2D>().enabled = false;
Init();
}
else if (thispoint.position.y >= 5)
{
// way = (2 * Vector2.Dot(-way, new Vector2(0, -1)) * new Vector2(0, -1) + way).normalized;
this.GetComponent<CircleCollider2D>().enabled = false;
Init();
}
else if (thispoint.position.y <= -5)
{
this.GetComponent<CircleCollider2D>().enabled = false;
Init();
// way = (2 * Vector2.Dot(-way, new Vector2(0, 1)) * new Vector2(0, 1) + way).normalized;
}
}
}
private void OnTriggerEnter2D(Collider2D collision)
{
points.Add(collision.transform);
}
private void OnTriggerExit2D(Collider2D collision)
{
int i = 0;
foreach (Transform ts in points)
{
if (collision.gameObject.name == ts.name)
{
if (points.Count == 1) { points.Remove(points[points.Count - 1]); return; }
for (int n = i; n < points.Count - 1; n++)
{
points[n] = points[n + 1];
}
points.Remove(points[points.Count - 1]);
return;
}
i++;
}
}
}
全文完