EnhanceScollView选择角色3D循环滚动效果实现
需求
在游戏开发中,常常会有呈现3D效果(使用2D素材)的选择角色界面需求。该界面需要满足以下条件:
- 呈现3D效果(使用2D素材)的选择角色效果。
- 滚动时保证层级、缩放比例和间距正常跟随。
- 实现循环滚动。
如何实现
实现技术关键点
要实现上述需求,需要解决以下几个关键问题:
- 如何控制每个Item之间的间隔(位置)、缩放比例以及差值平滑。
- 如何实现Item层级关系的正确显示(离屏幕近的层级高)。
- 如何实现循环滚动。
3D循环效果的原理其实并不复杂。通过利用数学函数整理好位置和缩放关系,就可以较为容易地实现,而且这种方式更便于控制效果。下面将详细介绍当前Demo采用的方法,主要会介绍AnimationCurve这个工具。
AnimationCurve介绍
在Unity3D中,有一个名为AnimationCurve的组件。它不仅仅是美术人员用于创建动画的工具,也不只是简单的动画曲线概念。虽然它本质上是动画曲线,但我们可以赋予它不同的意义,从而借助曲线实现各种不同的功能。
AnimationCurve定义了一个变化趋势或曲线,在不同的时间点,我们可以获取该曲线对应的y轴信息。这个信息可以代表多种含义,例如角色跳跃的高度、模型缩放的系数、摄像机与目标的距离、角色当前的心情数值等。
如果您还没有使用过AnimationCurve,可以直接前往Unity官网查看相关介绍,了解其使用方法。下面简单列举一些使用AnimationCurve可以实现的功能:
- 角色2D跳跃
- 摄像机移动
- 角色心情指数
- 缩放系数
- 距离系数
控制位移、缩放和差值过渡动画平滑
我们可以赋予AnimationCurve不同的意义,以实现控制位移、缩放(3D效果的关键)以及差值过渡动画平滑的目标。具体步骤如下:
- 创建AnimationCurve:创建两个
AnimationCurve,分别为scaleAnimationCurve和positionXAnimationCurve,用于控制缩放和位移。 - 时间流水线控制:将所有的Item设置好各自对应的时间流位置。每次移动时间流水线时,从两个曲线中获取当前流水线对应的缩放系数和位移系数,然后设置Item的位移和缩放。
- 制作动画:这实际上是简单的时间流水线差值处理,在一定时间内使时间流水值达到目标值即可。
以下是相关曲线截图和具体实现代码:

/// <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);
}
控制层级
为了保证界面效果“不穿帮”,需要正确控制层级。本Demo采用的是比较简单粗暴的列表排序方法,按照每个Item距离“屏幕的远近”(即scale系数)来判断哪个Item在前,哪个在后。不过这种方法存在一个问题,如果两个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将其移动到中心时,时间流应该往前或往后移动的间隔数:
/// <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;
}
注意问题
- 制作曲线:在制作曲线时,要确保0 - 1时间轴填充完毕,这样在进行循环处理时才不会出现偏差。
- 参数查看:如果您尝试使用这种方法遇到问题,请仔细查看Demo中的参数,主要问题可能出在曲线制作上。
本Demo使用的是NGUI,虽然笔者没有使用过UGUI,但我认为任何一个界面工具都可以通过这种方法实现,因为其共同点是相似的,只是层级处理和缩放处理有所区别。
实现效果

改进目标
该项目还有许多需要改进的地方,后续会花时间继续完善:
- 支持Editor模式下的编辑,无需运行即可查看效果(这应该是最关键的功能)。
- 支持偶数个Item进行滑动。
- 支持Drag操作。
- 支持和NGUI类似的DragScrollView和CenterOnChild功能。
- 优化每个Item的层级设置算法效率。
- 优化更新每个Item位置和缩放的算法效率。
总结
以上就是关于EnhanceScrollView选择角色3D循环滚动效果实现的全部内容。如果这篇文章能对您有所启发,请给予支持。如果文中存在错误或描述不清楚的地方,请您指正,让我们共同交流学习。您可以直接下载Demo,查看其中的逻辑和动画曲线的设置参数。欢迎转载,请注明出处。