欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Unity3d实现无限循环滚动背景

程序员文章站 2022-06-09 18:02:23
在游戏项目中我们常常看到商城的广告牌,几张广告图片循环滚动,类似跑马灯,现在我将讨论一种实现方法,并提供一个管理类,大家可以直接使用。实现原理:背景图片循环滚动的原理很简单:两张图片向一个方向移动,当...

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

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

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

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

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

下面谈谈我的方法:

第一步:创建滚动组件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;
    }
}
}

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