EnhanceScollView选择角色3D循环滚动效果实现

2015年10月27日 11:56 0 点赞 0 评论 更新于 2025-11-21 19:15

需求

在游戏开发中,常常会有呈现3D效果(使用2D素材)的选择角色界面需求。该界面需要满足以下条件:

  1. 呈现3D效果(使用2D素材)的选择角色效果。
  2. 滚动时保证层级、缩放比例和间距正常跟随。
  3. 实现循环滚动。

如何实现

实现技术关键点

要实现上述需求,需要解决以下几个关键问题:

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

3D循环效果的原理其实并不复杂。通过利用数学函数整理好位置和缩放关系,就可以较为容易地实现,而且这种方式更便于控制效果。下面将详细介绍当前Demo采用的方法,主要会介绍AnimationCurve这个工具。

AnimationCurve介绍

在Unity3D中,有一个名为AnimationCurve的组件。它不仅仅是美术人员用于创建动画的工具,也不只是简单的动画曲线概念。虽然它本质上是动画曲线,但我们可以赋予它不同的意义,从而借助曲线实现各种不同的功能。

AnimationCurve定义了一个变化趋势或曲线,在不同的时间点,我们可以获取该曲线对应的y轴信息。这个信息可以代表多种含义,例如角色跳跃的高度、模型缩放的系数、摄像机与目标的距离、角色当前的心情数值等。

如果您还没有使用过AnimationCurve,可以直接前往Unity官网查看相关介绍,了解其使用方法。下面简单列举一些使用AnimationCurve可以实现的功能:

  • 角色2D跳跃
  • 摄像机移动
  • 角色心情指数
  • 缩放系数
  • 距离系数

控制位移、缩放和差值过渡动画平滑

我们可以赋予AnimationCurve不同的意义,以实现控制位移、缩放(3D效果的关键)以及差值过渡动画平滑的目标。具体步骤如下:

  1. 创建AnimationCurve:创建两个AnimationCurve,分别为scaleAnimationCurvepositionXAnimationCurve,用于控制缩放和位移。
  2. 时间流水线控制:将所有的Item设置好各自对应的时间流位置。每次移动时间流水线时,从两个曲线中获取当前流水线对应的缩放系数和位移系数,然后设置Item的位移和缩放。
  3. 制作动画:这实际上是简单的时间流水线差值处理,在一定时间内使时间流水值达到目标值即可。

以下是相关曲线截图和具体实现代码: ScorollView参数缩放曲线 位移系数曲线 ScorollView参数

/// <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;
}

注意问题

  1. 制作曲线:在制作曲线时,要确保0 - 1时间轴填充完毕,这样在进行循环处理时才不会出现偏差。
  2. 参数查看:如果您尝试使用这种方法遇到问题,请仔细查看Demo中的参数,主要问题可能出在曲线制作上。

本Demo使用的是NGUI,虽然笔者没有使用过UGUI,但我认为任何一个界面工具都可以通过这种方法实现,因为其共同点是相似的,只是层级处理和缩放处理有所区别。

实现效果

最终效果 GIF

改进目标

该项目还有许多需要改进的地方,后续会花时间继续完善:

  1. 支持Editor模式下的编辑,无需运行即可查看效果(这应该是最关键的功能)。
  2. 支持偶数个Item进行滑动。
  3. 支持Drag操作。
  4. 支持和NGUI类似的DragScrollView和CenterOnChild功能。
  5. 优化每个Item的层级设置算法效率。
  6. 优化更新每个Item位置和缩放的算法效率。

总结

以上就是关于EnhanceScrollView选择角色3D循环滚动效果实现的全部内容。如果这篇文章能对您有所启发,请给予支持。如果文中存在错误或描述不清楚的地方,请您指正,让我们共同交流学习。您可以直接下载Demo,查看其中的逻辑和动画曲线的设置参数。欢迎转载,请注明出处。

作者信息

洞悉

洞悉

共发布了 3994 篇文章