Unity3d实现无限循环滚动背景

在游戏项目中我们常常看到商城的广告牌,几张广告图片循环滚动,类似跑马灯,现在我将讨论一种实现方法,并提供一个管理类,大家可以直接使用。

实现原理:背景图片循环滚动的原理很简单:两张图片向一个方向移动,当达某张图片到临界区域时将图片放在后面,依次循环。

在实际项目中,广告牌显示的图片数量不确定,例如某个假期活动会上很多新品,此时我们需要动态的创建显示的图片(一般在配置表读取数据),如果需要显示分类标签还得动态生成分类标签。

综上所述,一个完整的广告牌组件应该具有以下功能:

- 无限循环的滚动背景图片
- 根据读取的数据动态生成图片
- 具有分类标签,根据显示图片动态生成
- *做成一个管理类,方便使用(一个项目中可能多处会用到)

下面谈谈我的方法:

第一步:创建滚动组件AdvertisementScroll,这个组件挂在GameObject上面,接受传递过来的数据,生成显示的图片和分类标签,在Update中实现无限循环滚动。

using System.Collections.Generic;
using UnityEngine;
namespace Assets.Scripts.Client
{ 
    public class AdvertisementScroll : MonoBehaviour
    {   
         private float _timer;
         private bool _isStart;
         private Vector3 _toggleCenter;
         private int delDistance;
         private int _currentPage; //当前页面    
         private AdvertisementScrollManager.AdvertisementScrollData _itemData;       
         private List<ToggleData> _toggleList = new List<ToggleData>();        
         private Vector3 _toLeftPosition;//向左滑动到某个位置
         public class ToggleData
         {
            public string name;
            public GameObject go;
         }

        public AdvertisementScrollManager.AdvertisementScrollData ItemData
        {
            get { return _itemData; }
            set { _itemData = value; }
        }

    public void StartScroll(bool createToggle)
    {
        if (!_isStart)
        {
            CreateAdvertiseBg();
            CreateAdvertiseToggle(createToggle);
            if (createToggle)
            {
                if (ItemData.ToggleItem != null)
                {
                    ItemData.ToggleItem.GetComponent<UIToggle>().value = true;
                }                  
            }               
            _currentPage = 1;
            _isStart = true;
        }        
    }
    /// <summary>
    /// 创建需要显示的图片(需要图片数量,图片精灵名称,图片的宽度,图片左边和右边的显示位置)
    /// </summary>
    private void CreateAdvertiseBg()
    {

        _toLeftPosition = new Vector3(ItemData.LeftPosition.x - ItemData.SpriteWidth, ItemData.LeftPosition.y, ItemData.LeftPosition.z);
        for (int i = 0; i < ItemData.MaxPage; i++)
        {
            GameObject firstSpriteItem;
            GameObject secondSpriteItem;
            if (i == 0)
            {
                firstSpriteItem = secondSpriteItem = ItemData.SpriteItem.gameObject;
            }
            else
            {
                firstSpriteItem = ItemData.FirstMoveGo.gameObject.AddChild(ItemData.SpriteItem.gameObject);
                firstSpriteItem.SetActive(false);
                secondSpriteItem = ItemData.SecondMoveGo.gameObject.AddChild(ItemData.SpriteItem.gameObject);
                secondSpriteItem.SetActive(false);
            }
            firstSpriteItem.transform.localPosition = secondSpriteItem.transform.localPosition = Vector3.zero;
            firstSpriteItem.name = secondSpriteItem.name = (i + 1).ToString();
            firstSpriteItem.GetComponent<UISprite>().spriteName = secondSpriteItem.GetComponent<UISprite>().spriteName = ItemData.SpriteName[i];
        }
    }

