最近我在Wallpaper Engine上法线了一款有趣的壁纸,
不放音乐的时候
当音乐响起的时候
然后我就想,这个如何用Unity实现,我们先来观察,便面上每个点的运动毫无规律,实际上它们每个点都有自己的方向,当点到达屏幕边缘时,反弹;当音乐响起时,它只会随着音乐的节奏加速运动和放大,它的运动轨迹并没有变化;当相邻的两个点足够近的时候连接,足够远就断开。好了分析到这里,案子已经结了。
我们首先来实现它的运动部分和连接部分,音乐响应部分会在(下)篇来实现。
我们首先针对一个点来做:
在start的时候,给这个点一个随机的位置和一个随机的方向
thispoint = this.transform;
thispoint.position = new Vector2(Random.Range(-9.0f, 9.0f), Random.Range(-5.0f, 5.0f));
way = new Vector2(Random.Range(0.0f,1.0f), Random.Range(0.0f, 1.0f));
在fixedupdate函数中,让这个点保持一定的速度,朝着这个方向运动
private void FixedUpdate()
{
thispoint.Translate(way * gamectrl.speed*Time.fixedDeltaTime);
}
在update函数中,我们判断这个点是不是碰撞到了屏幕边缘,如果碰撞了,我们需要做的就是计算它的反弹方向,并把这个方向赋给二维方向变量way
private void Update()
{
checkside();
}
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;
}
else if (thispoint.position.x <= -9)
{
way = (2 * Vector2.Dot(-way, new Vector2(-1, 0)) * new Vector2(-1, 0) + way).normalized;
}
else if (thispoint.position.y >=5)
{
way = (2 * Vector2.Dot(-way, new Vector2(0, -1)) * new Vector2(0, -1) + way).normalized;
}
else if (thispoint.position.y <= -5)
{
way = (2 * Vector2.Dot(-way, new Vector2(0, 1)) * new Vector2(0,1) + way).normalized;
}
}
}
那么到现在,我们关于一个点的运动已经完成了
好,现在我们来完成点与点的连接,首先我们需要给这个点添加‘’碰撞器‘’和‘’线段渲染器‘’,我们需要碰撞器来判断什么时候连什么时候断,用线段渲染器来画线。
首先建立一个泛型,来管理这个点周围的点
private List<Transform> points = new List<Transform>();
当碰撞器碰撞的时候,触发OnCollisionEnter2D事件,在各个事件中我们把碰撞到的点添加到泛型中;当有点离开碰撞器范围之后,触发OnCollisionExit2D时间,把这个点从泛型中移出去。
private void OnCollisionEnter2D(Collision2D collision)
{
points.Add(collision.transform);
}
private void OnCollisionExit2D(Collision2D 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);
}
现在,运行效果如下:
因为电工实验考试的原因,我可能会在考完试之后再更新(下)关于受音频相应和特效美化的部分,所以这个暂时鸽了,有的同学说我关于【用Unity做图像处理软件】系列写的不够详细,我也听取了,我感觉这次写得应该算是比较详细了。。。
下面附上目前所有的代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public struct gamectrl
{
public static float speed = 10;
}
public class moveforall : 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;
thispoint.position = new Vector2(Random.Range(-9.0f, 9.0f), Random.Range(-5.0f, 5.0f));
way = new Vector2(Random.Range(0.0f,1.0f), Random.Range(0.0f, 1.0f));
way = way.normalized;
LR.SetVertexCount(30);
LR.SetWidth(.06f, .06f);
}
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;
}
else if (thispoint.position.x <= -9)
{
way = (2 * Vector2.Dot(-way, new Vector2(-1, 0)) * new Vector2(-1, 0) + way).normalized;
}
else if (thispoint.position.y >=5)
{
way = (2 * Vector2.Dot(-way, new Vector2(0, -1)) * new Vector2(0, -1) + way).normalized;
}
else if (thispoint.position.y <= -5)
{
way = (2 * Vector2.Dot(-way, new Vector2(0, 1)) * new Vector2(0,1) + way).normalized;
}
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
points.Add(collision.transform);
}
private void OnCollisionExit2D(Collision2D 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++;
}
}
}