unity选择关卡的跑马灯效果

来源:互联网 发布:2k17樱木花道捏脸数据 编辑:程序博客网 时间:2024/04/28 14:55

最近项目中需要做一个类似乱斗西游的选择关卡的效果,如下所示


涉及到的知识点也就四元数在旋转中的应用。

四元数公式:
    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);}}


0 0
原创粉丝点击