在上一篇实现了椭圆的方块摆布之后,接着实现方块选择时候的移动效果,由于最近比较忙,忘了写后续了。而且自己正好加到项目中去了,为了适应项目改了很多实现方式,可能会稍有出入,只好以最终版为准了。
我在unity中并没有找到直接将某对象移动到另一位置的api,因此,要实现移动效果,方式有三种:
1、使用Itween插件提供的MoveTo函数,能够达到移动效果。但是考虑情况比较复杂,首先必须方块数目大于3,移动效果可能好一点,并且往某个方向移动时,最后一个是平整的过去的,显得怪异。同时方块为2时,一前一后移动特别怪异,从上往下和从下往上,这两点比较难解决;
2、使用Itween插件的自动寻路算法,看了下,貌似是设置几个点,然后让方块按照先后顺序移动到终点就行了,这样的话,可以将每个方块的轨迹取出几个点,传入,然后ok;
3、也仅仅是模拟,所以我在这里去三段式,自己写一个类似Itween的方法,同时自定义,取路径上的三个点(包括终点),每个点传入后,将递归执行移动到目标点,达到近视椭圆轨迹的效果,理论上来说,点越多,椭圆轨迹越清晰,但是感觉三段式就够用了,所以自己写了个。
第一种和第三种方法是实践了的,第二种方法暂时没去实验,但是感觉难度不大,方法都有了,实现也不会费劲。第一种太过简单就不赘述了,取出终点和起点就行了,同时不完美。
1.实现左右变换位置
先实现点击左右按钮后,几个方块会变换好位置,且变换的位置是准确的。
定义一个方向枚举,用以判断当前操作是向左还是向右操作
public enum MYDirection
{
//向左
LEFT,
//向右
RIGHT
}
然后给左右按钮分别绑定左右按钮的回调函数,在界面里添加onclick事件即可
<pre name="code" class="csharp"> //往左滑动的回调函数即整体往左移动
public void LeftButtonEvent()
{
//添加到容器里,用以多次点击时延迟执行
m_eventList.Add(MYDirection.LEFT);//该容器要去声明,防止多次快速点击时乱掉,保存每个点击事件,一一递归执行
doEvent();
}
//往右滑动的回调函数
public void RightButtonEvent()
{
//添加到容器里,用以多次点击时延迟执行
m_eventList.Add(MYDirection.RIGHT);//该容器要去声明,防止多次快速点击时乱掉,保存每个点击事件,一一递归执行
doEvent();
}
//集中判断执行哪个按钮的回调函数
public void doEvent()
{
if(isruningone==true)//如果已经在执行着一个了,那么就不再执行,该变量也需声明,保证每次执行是第一个,暂时用不到
{
return;
}
//如果所有的都执行完了,那么跳出
if(m_eventList.Count<=0)
{
return;
}
isruningone = true;//设置为true,锁定,防止多次执行
//如果没有,那么取出一个来执行
MYButtonEvent(m_eventList[0]);
m_eventList.RemoveAt(0);
}
//根据方向来不断执行移动
void MYButtonEvent(MYDirection _direction)
{
//往左移动
if(_direction==MYDirection.LEFT)
{
GameObject temp0 = Sprites[0];//先保存第一个的引用
if (size <= 0)
{
return;
}
//右边全部往前一格
for (int i = 0; i < size - 1; i++)
{
Sprites[i] = Sprites[i + 1];
}
//右边最后一个直接赋值
Sprites[size - 1] = Sprites[Sprites.Length - 1];
//左边全部往后一格
for (int i = Sprites.Length - 1; i > size; i--)
{
Sprites[i] = Sprites[i - 1];
}
//左边第一个直接赋值
Sprites[size] = temp0;
//移动方块
Move(MYDirection.LEFT);
return;
}
//往右移动
else
{
GameObject temp0 = Sprites[size];//先保存左边第一个的引用
if (size <= 0)
{
return;
}
//左边全部往前一格
for (int i = size; i < Sprites.Length - 1; i++)
{
Sprites[i] = Sprites[i + 1];
}
//左边最后一个直接赋值
Sprites[Sprites.Length - 1] = Sprites[size - 1];
//右边全部往后一格
for (int i = size - 1; i > 0; i--)
{
Sprites[i] = Sprites[i - 1];
}
//左边第一个直接赋值
Sprites[0] = temp0;
//左边全部往后一格
//移动方块
Move(MYDirection.RIGHT);
return;
}
}
Move操作,即每次给它重设坐标即可,因为暂时不加移动效果:
<pre name="code" class="csharp">
//移动的函数
void Move(MYDirection _direction)
{
int size = Sprites.Length;
for (int i = 0; i < size; i++)
{
Sprites[i].transform.position=location[i];
}
ResetDeep();
isruningone = false;
i_havemovesprite = 0;
doEvent();
}
void ResetDeep()
{
int dep = 0;
//右半边
for (int i =size-1; i>=0; i--)
{
Sprites[i].GetComponent<Transform>().SetSiblingIndex(dep);
dep++;
}
dep = 0;
//左半边
for (int i = Sprites.Length - 1; i >=size; i--)
{
Sprites[i].GetComponent<Transform>().SetSiblingIndex(dep);
dep++;
}
}
至此,应该来说可以实现点击变换位置了,虽然没有移动效果(我是按照写好了的版本去写前面的,可能会有错误,大致思想在这儿,变量问题可以自己添加)。
2.创建自己的Move函数脚本
如下:
using UnityEngine;
using System.Collections;
using System;
using System.Reflection;
using UnityEditor;
using System.Collections.Generic;
public class ManagerEffective : MonoBehaviour
{
public enum LoopType//循环方式
{
one,//一次
loop,//循环
pingpong//来回
}
public static ArrayList ef_tive = new ArrayList();
//椭圆测试
bool m_isEllips=false;
List<Vector3> TargetPos=new List<Vector3>();
float nowtimelimit;
int count = 0;
//多少秒内完成,开始前等待时间
public float time, delay;
//循环方式
public LoopType loopType;
public bool isRunning;//判断是否在更新位置
//代理函数
private delegate void ApplyMthood();
private ApplyMthood apply;//代理函数对象
private Vector3[] vector3s;//用以保存当前的进度,目标的位置信息等
//当前时间,进度
private float runningTime, percentage;
private float lastRealTime; // Added by PressPlay