unity3d5.1物体椭圆旋转选择界⾯实现(⼀)
偶然在⾥看到有⼈拿了⼀张椭圆物体旋转选择界⾯来问怎么实现(也不知道这样描述对不对,反正是椭圆的,⽽且还是旋转的,类似于关卡和⾓⾊选择),于是
想了下⾃⼰写了⼀个类似的功能,⽅法可能不是很完美,但是也算是⼀个思路吧,就当练练⼿熟悉unity。原图如下:
附⾃⼰完成后的效果图:
遗憾的是不会做动态图⽚,也不知道⼤神写博客是怎么弄运⾏代码时的动态效果图,只能附上渣渣图⽚了~
基本效果能够达到⼀致,但是只是直接移动,原本是想实现绕椭圆轨迹移动,这⾥不得不说,unity动作机制⼏乎没有,原本api就难,⾃⼰半天连⼀个move的函
数都没有,如果不去⼀个插件,只能通过update每⼀帧去⼿动设置GameObject的位置来达到move的效果,原本我以为是能够像cocos那样,最起码,moveto,得有,然后⽤贝塞尔模拟,可惜只能每帧刷新的话就先不写了。
设计思路
⽅块的摆布:
⾸先需要明确的是⽅块的排布问题,摆布有多种⽅式,可以先将所有的⽅块保存到容器,之后按照⼀定的坐标差值来递增,递减这些⽅块的摆放位置,最后达到该视觉效果,只是在排列的过程中需要长时间的调试效果,因⽽没有采⽤;同时也可以按照椭圆的轨迹来摆放,根据对象容器的遍历,每次递增或递减⼀定⾓度
达到该效果,这个⽅式是⽐较⽅便的,只需要根据当前⾓度偏移量来计算出⽅块对应的位置即可。当然,我们还需要考虑⽅块的奇偶性,在⽅块为奇数时,除去第⼀个显⽰在正中央的⽅块,刚好还剩下偶数个⽅块,左右正好排布⼀半,但是当⽅块为偶数个时,除去第⼀个,还会剩下最后⼀个⽅块。
⽅块为奇数时:
该情况较为简单,除去第⼀个,剩下的刚好对半分成,可以这样考虑:将所有需要排布的⽅块Object存放到⼀个数组sprites⾥边,取size=(length+1)/2
例如有七个⽅块,前边size个(四个)从中间开始往右递增排布,即保证容器前size个是顺次排布,剩下三个从中间(除去中间那个点)往左边排布。
⽅块为偶数时:
该情况稍微复杂⼀点,除去第⼀个,再分去左右对称的,还会多出⼀个来,可以这样考虑:将所有⽅块存放到⼀个数组sprites⾥,取size=length/2
例如有⼋个⽅块,前边size个(四个)从中间开始往右递增排布,剩下三个从中间(除去中间那个点)往左边排布,最后⼀个可以放到第⼀个的正对⾯。
显⽰层级:在cocos2dx中,⼦类节点都是通过挂载到⽗节点的形式添加到场景中,在addchild的时候提供⼀个zorder参数,即精灵的渲染层级,⽽
unity不同,查api了半天,最后到SetSiblingIndex函数,值越⼤越后显⽰,没次初始化和移动都必须重置显⽰层级,所以需要单独封装函数。
点击按钮之后的回调
向左按钮:点击向左按钮时,右边的⽅块同⼀往左移⼀格位置,左边的⽅块统⼀往上移⼀格位置,左边最后⼀个⽅块移动到右边最后⼀个⽅块
向右按钮:同理。
开始动⼿开发
新建场景
新建项⽬:2d,3d⽆所谓,这⾥是3d,但是要⽤⼀般是在2d,只是项⽬⽽已。
添加控件:⾸先添加七个Image对象(控件可以是按钮,都⾏);添加left和right的button,摆布没有要求,随意摆放,反正都是要做排序的。
如图:(这⾥panel是没必要的,我多加的)
添加UI按椭圆顺序排布脚本
新建脚本:Ellipse.cs脚本,对象绑定到Canvas对象。
编写代码:
//保存需要排序的精灵容器
public GameObject[] Sprites;
public Transform centerPoint;//椭圆的中⼼点
public float anglecheap = 25;//每个⽅块间的⾓度偏移
//保存位置点
private List<Vector3> location = new List<Vector3>();
private float angle =270;//第⼀个保证是中⼼位置的,当前到的⾓度
private float firstangle = 270;//记录第⼀个⾓度,⽤以左右对称
private float r =90;//椭圆的两个弦长
private float r =90;//椭圆的两个弦长
private float R = 150;
int size = 0;//即对象数组的⼀半,奇数为总长度+1/2,偶数为⼀半<pre name="code" class="csharp">// Use this for initialization  void Start ()
{//初始化size
if (Sprites.Length % 2 == 0)
{
size = Sprites.Length / 2;
}
else
{
size = (Sprites.Length + 1) / 2;
}
//排序分级显⽰
makespriteSort();
//重置渲染层级
ResetDeep();
}
//给这些精灵排序显⽰
void makespriteSort()
{
//取出椭圆的中⼼点
Vector3 center = centerPoint.position;
/
/判断该数组的个数奇偶性,如果是偶数,那么需要留出⼀个来放到对⾯
if (Sprites.Length % 2 == 0)
{
//右半边
for (int i = 0; i < size; i++)
{
Sprites[i].transform.position = getPosition(angle, center);
//      m_rightsprite.Add(Sprites[i]);
angle += anglecheap;
}
//第⼀个已经得是左边了
angle = firstangle - anglecheap;
//左半边
for (int i = size; i < Sprites.Length-1; i++)
{
Sprites[i].transform.position = getPosition(angle, center);
angle -= anglecheap;
//  m_leftsprite.Add(Sprites[i]);
}
//最后⼀个
Sprites[Sprites.Length - 1].transform.position = getPosition(firstangle-180, center);
// m_leftsprite.Add(Sprites[Sprites.Length - 1]);
return;
}
//如果不是偶数,那么出去中间那个,正好正常显⽰
else单人开发选ue4还是unity
{
//右半边
for (int i = 0;i<size; i++)
{
Sprites[i].transform.position = getPosition(angle, center);
//    m_rightsprite.Add(Sprites[i]);
angle += anglecheap;
}
//第⼀个已经得是左边了
angle = firstangle - anglecheap;
//左半边
for (int i = size;i < Sprites.Length; i++)
{
Sprites[i].transform.position = getPosition(angle, center);
//  m_leftsprite.Add(Sprites[i]);
angle -= anglecheap;
}
}
return;
}
}
//获取当前⾓度的坐标
Vector3 getPosition(float _angle,Vector3 _centerposition)
{
float hudu = (_angle/180f) * Mathf.PI;
float cosx = Mathf.Cos(hudu);
float sinx = Mathf.Sin(hudu);
float x = _centerposition.x + R * cosx;
float y = _centerposition.y + r * sinx;
Vector3 point = new Vector3(x, y, 0);
//添加到容器保存
location.Add(point);
return  point;
}
//根据当前左右容器调整所有控件的渲染层级
void ResetDeep()
{
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++;
}
}
运⾏后可以看到如图效果(不要忘了把这⼏个对象拖到脚本⾥,中⼼点是传⼊的对象,所以有⼀个位置要摆好,摆在想要的中⼼点中,也可以⾃⼰改成⼿动输⼊x,y,z):

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。