    /// <summary>
    /// 创建分页图片,默认不创建(需要分页图片,分页的中间位置,每个分页的间隔)
    /// </summary>
    /// <param name="create"></param>
    private void CreateAdvertiseToggle(bool create = false)
    {
        if (create)
        {
            _toggleCenter = ItemData.ToggleCenterPos;
            delDistance = ItemData.ToggleDistance;       
            Vector3 firstpoint = _toggleCenter - new Vector3((ItemData.MaxPage / 2f - 0.5f) * delDistance, 0f, 0f);
            for (int i = 0; i < ItemData.MaxPage; i++)
            {
                GameObject item;
                ToggleData toggleData = new ToggleData();
                if (i == 0)
                {
                    item = ItemData.ToggleItem.gameObject;
                }
                else
                {
                    item = ItemData.ToggleContainer.gameObject.AddChild(ItemData.ToggleItem.gameObject);
                }
                item.transform.localPosition = firstpoint + new Vector3(i*delDistance, 0f, 0f);
                item.name = "toggle" + i;
                toggleData.go = item;
                toggleData.name = item.name;
                _toggleList.Add(toggleData);
            }
        }
    }

    void Update()
    {
        if (!_isStart)
        {
            return;              
        }
        if (Time.frameCount % (30 * ItemData.MoveTime) == 0 && ItemData.MaxPage > 1)
        {
            if (ItemData.FirstMoveGo.localPosition.x < ItemData.LeftPosition.x - 0.5)
            {
                ItemData.FirstMoveGo.localPosition = ItemData.RightPosition;
            }
            if (ItemData.SecondMoveGo.localPosition.x < ItemData.LeftPosition.x - 0.5)
            {
                ItemData.SecondMoveGo.localPosition = ItemData.RightPosition;
            }
            Transform leftTran = ItemData.FirstMoveGo.localPosition.x < ItemData.SecondMoveGo.localPosition.x ? ItemData.FirstMoveGo : ItemData.SecondMoveGo;
            Transform rightTran = ItemData.FirstMoveGo.localPosition.x < ItemData.SecondMoveGo.localPosition.x ? ItemData.SecondMoveGo : ItemData.FirstMoveGo;
            TweenPosition.Begin(rightTran.gameObject, 0.5f, ItemData.LeftPosition, false);
            TweenPosition.Begin(leftTran.gameObject, 0.5f, _toLeftPosition, false);
            _currentPage = FixPage(_currentPage);
            SetPic(rightTran, _currentPage);
            //SetBtn(leftTran,false);
            //SetBtn(rightTran,true);               
            _toggleList[_currentPage - 1].go.GetComponent<UIToggle>().value = true;
        }
    }

    private void SetBtn(Transform tran, bool state)
    {
        Transform tf = tran.Find("Icon");
        if (tf != null)
        {
            tf.gameObject.SetActive(state);
        }           
    }

    private void SetPic(Transform tran, int _currentPage)
    {
        foreach (Transform t in tran)
        {
            if (t.name == _currentPage.ToString())
            {
                t.gameObject.SetActive(true);
            }
            else
            {
                t.gameObject.SetActive(false);
            }
        }
    }

    private int FixPage(int page)
    {
        page++;
        if (page > ItemData.MaxPage)
        {
            page = 1;
        }
        return page;
    }
}    
}

第二步:创建管理类AdvertisementScrollManager,将它做成一个单例,调用AdvertisementScroll的方法,开始滚动。

using UnityEngine;
using System.Collections.Generic;
namespace Assets.Scripts.Client
{
public class AdvertisementScrollManager : Singleton<AdvertisementScrollManager>
{  
    public struct AdvertisementScrollData
    {
        public bool IsCreateToggle;       //是否创建分页标签
        public Transform ToggleItem;      //分页标签
        public Transform ToggleContainer; //分页标签所在的Panel
        public Vector3 ToggleCenterPos;   //分页标签的中间位置
        public int ToggleDistance;        //分页标签之间的间隔
        public Transform FirstMoveGo;     //移动的物体
        public Transform SecondMoveGo;    //移动的物体
        public Vector3 LeftPosition;      //移动物体的左边位置
        public Vector3 RightPosition;     //移动物体的右边位置
        public Transform SpriteItem;      //显示的图片
        public int SpriteWidth;           //图片的宽度
        public string[] SpriteName;       //显示的所有图片在图集中的名称
        public int MaxPage;               //最大的页面
        public int MoveTime;              //每隔多少秒移动一次

    };

