请添加图片描述

请添加图片描述


前言

  • 在众多游戏的主界面、商城、图鉴或关卡选择界面中,我们常常能看到轮播图的身影。
  • 它以动态、直观的方式展示游戏角色、皮肤、成就或场景,不仅极大地提升了界面的美观度和交互性,还能高效地引导玩家聚焦于核心内容。
  • 本篇文章将从零开始,一步步在Unity中构建一个功能完备、性能优良的游戏轮播图。
  • 使用UGUI系统,通过代码驱动,实现包括自动轮播、手动拖拽、分页指示器、无限循环等核心功能。
  • 无论是UI新手还是希望优化现有方案的开发者,这篇文章都将为你提供清晰的思路和完整的解决方案。

【Unity实战篇】| 游戏轮播图效果,多种实现思路及完整教程

效果展示

功能 效果
简易轮播 请添加图片描述
SuperScrollView轮播 请添加图片描述
FancyScrollView轮播 请添加图片描述

一、Unity原生制作简易轮播图效果

首先介绍一下使用Unity原生制作简易轮播图效果的方案,主打一个简单便捷,功能代码及操作步骤都非常简单。

下面一起来看下实现步骤及完成的效果展示。

1.1 搭建测试场景

在场景中新建一个ScrollView并在Content节点下添加一个Item预制,用来作为轮播图子物体使用。

给Content节点添加水平布局组件及布局控制器,用来实现水平自适应延伸。

再添加一个dotContent节点用作分页指示的父节点,在其节点下添加dotItem用作分页指示自动生成。

测试场景效果如下:
在这里插入图片描述

1.2 编写测试脚本

添加一个测试脚本BannerDemo1.cs,测试脚本完整代码如下:

using Example_Banner;
using System.Collections.Generic;
using UnityEngine;

public class BannerDemo1 : MonoBehaviour
{
    public RectTransform loopParent;
    public GameObject itemPrefab;

    public Transform dotParent;
    public GameObject dotItemPrefab;

    [Header("刷新间隔")]
    public float timeInterval = 3;

    private List<LoopTestItem> loopTestItemList = new List<LoopTestItem>();
    private List<DotUI> dotUIItemList = new List<DotUI>();
    private float timer;
    private int curShowIndex;

    private void Start()
    {
        itemPrefab.SetActive(false);
        dotItemPrefab.SetActive(false);
        for (int i = 1; i < 10; i++)
        {
            if (loopTestItemList.Count < i)
            {
                GameObject itemGo = GameObject.Instantiate(itemPrefab, loopParent.transform);
                loopTestItemList.Add(itemGo.GetComponent<LoopTestItem>());

                GameObject dotItemGo = GameObject.Instantiate(dotItemPrefab, dotParent.transform);
                dotItemGo.SetActive(true);
                dotUIItemList.Add(dotItemGo.GetComponent<DotUI>());
            }
            loopTestItemList[i - 1].SetData(i);
        }

    }

    void Update()
    {
        timer += Time.deltaTime;
        if (timer>= timeInterval)
        {
            curShowIndex += 1;
            timer = 0;
            if (curShowIndex >= loopTestItemList.Count)
            {
                curShowIndex = 0;
            }
            for (int i = 0;  i < dotUIItemList.Count; i++)
            {
                dotUIItemList[i].SetDisp(i == curShowIndex);
            }
        }
        loopParent.anchoredPosition = Vector3.Lerp(loopParent.anchoredPosition,
            new Vector2(-itemPrefab.GetComponent<RectTransform>().rect.width * curShowIndex, 0), Time.deltaTime * 10);
    }
}

给子对象Item身上挂载了一个测试脚本,用来标记当前展示的轮播图,测试脚本完整代码如下:

public class LoopTestItem : MonoBehaviour
{
    public Text TxtName;
    public void SetData(int index)
    {
        TxtName.text = index.ToString();
        transform.gameObject.SetActive(true);
    }
}

分支指示器的子对象身上也添加一个脚本DotUI.cs,用作展示当前轮播的分页标志。

	public sealed class DotUI : MonoBehaviour
	{
		[SerializeField] private GameObject	m_smallUI	= null;
		[SerializeField] private GameObject	m_largeUI	= null;

		public void SetDisp( bool isLarge )
		{
			m_smallUI.SetActive( !isLarge );
			m_largeUI.SetActive(  isLarge );
		}
	}

