Unity3D问题之EnhanceScollView选择角色3D循环滚动效果实现

需求

  • 呈现3D效果(2D素材)选择角色效果
  • 滚动保证层级。缩放比例。间距正常尾随
  • 循环滚动
  • 这个界面需求一般也会有游戏会採用(貌似有挺多)

怎样实现

实现技术关键点

(3D循环效果,依据数学函数和细致研究下详细效果非常easy通过计算方式直接实现,本文主要目的是介绍下AnimationCurve工具,通过这个工具可以帮助我们实现一些需求当然也包含实现酷炫的3D滚动效果)

  1. 怎样控制每一个Item之间的间隔(位置)。缩放比例,差值平滑
  2. 怎样实现item层级关系正确显示("离" 屏幕近的层级高)
  3. 怎样实现循环滚动

以下一一讲述当前Demo採用的方法
说到实现的核心,须要知道Unity3D中提供的一个叫做AnimationCurve的组件。这个不不过表面上美术能够使用的组件,也不不过单纯的动画曲线的概念,当然它就是动画曲线,可是我们能够赋予AnimationCurve不同的意义。则能够借助Curve实现不同的功能,(AnimationCurve定义了一个变化趋势或者曲线,在不同的时间点,我们能够得到当前时间点下该曲线相应的y轴信息。这个信息能够是角色跳跃的高度。模型缩放的一个系数,摄像机距离目标的长度。一个角色当前的心情数值等等。曲线能够表示非常多的意义)
没用过AnimationCurve的朋友,直接去官网看下介绍就明确怎样使用
以下简单说下使用AnimationCurve能够完毕的一些功能(上面已经介绍了一部分场景)

  1. 角色2D跳跃
  2. 摄像机移动
  3. 角色心情指数
  4. 缩放系数
  5. 距离系数
  6. ......

我们也赋予AnimationCurve不同的意义,实现我们核心目标(控制位移。控制缩放 当然也能够控制层级)

控制位移,缩放(3D效果的关键),差值过度动画平滑

  1. 创建两个AnimationCurve一个是scaleAnimationCurve和positionXAnimationCurve,分别控制缩放和位移
  2. 时间流水线控制(我们把全部的Item设置好自己相应的时间流位置就可以,每次仅仅要一动时间流水线,然后从两个曲线内获得当前流水线相应的缩放系数,位移系数,然后设置item的位移和缩放就可以)
  3. 怎样制作动画(这个事实上就是简单的时间流水线的差值处理,一定时间时间流水值达到目标值就可以)
以下放上两张曲线截图和详细实现:


/// <summary>
    /// 缩放曲线模拟当前缩放值
    /// </summary>
    private float GetScaleValue(float sliderValue, float added)
    {
        float scaleValue = scaleCurve.Evaluate(sliderValue + added);
        return scaleValue;
    }

    /// <summary>
    /// 位置曲线模拟当前x轴位置
    /// </summary>
    private float GetXPosValue(float sliderValue, float added)
    {
        float evaluateValue = positionCurve.Evaluate(sliderValue + added) * posCurveFactor;
        return evaluateValue;
    }

public void UpdateEnhanceScrollView(float fValue)
    {
        for (int i = 0; i < scrollViewItems.Count; i++)
        {
            EnhanceItem itemScript = scrollViewItems[i];
            float xValue = GetXPosValue(fValue, dHorizontalValues[itemScript.scrollViewItemIndex]);
            float scaleValue = GetScaleValue(fValue, dHorizontalValues[itemScript.scrollViewItemIndex]);
            itemScript.UpdateScrollViewItems(xValue, yPositionValue, scaleValue);
        }
    }

    void Update()
    {
        currentDuration += Time.deltaTime;
        if (currentDuration > duration)
        {
            // 更新完成设置选中item的对象就可以
            currentDuration = duration;
            if(centerItem != null)
                centerItem.SetSelectColor(true);
            if(preCenterItem != null)
                preCenterItem.SetSelectColor(false);
            canChangeItem = true;
        }

        SortDepth();
        float percent = currentDuration / duration;
        horizontalValue = Mathf.Lerp(originHorizontalValue, horizontalTargetValue, percent);
        UpdateEnhanceScrollView(horizontalValue);
    }

控制层级

