unity选择关卡的跑马灯效果
2016-03-09 16:14
519 查看
最近项目中需要做一个类似乱斗西游的选择关卡的效果,如下所示
涉及到的知识点也就四元数在旋转中的应用。
四元数公式:
q.w=cos(a/2)
q.x=RAix.x*sin(a/2)
q.y=RAix.y*sin(a/2)
q.z=RAix.z*sin(a/2)
首先,需要需要假定一个旋转的半径,然后在该空间中放入一系列的单元,这些单元围绕着坐标系的某跟轴旋转,每个单元必然存在一个围绕该轴的角度,比如放入三个单元,那么,这三个单元围绕某个轴旋转的角度必然依次是0, 120, 240,。然后拖拽屏幕,这三个单元在初始旋转角度的基础上做角度的偏移,再根据这个新值计算出新的位置。原理就是这样,下面放上代码。
涉及到的知识点也就四元数在旋转中的应用。
四元数公式:
q.w=cos(a/2)
q.x=RAix.x*sin(a/2)
q.y=RAix.y*sin(a/2)
q.z=RAix.z*sin(a/2)
首先,需要需要假定一个旋转的半径,然后在该空间中放入一系列的单元,这些单元围绕着坐标系的某跟轴旋转,每个单元必然存在一个围绕该轴的角度,比如放入三个单元,那么,这三个单元围绕某个轴旋转的角度必然依次是0, 120, 240,。然后拖拽屏幕,这三个单元在初始旋转角度的基础上做角度的偏移,再根据这个新值计算出新的位置。原理就是这样,下面放上代码。
using UnityEngine; using System.Collections; using UnityEngine.Events; using System.Collections.Generic; public class LoopScrollView : MonoBehaviour { [SerializeField] protected TouchEvent mTouchEvent; [SerializeField] private List<GameObject> mChildrenList; [SerializeField] private Vector2 mStartTouchPosition; [SerializeField] private Vector2 mLastTouchPosition; [SerializeField] private UILayer mUILayer; [SerializeField] protected float mR = 400; //虚拟旋转半径 [SerializeField] private float mAngle = 0; //虚拟当前旋转角度 [SerializeField] private float mTargetAngle = 1000; //选择目标角度 private float mTouchOffsetAngle = 0; //每次拖动旋转的角度 private int mCurSelectIndex = 0; public static LoopScrollView Create(Vector2 size, RectTransform rectT, UILayer uiLayer) { LoopScrollView obj = UINode.Create<LoopScrollView>("Layout/Common/LoopScrollView", rectT); obj.GetComponent<RectTransform>().sizeDelta = size; obj.mUILayer = uiLayer; return obj; } void Awake() { mTouchEvent.AddTouchEventListener(onTouchCallBack); } void Update() { if(mTargetAngle != 1000) { mAngle = Mathf.Lerp(mAngle, mTargetAngle, 0.2f); for(int i = 0; i < mChildrenList.Count; ++i) { UpdatePositionByAngle(mChildrenList[i], -2.0f*Mathf.PI*i/mChildrenList.Count + mAngle); } float deltaAngle = 180*(mTargetAngle - mAngle)/Mathf.PI; if(deltaAngle < 0.5f && deltaAngle > -0.5f) { mAngle = mTargetAngle; for(int i = 0; i < mChildrenList.Count; ++i) { UpdatePositionByAngle(mChildrenList[i], -2.0f*Mathf.PI*i/mChildrenList.Count + mAngle); } mTargetAngle = 1000; } UpdateZOrder(); } } void setR(int r) { mR = r; for(int i = 0; i < mChildrenList.Count; ++i) { UpdatePositionByAngle(mChildrenList[i], -2.0f*Mathf.PI*i/mChildrenList.Count); } } public void AddItem(GameObject obj) { obj.transform.parent = this.transform; obj.transform.localScale = new Vector3(1,1,1); mChildrenList.Add(obj); for(int i = 0; i < mChildrenList.Count; ++i) { UpdatePositionByAngle(mChildrenList[i], -2.0f*Mathf.PI*i/mChildrenList.Count); } UpdateZOrder(); } void onTouchCallBack(TouchEvent touchEvent) { switch (touchEvent.GetTouchEventType()) { case TouchEvent.TouchEventType.Down: mLastTouchPosition = touchEvent.Position; mStartTouchPosition = touchEvent.Position; break; case TouchEvent.TouchEventType.Move: //Debug.Log("拖动"); if(mLastTouchPosition != Vector2.zero) { MoveChildren(mLastTouchPosition, touchEvent.Position); } mLastTouchPosition = touchEvent.Position; break; case TouchEvent.TouchEventType.Up: mLastTouchPosition = Vector2.zero; if(mTouchOffsetAngle > 0.4*Mathf.PI/mChildrenList.Count) { mTargetAngle = mAngle + 2.0f*Mathf.PI/mChildrenList.Count; ++mCurSelectIndex; if(mCurSelectIndex > mChildrenList.Count - 1) { mCurSelectIndex = 0; } } else if(mTouchOffsetAngle < -0.4*Mathf.PI/mChildrenList.Count) { mTargetAngle = mAngle - 2.0f*Mathf.PI/mChildrenList.Count; --mCurSelectIndex; if(mCurSelectIndex < 0) { mCurSelectIndex = mChildrenList.Count - 1; } } else { mTargetAngle = mAngle; } mAngle = mAngle + mTouchOffsetAngle; mTouchOffsetAngle = 0; UpdateSelectIndex(mCurSelectIndex); break; default: break; } } void MoveChildren(Vector2 lastPosiotn, Vector2 curPosition) { //圆心坐标 Vector2 center = new Vector2(0, mR); for(int i = 0; i < mChildrenList.Count; ++i) { Vector2 lastUIPos; Vector2 curUIPos; RectTransformUtility.ScreenPointToLocalPointInRectangle(mUILayer.transform as RectTransform, lastPosiotn, mUILayer.UICanvas.worldCamera, out lastUIPos); RectTransformUtility.ScreenPointToLocalPointInRectangle(mUILayer.transform as RectTransform, curPosition, mUILayer.UICanvas.worldCamera, out curUIPos); Vector2 offset = curUIPos - lastUIPos; //位移转角度 if(mTouchOffsetAngle < 2.0f*Mathf.PI/mChildrenList.Count && mTouchOffsetAngle > -2.0f*Mathf.PI/mChildrenList.Count) { //mAngle = mAngle - (offset.x)/(2.0f*Mathf.PI*mR); mTouchOffsetAngle = mTouchOffsetAngle - (offset.x)/(2.0f*Mathf.PI*mR); } UpdatePositionByAngle(mChildrenList[i], -2.0f*Mathf.PI*i/mChildrenList.Count + mAngle + mTouchOffsetAngle); } UpdateZOrder(); } void UpdatePositionByAngle(GameObject obj, float angle) { angle += Mathf.PI/2; Quaternion q = new Quaternion(0, 1*Mathf.Sin(angle/2), 0, Mathf.Cos(angle/2)); Vector3 vec = q * new Vector3(mR, 0, 0); obj.transform.localPosition = vec + new Vector3(0, 0, mR); obj.transform.localPosition = new Vector3(obj.transform.localPosition.x, (obj.transform.localPosition.z - mR)/6, obj.transform.localPosition.z); } //深度排序 void UpdateZOrder() { List<GameObject> sortBuf = new List<GameObject>(); List<GameObject> sortResult = new List<GameObject>(); float leastZ = 10000; for(int i = 0; i < mChildrenList.Count; ++i) { sortBuf.Add(mChildrenList[i]); } for(int i = 0; i < mChildrenList.Count; ++i) { int index = -1; for(int j = 0; j < sortBuf.Count; ++j) { if(sortBuf[j].transform.localPosition.z < leastZ) { leastZ = sortBuf[j].transform.localPosition.z; index = j; } } sortResult.Add(sortBuf[index]); sortBuf.RemoveAt(index); leastZ = 10000; } for(int i = 0; i < sortResult.Count; ++i) { sortResult[i].transform.SetSiblingIndex(sortResult.Count - i - 1); } } //更新选择 void UpdateSelectIndex(int index) { Debug.Log("选择的序号:" + index); EventCenter.Single.PostEvent("LOOP_SCROLL_VIEW_SELECT_INDEX", index); } }
相关文章推荐
- 【Unity3D】 面试 笔试题目(一)
- 使用Unity发布第一个程序时遇到的问题
- Unity 你以为SetParent()是个很简单的API???!!
- Unity5新的AssetBundle系统使用心得
- Unity3D ----- 代码控制shader的自发光参数(摄像机黑白特效下)
- Unity3D ----- 动态设置UGUI中Text的大小和位置
- unity 编辑器工具扩展
- 【Unity】关于项目中画线设定
- unity3d发布apk在android虚拟机中运行的详细步骤(unity3d导出android apk)
- 关于unity常见的面试题
- 【Unity】修改MainMaps 下的offset 的值
- unity 中的 数学函数库(完善中)
- 【Unity】 旧版动画 在某一帧增添事件
- Unity3D脚本中文字符乱码的解决方案
- unity 3D 5.3.3官方最新版 完整包下载,包含所有补丁包
- unity3d利用pano2VR实现全景视图效果
- unity3d学习笔记(十一)-NGUI结合Shader制作小map
- unity3d 在UGUI中制作自适应调整大小的滚动布局控件
- unity3d进程通信利用WM_COPYDATE和HOOK
- Unity3D外包(u3d外包)—就找北京动点软件(我们长年承接U3D外包、Maya、3DMax项目外包)