将BannerDemo1脚本挂载到场景中,将对应的节点拖到脚本上即可。
在这里插入图片描述

1.3 效果展示

这样一个简易的轮播图效果就实现了,支持自动轮播、分页展示及无限循环,效果如下:
请添加图片描述

实现步骤非常简单,通过添加一个计时器和一个当前轮播图的索引,达到指定时间后使用Vector3.Lerp方法,将Content组件的位置进行移动,移动到最后时再将其移动到第一个位置从而实现循环滚动。

除了不支持手动拖拽之外,轮播图其他应有的功能都有了。手动拖拽麻烦的地方在于拖拽后要加滑动定位,需要使用较为麻烦的逻辑实现。

下面则介绍一下可以轻松实现轮播图所有功能的方法,基本上使用ScrollView时都可以使用的方案。


二、使用 SuperScrollView实现高级轮播效果(推荐)

SuperScrollView是一个Unity中的循环列表插件,在之前的文章中介绍过该插件及常用功能:
【Unity 实用工具篇】 | UGUI 循环列表 SuperScrollView,快速上手使用

下面来展示一下使用该插件实现轮播图效果的步骤。

2.1 搭建测试场景

在场景中新建一个ScrollView并在Content节点下添加一个Item预制,用来作为轮播图子物体使用。

再添加一个DotsRoot节点用作分页指示的父节点,在其节点下添加dotsItem用作分页指示自动生成。

ScrollRect节点需要添加LoppListView2脚本,并添加一下Item参数及勾选 ItemSnapEnable

测试场景效果如下:
在这里插入图片描述

2.2 编写测试脚本

添加一个测试脚本BannerDemo2.cs,测试脚本完整代码如下:

using Example_Banner;
using SuperScrollView;
using System.Collections.Generic;
using UnityEngine;

public class BannerDemo2 : MonoBehaviour
{
    [SerializeField] private LoopListView2 m_view = null;
    [SerializeField] private Transform dotParent;
    [SerializeField] private GameObject dotItemPrefab;

    [Header("刷新间隔")][SerializeField] 
    private float m_interval = 0;

    private List<DotUI> m_dotUIList = new List<DotUI>();
    private float m_timer;

    private List<int> testList = new List<int> { 2, 4, 6, 8, 10 };//测试数据

    private void Start()
    {
        //初始化循环列表(调整滑动速率等参数)
        var initParam = new LoopListViewInitParam
        {
            mSmoothDumpRate = 0.1f,
            mSnapVecThreshold = 99999,
        };
        m_view.mOnSnapNearestChanged = OnSnapNearestChanged;
        //第一个参数传-1,代表开启循环
        m_view.InitListView(-1, OnUpdate, initParam);

        //分页指示生成
        dotItemPrefab.SetActive(false);
        for (int i = 1; i < testList.Count + 1; i++)
        {
            GameObject dotItemGo = GameObject.Instantiate(dotItemPrefab, dotParent.transform);
            dotItemGo.SetActive(true);
            m_dotUIList.Add(dotItemGo.GetComponent<DotUI>());
        }
    }

    /// <summary>
    /// 滑动列表后的回调方法
    /// </summary>
    /// <param name="view"></param>
    /// <param name="item"></param>
    private void OnSnapNearestChanged(LoopListView2 view, LoopListViewItem2 item)
    {
        int itemIndex = m_view.CurSnapNearestItemIndex;
        int count = testList.Count;
        int currentIndex = itemIndex % count + 1;
        for (int i = 1; i < count + 1; i++)
        {
            var dotUI = m_dotUIList[i - 1];
            dotUI.SetDisp(currentIndex == i);
        }
    }

    private LoopListViewItem2 OnUpdate(LoopListView2 view, int index)
    {
        if (index < 0) return null;
  
        var itemObj = view.NewListViewItem("item");
        var itemUI = itemObj.GetComponent<LoopTestItem>();
        int count = testList.Count;

        int wrapindex = (index % count) + 1;
        itemUI.SetData(wrapindex);
        return itemObj;
    }

    private void Update()
    {
        if (m_view.IsDraging)
        {
            m_timer = 0;
            return;
        }
        m_timer += Time.deltaTime;
        if (m_timer < m_interval) return;
        SetSnapIndex(1);
    }