仅仅有正确的层级控制。才干够保证"不穿帮",上文也说过,也能够通过AnimationCurve做一个层级曲线,在当前item的时间以下该item的depth或者层级应该是多少,该demo採用的是比較粗暴的list排序方法。依照每一个item距离"屏幕的远近"事实上就是scale系数。推断哪个item在前,哪个在后面,当然也有些问题,假设距离同样,可能存在item相互打架的可能(这个能够通过控制scaleCurve进行控制)
该Demo使用的UITexture控制层级(其它的不论什么方式原理一样,仅仅是处理对象不一样,用mesh实现。那就是z轴等等)
详细实现例如以下:

public void SortDepth()
    {
        textureTargets.Sort(new CompareDepthMethod());
        for (int i = 0; i < textureTargets.Count; i++)
            textureTargets[i].depth = i;
    }
    /// <summary>
    /// 用于层级对照接口
    /// </summary>
    public class CompareDepthMethod : IComparer<UITexture>
    {
        public int Compare(UITexture left, UITexture right)
        {
            if (left.transform.localScale.x > right.transform.localScale.x)
                return 1;
            else if (left.transform.localScale.x < right.transform.localScale.x)
                return -1;
            else
                return 0;
        }
    }

实现滚动循环

说道循环滚动,由于我们使用到了AnimationCurve,先天性的动画曲线会有三种模式一种是pingpong。loop,一种是clamp,当中我们须要的是LOOP,没听错这就是滚动循环的关键点(我们的缩放曲线。位移系数曲线从0到1的效果模拟完成,假设我们继续向前添加时间流水值,那么进入到下一个曲线的时候。全部的item都会反过来进行採样曲线值。就行巧妙的实现循环效果(缩放系数。位移系数))假设不理解的,可以自己设置一个AnimationCurve,研究下,以下截图示意:

代码部分仅仅是须要知道。假设点击了一个Item将该item移动到中心相应的时间流应该往前或者往后走多少

    /// <summary>
    /// 获得当前要移动到中心的Item须要移动的factor间隔数
    /// </summary>
    private int GetMoveCurveFactorCount(float targetXPos)
    {
        int centerIndex = scrollViewItems.Count / 2;
        for (int i = 0; i < scrollViewItems.Count;i++ )
        {
            float factor = (0.5f - dFactor * (centerIndex - i));

            float tempPosX = positionCurve.Evaluate(factor) * posCurveFactor;
            if (Mathf.Abs(targetXPos - tempPosX) < 0.01f)
                return Mathf.Abs(i - centerIndex);
        }
        return -1;
    }

注意问题

  1. 制作曲线。记得保证0-1时间轴填充完成。这样在进行循环处理的时候才不会出现偏差
  2. 额,假设自己用这样的方法尝试的朋友,假设有问题,请细致查看Demo中的參数就可以......(主要就是曲线制作问题)

该Demo使用的NGUI,尽管笔者没实用过UGUI,我想不论什么一个界面Tools都能够通过该方法实现,由于共同点一样。仅仅是层级处理,缩放处理有差别而已

实现效果






改进目标

该项目还有很多须要改进的地方,以后花时间继续完好

  • 支持Editor模式下的编辑,不用执行就可以查看效果(这个应该是最关键的功能)
  • 支持偶数个Item进行滑动
  • 支持Drag操作
  • 支持和NGUI类似的DragScrollView和CenterOnChild功能
  • 优化每一个Item的层级设置算法效率
  • 优化更新每一个Item位置,缩放算法效率

问题:
1. 在处理曲线循环的地方,因为准确度不够。导致持续点按过后会造成卡片大小发生变化,兴许直接使用单一曲线或者通过程序控制曲线精确~

GitHub地址:兴许更新会直接在版本号库中更新

https://github.com/tinyantstudio/EnhancedScrollView


APK測试安装地址:http://pan.baidu.com/s/1bnfPasJ

总结

全部的内容都讲述完成。假设这篇文章可以帮助到您获得对看到结束的朋友有一个简单的启示,请支持下~,文中存在错误或者描写叙述不清楚的也请指正,共同交流学习,最好的方法就是直接下载Demo。然后看下逻辑和动画曲线的设置參数

欢迎转载,请注明出处~

By NPC燕(AndyKun)



原文地址:https://www.cnblogs.com/mengfanrong/p/5314002.html