    public void StartAdvertisementScroll(Transform parentTf, AdvertisementScrollData data,bool createToggle = false)
    {
        if (parentTf != null)
        {
            UIPanel panel = parentTf.GetComponent<UIPanel>();
            if (panel == null)
            {
                return;
            }
            AdvertisementScroll scroll = null;
            Transform tf = parentTf.Find("AdvertisementScroll");
            if (tf == null)
            {
                GameObject go = new GameObject();
                go.name = "AdvertisementScroll";
                go.transform.parent = parentTf;
                go.transform.localPosition = Vector3.zero;
                go.transform.localScale = new Vector3(1, 1, 1);
                //go.layer = LayerModel.UILayer;
                tf = go.transform;
                scroll = tf.gameObject.AddComponent<AdvertisementScroll>();                  
            }
            else
            {
                scroll = tf.gameObject.GetComponent<AdvertisementScroll>();
            }
            scroll.ItemData = data;
            scroll.ItemData.FirstMoveGo.parent = tf;
            scroll.ItemData.SecondMoveGo.parent = tf;
            scroll.StartScroll(createToggle);
        }
    }
}
}

第三步:使用。预制体的制作方法就不说了,代码看懂了自然好弄,后面也会附上工程文件。你在任何一个界面需要使用广告牌组件时只需要先设置好数据,然后调用AdvertisementScrollManager中的StartAdvertisementScroll方法就可以了。

using Assets.Scripts.Client;
using UnityEngine;

namespace Assets
{
public class AdvertiseScrollSample : MonoBehaviour
{
    private Transform _firstMoveGo;
    private Transform _secondMoveGo;
    private Transform _container;
    private Transform _toggleContainer;
    private Transform _spriteItem;
    private Transform _toggleItem;      
    void Start ()
    {
        _firstMoveGo = transform.Find("Panel/Container/First");
        _secondMoveGo = transform.Find("Panel/Container/Second");
        _container = transform.Find("Panel/Container");
        _toggleContainer = transform.Find("Panel/ToggleContainer");
        _spriteItem = transform.Find("Panel/Container/First/Item");
        _toggleItem = transform.Find("Panel/ToggleContainer/ToggleItem");
        OnRefreshData();
    }

    void OnRefreshData()
    {
        AdvertisementScrollManager.AdvertisementScrollData data = CreateAdvertisementScrollData();
        AdvertisementScrollManager.Instance.StartAdvertisementScroll(_container,data,data.ToggleContainer);
    }

    private AdvertisementScrollManager.AdvertisementScrollData CreateAdvertisementScrollData()
    {
        AdvertisementScrollManager.AdvertisementScrollData data = new AdvertisementScrollManager.AdvertisementScrollData();
        //设置显示图片的数量和滑动的时间间隔
        data.MoveTime = 10;
        data.MaxPage = 3;
        //设置图片的位置信息
        data.FirstMoveGo = _firstMoveGo;
        data.SecondMoveGo = _secondMoveGo;
        data.SpriteItem = _spriteItem;
        data.SpriteWidth = 884;
        data.SpriteName = new string[] { "1", "2", "3" };
        data.LeftPosition = Vector3.zero;
        data.RightPosition = new Vector3(800, 0, 0);
        //设置分页标签信息(如果不需要分页标签,可以不用赋值)
        data.IsCreateToggle = true;
        data.ToggleItem = _toggleItem;
        data.ToggleContainer = _toggleContainer;  
        data.ToggleCenterPos = new Vector3(0,-200,0);
        data.ToggleDistance = 30;                              
        return data;
    }
}
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Unity UI组件ScrollRect实现无限滚动条