    private void SetSnapIndex(int offset)
    {
        m_timer = 0;
        int currentIndex = m_view.CurSnapNearestItemIndex;
        int nextIndex = currentIndex + offset;
        m_view.SetSnapTargetItemIndex(nextIndex);
    }
}

给子对象Item身上挂载了一个测试脚本,用来标记当前展示的轮播图,测试脚本完整代码如下:

public class LoopTestItem : MonoBehaviour
{
    public Text TxtName;
    public void SetData(int index)
    {
        TxtName.text = index.ToString();
        transform.gameObject.SetActive(true);
    }
}

分支指示器的子对象身上也添加一个脚本DotUI.cs,用作展示当前轮播的分页标志。

	public sealed class DotUI : MonoBehaviour
	{
		[SerializeField] private GameObject	m_smallUI	= null;
		[SerializeField] private GameObject	m_largeUI	= null;

		public void SetDisp( bool isLarge )
		{
			m_smallUI.SetActive( !isLarge );
			m_largeUI.SetActive(  isLarge );
		}
	}

将BannerDemo2脚本挂载到场景中,将对应的节点拖到脚本上即可。
在这里插入图片描述
在这里插入图片描述

2.3 效果展示

请添加图片描述

与正常使用该插件实现循环列表类似,只不过通过设置参数赖实现无限循环轮播,而且支持手动拖拽、滑动定位,分页展示等。

使用该插件基本上可以满足轮播图的各种需求,还有很多参数可以调节,这里就不赘述了。


三、使用FancyScrollView轮播

FancyScrollView也是一个Unity中滑动列表插件,在之前的文章中介绍过该插件及常用功能:
【Unity 实用工具篇】 | 滚动列表插件FancyScrollView,快速上手使用

在该插件的示例场景中,也有一个LoopTabBar的示例Demo,可以实现循环展示的功能,感兴趣的小伙伴也可以导入该插件试试效果。
请添加图片描述


总结

  • 本文展示了多种轮播图的效果及制作方法,主要目的是增强游戏交互体验。
  • 具体实现效果可根据自己项目的实际需求进行调整及优化,且循环组件已经多个上线项目中使用,
  • 除了文中用到的轮播功能之外,还有很多种其他功能及示例,感兴趣的小伙伴可以自行下载体验。

  • 🎬 博客主页:https://xiaoy.blog.csdn.net

  • 🎥 本文由 呆呆敲代码的小Y 原创 🙉

  • 🎄 学习专栏推荐:Unity系统学习专栏

  • 🌲 游戏制作专栏推荐:游戏制作

  • 🌲Unity实战100例专栏推荐:Unity 实战100例 教程

  • 🏅 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!

  • 📆 未来很长,值得我们全力奔赴更美好的生活✨

  • ------------------❤️分割线❤️-------------------------

请添加图片描述请添加图片描述请添加图片描述

请添加图片描述

资料白嫖,技术互助

学习路线指引(点击解锁) 知识定位 人群定位
🧡 Unity系统学习专栏 入门级 本专栏从Unity入门开始学习,快速达到Unity的入门水平
💛 Unity实战类项目 进阶级 计划制作Unity的 100个实战案例!助你进入Unity世界,争取做最全的Unity原创博客大全。
❤️ 游戏制作专栏 难度偏高 分享学习一些Unity成品的游戏Demo和其他语言的小游戏!
💚 游戏爱好者万人社区 互助/吹水 数万人游戏爱好者社区,聊天互助,白嫖奖品
💙 Unity100个实用技能 Unity查漏补缺 针对一些Unity中经常用到的一些小知识和技能进行学习介绍,核心目的就是让我们能够快速学习Unity的知识以达到查漏补缺

请添加图片描述

Logo

这里是一个专注于游戏开发的社区,我们致力于为广大游戏爱好者提供一个良好的学习和交流平台。我们的专区包含了各大流行引擎的技术博文,涵盖了从入门到进阶的各个阶段,无论你是初学者还是资深开发者,都能在这里找到适合自己的内容。除此之外,我们还会不定期举办游戏开发相关的活动,让大家更好地交流互动。加入我们,一起探索游戏开发的奥秘吧!

更多推荐