• unity3d 3D卡片滚动效果

    2015-08-17 11:36:28
    本来上个月就改写的文章,但是因为这段时间受到国漫的影响,不停的刷《大圣归来》和《那年那兔那些事儿》两部动漫,以至于很长时间没有...好了,下面进入正文,今天为大家唠叨一下3D卡片滚动切换效果,首先按惯例,先上

    本来上个月就改写的文章,但是因为这段时间受到国漫的影响,不停的刷《大圣归来》和《那年那兔那些事儿》两部动漫,以至于很长时间没有写什么新内容给各位看官啦,嘿嘿~~so,大家也应该晓得我是大圣哥哥的自来水啦!同时,我也是种花家一只热血沸腾的兔子!墙裂推荐《那兔》,这是一部很呆萌也很感人的动漫哦,让大家感受不一样的热血国漫!

    好了,下面进入正文,今天为大家唠叨一下3D卡片滚动切换效果,首先按惯例,先上效果图:

    设计思路:给每张图片设置编号,以编号为基础,根据一定的距离将所有图片分散到两边排开,每张图片的depth也根据此编号进行调整;每张卡片的移动效果都由NGUI自带的TweenPosition来实现;每次左右移动卡片都会重新设置卡片的编号,再根据新的编号移动到相应的位置,同时也要相对应的增减图片的depth。 

    实施方案:

    (1).    基本界面:两个左右移动的按钮,一个空物体RoleList,用于存放所有的卡片;单张卡片界面,背景图”Role”+被激活的高亮图”Active”+角色图片”Texture”,初始depth为0:1:2;添加文件夹 Resources/Pictures,将所有的角色图片放入此目录下;

    (2).    单张卡片组件设置:为”Role”添加UIToggle组件,用于鼠标点击卡片时调用;创建并挂上脚本RoleItem,把变量Role、Active、Texture拖入相应位置,添加TweenPosition组件,Duration设置0.2,用于卡片移动效果,在OnFinished挂上RoleItem下的Finish()方法,当卡片移动完后更新移动的初始状态;设置完成后,将Role拖成预设至Resources文件夹下,

    代码如下:

    [code]csharpcode:

    public class RoleItem : MonoBehaviour {    public UISprite bg;    public UISprite active;    public UITexture texture;    /// <summary>    /// tween完成后记录当前位置    /// </summary>    public void Finish()    {         TweenPosition tp = gameObject.GetComponent<TweenPosition>();        tp.from = gameObject.transform.localPosition;        tp.ResetToBeginning();    }}

    (3).    编号排序:创建脚本SelectRole,将其拖入UIRoot下,然后开始码字吧。卡片的排列方式是以倒三角形的形式,最中间的卡片要显示在最前方,其他的卡片向其后两边散开,因此图片的深度要最大,排序的编号也就最大,排序方式按下图所示;

    (4).    Depth调整:Sprite/Texture的Depth=卡片编号的绝对值*卡片组合数+初始Depth,例如编号为-4的Role的Depth为|-4|*3+0=12,Active的Depth为|-4|*3+1=13,Texture的Depth为|-4|*3+2=15

    (5).    位置排列:以编号为5的卡片为基础,编号为4的卡片x向右移动N*1个单位,编号为3的卡片x向右移动N*2个单位,然后依次类推,y、z坐标也是如此,代码如下:计算出移动后的坐标以后将新的坐标存入TweenPosition的To里边,然后再开启enable移动卡片;

    [code]csharpcode:

    /// <summary>    /// 设置深度及位置    /// </summary>    /// <param name="role"></param>    /// <param name="dir">方向:往左=1,往右=-1,初始化=0</param>    /// <param name="index">移动位置后新的编号</param>    private void SetDepthAndPosition(RoleItem role,int dir,int index)    {        int indexDepth = 0;        //非初始化状态,左右移动后,重新排序命名,        if (dir != 0)        {            //最中间位置的编号变化,右移:原-4变5;左移:原5变-4            if (index*dir > _half )                indexDepth = -dir * (_half - 1);            //左移或右移后超出位置的最后一张卡片的编号为原来的相反数            else                indexDepth = index > -1 && index < 1 ? dir : index;            role.name = indexDepth.ToString();          }                else        {            indexDepth = int.Parse(role.name);//初始化状态        }        //设置移动位置        TweenPosition tp = role.GetComponent<TweenPosition>();        int x = indexDepth < 0 ? -(_half + indexDepth) * _movX : (_half - indexDepth) * _movX;        indexDepth = System.Math.Abs(indexDepth);        tp.to = new Vector3(x, (_half - indexDepth) * _movY, (_half - indexDepth) * _movZ);        //设置图片层级        role.bg.depth = count * indexDepth;        role.active.depth = 1 + count * indexDepth;        role.texture.depth = 2 + count * indexDepth;                role.GetComponent<UIToggle>().value = indexDepth == _half ? true:false;        tp.PlayForward();    }

    (6).    左右移动按钮:向左移动,所有编号+1,向右移动,所有编号-1,重新排序,代码如下:

    [code]csharpcode:

    /// <summary>    /// 左边    /// </summary>    public void LeftClick()    {        //重新排列顺序        foreach (RoleItem role in _roleList)        {            int index = int.Parse(role.name);             SetDepthAndPosition(role,1,++index);        }     }    /// <summary>    /// 右边    /// </summary>    public void RightClick()    {        //重新排列顺序        foreach (RoleItem role in _roleList)        {            int index = int.Parse(role.name);            SetDepthAndPosition(role,-1,--index);        }    }
    (7).    卡片点击移动:其实就是调用N次左右移动的方法啦,代码如下:

    [code]csharpcode:

    /// <summary>    /// 鼠标选中某个角色    /// </summary>    public void RoleToggleChange()    {         if(UIToggle.current.value)        {            int index = int.Parse(UIToggle.current.name);            int moveCount = _half - System.Math.Abs(index);//移动个数            for (int i = 0; i < moveCount;i++ )            {                if (index > 0)                    LeftClick();                else                    RightClick();            }                   }    }
    最后附上作品及源码地址:
    http://pan.baidu.com/s/1i3gu4q5
    展开全文
  • Unity3D基础知识、游戏算法一网打尽。
  • Unity 3D循环滚动效果

    2017-07-25 14:50:36
    然后通过SetDepthAndPosition这个方法,实现图片的空间空间展开Z轴和Y轴,系数是一样的经过上面设置,空间就摆开了using UnityEngine; using System.Collections; using System.Collections.Generic;...

    这里写图片描述


    然后通过SetDepthAndPosition这个方法,实现图片的空间空间展开


    这里写图片描述



    这里写图片描述


    Z轴和Y轴,系数是一样的


    经过上面设置,空间就摆开了


    这里写图片描述



    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    
    public class SelectRole : MonoBehaviour {
        public GameObject rolesObj;
        private int _half = 0;//一侧的卡片数
        private int _movX = 150;//X轴移动距离
        private int _movY = 50;//Y轴移动距离
        private int _movZ = 60;//Z轴移动距离
        private int count = 3;//组件数
        private List<RoleItem> _roleList = new List<RoleItem>();
    
        // Use this for initialization
        void Start () {
            //加载图片
            Object[] textureList = (Object[])Resources.LoadAll("Pictures");
    
            int maxDepth = textureList.Length % 2 == 1 ? textureList.Length / 2 + 1 : textureList.Length / 2;//最大深度
            _half = maxDepth;      
    
            for (int i = 0; i < textureList.Length; i++)
            {            
                //加载角色图片预设
                GameObject role = Instantiate(Resources.Load("Role", typeof(GameObject))) as GameObject;            
                role.transform.parent = rolesObj.transform;
                role.transform.localScale = Vector3.one;
    
                EventDelegate.Add(role.GetComponent<UIToggle>().onChange , RoleToggleChange);
    
                RoleItem item = role.GetComponent<RoleItem>();            
                item.texture.mainTexture = textureList[i] as Texture;
    
                //设置角色卡片排序命名
                role.name = maxDepth.ToString();
                if (i > 0)
                {
                    //奇数设置为右边,下标为正数
                    if (i % 2 == 1)
                    {
                        maxDepth--;
                        role.name = maxDepth.ToString();
                    }
                    //偶数设置为左边,下标为负数
                    else
                    {
                        role.name = "-" + maxDepth.ToString();
                    }
                }
    
                SetDepthAndPosition(item,0,0);
                _roleList.Add(item);
            }        
        }
    
    
        private void SetDepthAndPosition(RoleItem role,int dir,int index)
        {
            int indexDepth = 0;
            //左右移动后,重新排序命名
            if (dir != 0)
            {
                if (index*dir > _half )
                    indexDepth = -dir * (_half - 1);
                else
                    indexDepth = index > -1 && index < 1 ? dir : index;
                role.name = indexDepth.ToString();  
            }        
            else
            {
                indexDepth = int.Parse(role.name);
            }
    
            TweenPosition tp = role.GetComponent<TweenPosition>();
            int x = indexDepth < 0 ? -(_half + indexDepth) * _movX : (_half - indexDepth) * _movX;
            indexDepth = System.Math.Abs(indexDepth);
            tp.to = new Vector3(x, (_half - indexDepth) * _movY, (_half - indexDepth) * _movZ);
    
    
            role.bg.depth = count * indexDepth;
            role.active.depth = 1 + count * indexDepth;
            role.texture.depth = 2 + count * indexDepth;      
    
            role.GetComponent<UIToggle>().value = indexDepth == _half ? true:false;
            tp.PlayForward();
        }
    
        /// <summary>
        /// 左边
        /// </summary>
        public void LeftClick()
        {
            //重新排列顺序
            foreach (RoleItem role in _roleList)
            {
                int index = int.Parse(role.name);
                print(index);
                SetDepthAndPosition(role,1,++index);
            } 
        }
    
        /// <summary>
        /// 右边
        /// </summary>
        public void RightClick()
        {
            //重新排列顺序
            foreach (RoleItem role in _roleList)
            {
                int index = int.Parse(role.name);
                SetDepthAndPosition(role,-1,--index);
            }
        }
    
        /// <summary>
        /// 鼠标选中某个角色
        /// </summary>
        public void RoleToggleChange()
        { 
            if(UIToggle.current.value)
            {
                int index = int.Parse(UIToggle.current.name);
                int moveCount = _half - System.Math.Abs(index);//移动个数
                for (int i = 0; i < moveCount;i++ )
                {
                    if (index > 0)
                        LeftClick();
                    else
                        RightClick();
                }           
            }
        }
    
    }



    FR:海涛高软(hunk Xu)

    展开全文
  • 搭建简单的场景 运行效果 控制脚本: using UnityEngine; using System.Collections; using UnityEngine.UI; using DG.Tweening; public class CardMove : MonoBehaviour { GameObject[] sprites;... Vector

    搭建简单的场景
    这里写图片描述

    运行效果
    这里写图片描述
    卡片移动动画通过插件DoTween实现

    控制脚本:

    
    using UnityEngine;
    using System.Collections;
    using UnityEngine.UI;
    using DG.Tweening;
    public class CardMove : MonoBehaviour {
        GameObject[] sprites;
        int halfSize;
        Vector2 screenCenterPos;
        public float startAngle;//中间卡牌的角度
        public float deltaAngle;//相邻卡牌的角度差值
        public float moveSpeed;//移动动画的速度
    
        public Vector3 center;//椭圆中心点
        public float A = 1;//long axis
        public float B = 1;//short axis
        int cardcount;
        // Use this for initialization
        void Start () {
            init ();
        }
    
        // Update is called once per frame
        void Update () {
    
        }
        /// <summary>
        /// 初始化卡牌显示位置
        /// </summary>
        void init(){
            screenCenterPos = new Vector2 (Screen.width*0.5f,Screen.height*0.5f);
            cardcount = transform.childCount;
             halfSize = (cardcount - 1) / 2;
            sprites=new GameObject[cardcount];
            for (int i = 0; i < cardcount; i++) {
                sprites [i] = transform.GetChild (i).gameObject;
                setPosition (i,false);
                setDeeps (i);
    
            }
    
        }
        /// <summary>
        /// 椭圆的半长轴为A,半短轴为B,计算椭圆上一点的位置
        /// x=A*cos(angle),y=B*sin(angle)
        /// </summary>
        /// <param name="index">Index.</param>
        /// <param name="userTweener">是否使用tween动画.</param>
        void setPosition(int index,bool userTweener=true){
            //计算每一张卡片在椭圆上相对中间卡牌的角度
            float angle = 0;
            if(index<halfSize){//left
                angle=startAngle-(halfSize-index)*deltaAngle;
    
            }else if(index>halfSize){//right
    
                angle = startAngle + (index - halfSize) * deltaAngle;
            }else{//medim
                angle=startAngle;
            }
    
    
            //通过卡牌的角度,计算对应的位置
            float xpos = A*Mathf.Cos((angle/180)*Mathf.PI);//+center.x;
            float ypos = B*Mathf.Sin((angle/180)*Mathf.PI);//+center.y;
            Debug.Log ("index="+index+",xpos="+xpos+",ypos="+ypos);
    
            Vector2 pos = new Vector2 (xpos,ypos);
    //      Debug.Log ("screenPos="+screenPos+",wordPos="+wordPos);
    
    //通过doTween控制卡片移动动画
            if(!userTweener){
                sprites [index].GetComponent<Image> ().rectTransform.DOMove(new Vector2(screenCenterPos.x+pos.x,screenCenterPos.y+pos.y),0f);
            }else
                sprites [index].GetComponent<Image> ().rectTransform.DOMove(new Vector2(screenCenterPos.x+pos.x,screenCenterPos.y+pos.y),1f);
    
        }
        /// <summary>
        /// 计算每一张卡片的层级
        /// </summary>
        /// <param name="index">Index.</param>
        void setDeeps(int index){
            int deep = 0;
            if (index < halfSize) {//左侧卡牌层级,从左侧到中间,层级依此递增
                deep=index;
            } else if (deep > halfSize) {//右侧卡牌层级,从中间到右侧,层级依此递减
                deep=sprites.Length-(index+1);
            } else {
                deep = halfSize;
            }
    
            sprites [index].GetComponent<RectTransform> ().SetSiblingIndex (deep);
        }
        /// <summary>
        /// 左侧按钮点击,向左移动
        /// </summary>
        public void OnLeftBtnClick(){
            int length = sprites.Length;
    
            GameObject temp=sprites[0];
            for (int i = 0; i < length; i++) {//移动卡片在数组中的位置,依此向前移动一位
                if (i == length - 1)
                    sprites [i] = temp;
                else
                    sprites [i] = sprites [i + 1];
            }
    
            for (int i = 0; i < length; i++) {//跟新数组卡片需要显示的位置和层级
                setPosition (i);
                setDeeps (i);
            }
        }
    
        /// <summary>
        /// 右侧按钮点击,向右移动
        /// </summary>
        public void RightBtnClick(){
            int length = sprites.Length;
    
            GameObject temp=sprites[length-1];
            for (int i = length-1; i >=0; i--) {
                if (i == 0)
                    sprites [i] = temp;
                else
                    sprites [i] = sprites [i - 1];
            }
            for (int i = 0; i < length; i++) {
                setPosition (i);
                setDeeps (i);
            }
        }
    }
    

    demo 下载:http://download.csdn.net/detail/u011484013/9877532

    展开全文
  • 之前做卡片滑动的时候,老是会出现头尾UI穿透的bug,一直没有找到好的解决办法,今天抽空又研究了一下,解决了首尾穿透的bug,但是现在不能点击卡片滑动了。只能点击按钮滑动卡片,导致这个原因是因为我在卡片上添加...

    之前做卡片滑动的时候,老是会出现头尾UI穿透的bug,一直没有找到好的解决办法,今天抽空又研究了一下,解决了首尾穿透的bug,但是现在不能点击卡片滑动了。只能点击按钮滑动卡片,导致这个原因是因为我在卡片上添加了canvas这个组件来控制层级。目前没有找到解决办法。

    一、实现效果图:

    在这里插入图片描述

    在这里插入图片描述

    二、整体代码:

    using DG.Tweening;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.EventSystems;
    using UnityEngine.UI;
    
    public class MManager : MonoBehaviour
    {
    
        /// <summary>
        /// 左边按钮
        /// </summary>
        public Button LeftButton = null;
    
        /// <summary>
        /// 右边按钮
        /// </summary>
        public Button RightButton = null;
    
        /// <summary>
        /// 滚动速度
        /// </summary>
        public float Speed = 0;
    
        /// <summary>
        /// 卡片集合
        /// </summary>
        private List<Transform> CardList = new List<Transform>();
    
        /// <summary>
        /// 卡片坐标集合
        /// </summary>
        private List<Vector3> CardPosList = new List<Vector3>();
    
        /// <summary>
        /// 卡片大小集合
        /// </summary>
        private List<Vector3> CardScaleList = new List<Vector3>();
    
        /// <summary>
        /// 卡片父节点
        /// </summary>
        private Transform CardRoot = null;
    
        /// <summary>
        /// 是否可以点击按钮
        /// </summary>
        private bool IsCanClickButton = true;
    
        /// <summary>
        /// 左边需要设置为0层的卡片的索引
        /// </summary>
        public int LeftLimit = 0;
    
        /// <summary>
        /// 右边边需要设置为0层的卡片的索引
        /// </summary>
        public int RightLimit = 5;
    
        // Use this for initialization
        void Start()
        {
    
            LeftButton.onClick.AddListener(delegate () { ClickLeftOrRightButtonMethod(0); });
    
            RightButton.onClick.AddListener(delegate () { ClickLeftOrRightButtonMethod(1); });
    
            CardRoot = GameObject.Find("CardRoot").transform;
    
            for (int i = 0; i < CardRoot.childCount; i++)
            {
                CardList.Add(CardRoot.GetChild(i));
    
                //if (CardRoot.GetChild(i).GetComponent<Button>() == null)
                //    CardRoot.GetChild(i).gameObject.AddComponent<Button>().onClick.AddListener(ClickCardMethod);
            }
    
            foreach (var item in CardList)
            {
                CardPosList.Add(item.localPosition);
    
                CardScaleList.Add(item.localScale);
            }
    
        }
    
        // Update is called once per frame
        void Update()
        {
    
        }
    
        /// <summary>
        /// 点击卡片
        /// </summary>
        //public void ClickCardMethod()
        //{
        //    print(EventSystem.current.currentSelectedGameObject.transform.name);
    
        //    if (!IsCanClickButton)
        //        return;
        //    IsCanClickButton = false;
    
    
        //    var posX = EventSystem.current.currentSelectedGameObject.transform.localPosition.x;
    
        //    int scale = (int)((1f - EventSystem.current.currentSelectedGameObject.transform.localScale.x) * 10 / 2);
    
        //    if (posX < 0)
        //    {
        //        RollCardMethod(0, scale);
        //    }
        //    else if (posX > 0)
        //    {
        //        RollCardMethod(1, scale);
        //    }
        //}
    
        /// <summary>
        /// 点击左右按钮
        /// _n=0:Click Left
        /// _n=1:Click Right
        /// </summary>
        /// <param name="_n"></param>
        public void ClickLeftOrRightButtonMethod(int _n)
        {
            if (!IsCanClickButton)
                return;
            IsCanClickButton = false;
    
            RollCardMethod(_n);
        }
    
       
    
        /// <summary>
        /// 滚动卡片
        /// </summary>
        /// <param name="_n"></param>
        private void RollCardMethod(int _n,int _space=1)
        {
    
            CardList.Clear();
    
            CardPosList.Clear();
    
            CardScaleList.Clear();
    
            for (int i = 0; i < CardRoot.childCount; i++)
            {
                CardList.Add(CardRoot.GetChild(i));
            }
    
            foreach (var item in CardList)
            {
                CardPosList.Add(item.localPosition);
    
                CardScaleList.Add(item.localScale);
            }
    
            if (_n == 0)
            {
                for (int i = 0; i < CardList.Count; i++)
                {
                    if (i <= LeftLimit || i >= RightLimit)
                    {
                        CardList[i].GetComponent<Canvas>().sortingOrder = 0;
                    }
                    else
                    {
                        CardList[i].GetComponent<Canvas>().sortingOrder = 1;
                    }
    
                    CardList[i].DOLocalMove(CardPosList[i + _space >= CardList.Count ? 0 : i + _space], Speed);
    
                    CardList[i].DOScale(CardScaleList[i + _space >= CardList.Count ? 0 : i + _space], Speed);
    
                    CardList[i].SetSiblingIndex(i + _space >= CardList.Count ? 0 : i + _space);
                }
            }
            else if (_n == 1)
            {
                for (int i = CardList.Count - 1; i >= 0; i--)
                {
                    if (i <= (LeftLimit+1) || i >= (RightLimit+1))  //向左滑动的时候限制加1,要不然还是会穿透
                    {
                        CardList[i].GetComponent<Canvas>().sortingOrder = 0;
                    }
                    else
                    {
                        CardList[i].GetComponent<Canvas>().sortingOrder = 1;
                    }
    
                    CardList[i].DOLocalMove(CardPosList[i - _space < 0 ? CardList.Count - 1 : i - _space], Speed);
    
                    CardList[i].DOScale(CardScaleList[i - _space < 0 ? CardList.Count - 1 : i - _space], Speed);
    
                    CardList[i].SetSiblingIndex(i - _space < 0 ? CardList.Count - 1 : i - _space);
                }
            }
    
            Invoke("ActiveButtonMethod", Speed);
    
        }
    
        /// <summary>
        /// 激活按钮
        /// </summary>
        private void ActiveButtonMethod()
        {
            IsCanClickButton = true;
        }
    }
    
    展开全文
  • 下载地址:http://pan.baidu.com/s/1mgD2VH2  密码u35x






    下载地址:http://pan.baidu.com/s/1mgD2VH2  密码u35x

    展开全文
  • Unity3D图片滑动效果

    2020-06-14 11:42:15
    Unity3D图片滑动,滚动效果,C#语言!
  • 最近一位朋友问我,如何在Unity引擎中实现类似《英雄联盟》中选择皮肤时的3D滚动视图效果,虽然我非常不喜欢这个游戏,可是大学四年在宿舍里被周围同学们耳濡目染,对这个游戏中常见英雄的口头禅还是颇为熟悉的,...
  • 参考链接 : https://blog.csdn.net/dengshunhao/article/details/82657585(包含效果图) UGUI实现闹钟选择,数字上下循环滚动(当然也可以换成其他UI,比如图片)
  • UGUI实现的一个相册功能,有代码有注释,期间用到了DoTween插件。
  • 最近用unity4.3做个2d平台游戏,背景循环的问题搞得我头大了,如果用锚点连接图片有点小题大做,于是发现了下边这篇文章. 建议大家看文章中提到的这个例子插件androidgameexample,下载地址:泽国论坛(这个论坛好棒呀,...
  • 事实上这是项目需要,我改的一个代码,实际上就是利用unity的一些基础属性实现其效果。啥也不多说了,先上原代码: using UnityEngine.Events; namespace UnityEngine.UI.Extensions { [RequireComponent...
  • 需求:游戏中展示卡牌这种效果也是蛮酷炫并且使用的一种常见效果,下面我们就来实现以下这个效果是如何实现。 思考:第一看看到这个效果,我们首先会想到UGUI里面的ScrollRect,当然也可以用ScrollRect来实现缩短...
  • 最近项目中的活动面板要做来回滚动卡牌预览效果,感觉自己来写的话,也能写,但是可能会比较耗时,看到Github上有开源的项目,于是就借用了,Github的资源地址是:... 本篇博客旨在告诉大家如何利用这个插件。...
  • 3D循环效果,依据数学函数和细致研究下详细效果非常easy通过计算方式直接实现,本文主要目的是介绍下AnimationCurve工具,通过这个工具可以帮助我们实现一些需求当然也包含实现酷炫的3D滚动...
  • [UnityUI]循环滑动列表

    2017-09-20 16:01:26
    效果图: 使用的是UGUI和DOTween 其中比较关键的是循环滑动和层次排序: 1.循环滑动:这里先假设显示五张图片,分别标记为0,1,2,3,4,那么当向左滑动时,序列就变为1,2,3,4,0,这里先保存4的位置,然后从4开始...
  • 新建了一个带mask的prefab,加上代码只需要将图片prefab、按钮prefab和所想添加的图片 拖进去会自动生成按钮,滑动速度可以随意调time,滑动效果用itween实现的,所以需要加上itween插件 效果如下:(图片是我...
1 2 3
收藏数 59
精华内容 23