    在游戏开发中 经常遇到滚动显示的数据 特别是商店商品 排行榜 .......等 数据很多,每一条数据去加载一个UI来显示显然对内存浪费很大,这种情况处理一般就是用几个显示条可滚动循环显示无限数据条.本篇介绍实现过程和大体思路以及可重用的滑动脚本InfinityGridLayoutGroup和MarketLayoutGroup数据管理刷新脚本.MarketElement类要看具体项目中具体数据结构来设计:仅供参考. 一 .总体流程 建一个循环滑动脚本 InfinityGridLayoutGroup

  • Unity UGUI实现卡片椭圆方向滚动

    本文实例为大家分享了UGUI实现卡片椭圆方向滚动的具体代码,供大家参考,具体内容如下 搭建简单的场景 运行效果 卡片移动动画通过插件DoTween实现 控制脚本: using UnityEngine; using System.Collections; using UnityEngine.UI; using DG.Tweening; public class CardMove : MonoBehaviour { GameObject[] sprites; int halfSize; Vector

  • Unity实现3D循环滚动效果

    本文实例为大家分享了Unity实现3D循环滚动效果展示的具体代码,供大家参考,具体内容如下 然后通过SetDepthAndPosition这个方法,实现图片的空间空间展开 Z轴和Y轴,系数是一样的 经过上面设置,空间就摆开了 using UnityEngine; using System.Collections; using System.Collections.Generic; public class SelectRole : MonoBehaviour { public GameObjec

  • Unity3D实现待机状态图片循环淡入淡出

    本文实例为大家分享了Unity3D实现图片循环淡入淡出的具体代码,供大家参考,具体内容如下 1.说明 由于近期项目需求,在网上找了淡入淡出的代码,但都是两张图片淡入淡出结束后就没有了(可能我没找到其他好的作品).所以我做了简单的扩展 2.简单思路 既然待机状态下的图片淡入淡出切换,所以,首先要判断何时为待机状态(即屏幕没有任何操作的情况下):其次,图片静止一段时间后,开始淡入淡出,第一张图片淡入,第二张淡出:接着图片再次静止一段时间,然后接着下次的淡入淡出,但因为是循环淡入淡出,所以要考虑重新加

  • Unity3d实现无限循环滚动背景

    在游戏项目中我们常常看到商城的广告牌,几张广告图片循环滚动,类似跑马灯,现在我将讨论一种实现方法,并提供一个管理类,大家可以直接使用. 实现原理:背景图片循环滚动的原理很简单:两张图片向一个方向移动,当达某张图片到临界区域时将图片放在后面,依次循环. 在实际项目中,广告牌显示的图片数量不确定,例如某个假期活动会上很多新品,此时我们需要动态的创建显示的图片(一般在配置表读取数据),如果需要显示分类标签还得动态生成分类标签. 综上所述,一个完整的广告牌组件应该具有以下功能: - 无限循环的滚动背景图

  • iOS中无限循环滚动简单处理实现原理分析

    说下原理: 1./*初始化/ + (instancetype)loopScrollViewWithFrame:(CGRect)frame; 将背景collectinview视图初始化设置 代理和数据源 . 布局 2.在激活initwithFrame后触发 layoutSubviews //默认滚动到要显示的第一张图片 if (self.imageCollectionView.contentOffset.x == 0) { NSIndexPath *indexPath = [NSIndexPath

  • iOS实现无限循环滚动的TableView实战教程

    前言 本文主要给大家介绍了如何实现一个可以无限循环的TableView的相关内容,分享出来供大家参考学习,下面来一起看看详细的介绍吧. 先来看看效果: 思路 条条大路通罗马,个人分析下以下思路的可行性: 1.借鉴无限广告轮播的思路.可行性不高,主要是列表头部和尾部的衔接不够自然,而且快速滑动不够流畅. 2.使用TableView+3倍长度dataSource.可行性一般,在使用过程中滑动流畅,但是由于重复的数据源,可能导致在处理事件时需要特别对数据进行处理避免重复,另外此方法不能重用,总让有强迫

  • iOS UIScrollView滚动视图/无限循环滚动/自动滚动的实例代码

    我们都知道UIScrollView有一种很流畅的切换效果,结合UIPageControl的辅助展示效果,就可以完成一个很不错的产品介绍功能页面.下面给大家分享iOS UIScrollView滚动视图/无限循环滚动/自动滚动功能,具体代码如下所示: <UIScrollViewDelegate> #define WIDTH [[UIScreen mainScreen] bounds].size.width #define HEIGHT [[UIScreen mainScreen] bounds].

  • Android ViewPager实现智能无限循环滚动回绕效果

    android系统提供的ViewPager标准方式是左右可以自由滑动,但是滑动到最左边的极限位置是第一个page,滑动到最右边的位置是最后一个page,当滑动到最左或者最右时候,就不能再滑动/滚动了,这是Android系统默认的ViewPager实现方式. 但是有些情况下开发者可能希望ViewPager能够智能的无限循环滚动回绕,比如现在总共有编号1, 2, 3, 4, 5的5个Page. (1)当用户手指从右往左滚动到最右边/最后面的页面5时候,如果此时用户继续拖住ViewPager往左边滑动

  • Android ListView实现无限循环滚动

    本文实例为大家分享了Android无限循环滚动的具体代码,供大家参考,具体内容如下 因项目需要循环展示列表数据,所以就实现了这个无限循环滚动的 LIstView.先说一下原理,原理呢,其实很简单,首先将要展示的数据循环展示三遍 监听ListView的滚动事件,当ListView滚动到第一遍第第二个时,ListView变自动跳到第二遍的第二个,同理,如果ListView滚动到倒数第一个时,ListView自动跳转到第二遍的倒数第一个,然后可以不停的向上或者向下滑动,永远不会到头,废话少说,上 代码

  • Vue实现一种简单的无限循环滚动动画的示例

    本文主要介绍了Vue实现一种简单的无限循环滚动动画的示例,分享给大家,具体如下: 先看实现效果: 这种类似轮播的效果,通常可以使用轮播的方案解决,只不过相对于我要分享的方案来说,轮播实现还是要复杂些的. Vue提供了一种过渡动画transition-group,这里我便是利用的这个效果 // template <transition-group name="list-complete" tag="div"> <div v-for="v i

  • react实现无限循环滚动信息

    本文实例为大家分享了react实现无限循环滚动信息的具体代码,供大家参考,具体内容如下 需求 后端传递过来的数据滚动显示,鼠标移入后停止滚动,鼠标移出后继续滚动,参考公司门户的公告信息栏 实现思路 思路一 在componentDidMount中定义一个定时器,每过1000ms触发一次事件,将数组中第一条数据push到数组中,再删除掉第一条数据,最后给div添加onMouEnter和onMouseLeave事件,让鼠标移入时清除定时器,鼠标移出时重新开启定时器. 代码: class Roll ex

  • Android实现横向无限循环滚动的单行弹幕效果

    本期将带领大家实现一个这样的效果,支持无限循环的单行弹幕效果. 实现思路分析 要实现上面的效果,我们先拆分下实现要素: 1.弹幕布局是从屏幕的右侧向左侧滚动,单个弹幕之间的间距是固定的(设计要求) 2.弹幕要支持无限滚动,出于性能要求,如果不在屏幕内的,应该移除,不能无限追加到内存里面. 拆分完需求要素之后,针对上面的需求要素,做一下思路解答: 1.对于滚动和超出屏幕后移除,可以使用动画来实现,动画从屏幕右边开始移动到屏幕左边,监听如果已经动画结束,则remove掉布局. 2.无限循环效果,可以

  • Android实现无限循环滚动

    传统的ViewPager做循环滚动有两种思路. 一种是设置count为Integer.MAX,然后根据index对实际数量取模 一种是在开头在开头添加end,在末尾添加start.简单的说就是多两个,滑动到这两个的时候直接setCurrentItem到真正的位置. 在观察pdd的拼单的循环滚动的时候,想到几种实现方式. 1.通过Recyclerview,同样跟ViewPager做循环滚动的思路类似,多一点要拦截掉所有的触摸事件.但是这种方式的话无法像pdd的效果那样设置进入和出去的动画. 2.通

随机推荐