2016-10-31 12:00:27 qq_22329587 阅读数 2413

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

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

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

综上所述,一个完整的广告牌组件应该具有以下功能:
- 无限循环的滚动背景图片
- 根据读取的数据动态生成图片
- 具有分类标签,根据显示图片动态生成
- *做成一个管理类,方便使用(一个项目中可能多处会用到)


下面谈谈我的方法:
第一步:创建滚动组件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;
    }
}
}
2017-07-24 11:10:43 qq_15267341 阅读数 4430

这里写图片描述


然后通过SetDepthAndPosition这个方法,实现图片的空间空间展开


这里写图片描述



这里写图片描述


Z轴和Y轴,系数是一样的


经过上面设置,空间就摆开了


这里写图片描述



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

public class SelectRole : MonoBehaviour {
    public GameObject rolesObj;
    private int _half = 0;//一侧的卡片数
    private int _movX = 150;//X轴移动距离
    private int _movY = 50;//Y轴移动距离
    private int _movZ = 60;//Z轴移动距离
    private int count = 3;//组件数
    private List<RoleItem> _roleList = new List<RoleItem>();

    // Use this for initialization
    void Start () {
        //加载图片
        Object[] textureList = (Object[])Resources.LoadAll("Pictures");

        int maxDepth = textureList.Length % 2 == 1 ? textureList.Length / 2 + 1 : textureList.Length / 2;//最大深度
        _half = maxDepth;      

        for (int i = 0; i < textureList.Length; i++)
        {            
            //加载角色图片预设
            GameObject role = Instantiate(Resources.Load("Role", typeof(GameObject))) as GameObject;            
            role.transform.parent = rolesObj.transform;
            role.transform.localScale = Vector3.one;

            EventDelegate.Add(role.GetComponent<UIToggle>().onChange , RoleToggleChange);

            RoleItem item = role.GetComponent<RoleItem>();            
            item.texture.mainTexture = textureList[i] as Texture;

            //设置角色卡片排序命名
            role.name = maxDepth.ToString();
            if (i > 0)
            {
                //奇数设置为右边,下标为正数
                if (i % 2 == 1)
                {
                    maxDepth--;
                    role.name = maxDepth.ToString();
                }
                //偶数设置为左边,下标为负数
                else
                {
                    role.name = "-" + maxDepth.ToString();
                }
            }

            SetDepthAndPosition(item,0,0);
            _roleList.Add(item);
        }        
    }


    private void SetDepthAndPosition(RoleItem role,int dir,int index)
    {
        int indexDepth = 0;
        //左右移动后,重新排序命名
        if (dir != 0)
        {
            if (index*dir > _half )
                indexDepth = -dir * (_half - 1);
            else
                indexDepth = index > -1 && index < 1 ? dir : index;
            role.name = indexDepth.ToString();  
        }        
        else
        {
            indexDepth = int.Parse(role.name);
        }

        TweenPosition tp = role.GetComponent<TweenPosition>();
        int x = indexDepth < 0 ? -(_half + indexDepth) * _movX : (_half - indexDepth) * _movX;
        indexDepth = System.Math.Abs(indexDepth);
        tp.to = new Vector3(x, (_half - indexDepth) * _movY, (_half - indexDepth) * _movZ);


        role.bg.depth = count * indexDepth;
        role.active.depth = 1 + count * indexDepth;
        role.texture.depth = 2 + count * indexDepth;      

        role.GetComponent<UIToggle>().value = indexDepth == _half ? true:false;
        tp.PlayForward();
    }

    /// <summary>
    /// 左边
    /// </summary>
    public void LeftClick()
    {
        //重新排列顺序
        foreach (RoleItem role in _roleList)
        {
            int index = int.Parse(role.name);
            print(index);
            SetDepthAndPosition(role,1,++index);
        } 
    }

    /// <summary>
    /// 右边
    /// </summary>
    public void RightClick()
    {
        //重新排列顺序
        foreach (RoleItem role in _roleList)
        {
            int index = int.Parse(role.name);
            SetDepthAndPosition(role,-1,--index);
        }
    }

    /// <summary>
    /// 鼠标选中某个角色
    /// </summary>
    public void RoleToggleChange()
    { 
        if(UIToggle.current.value)
        {
            int index = int.Parse(UIToggle.current.name);
            int moveCount = _half - System.Math.Abs(index);//移动个数
            for (int i = 0; i < moveCount;i++ )
            {
                if (index > 0)
                    LeftClick();
                else
                    RightClick();
            }           
        }
    }

}



FR:海涛高软(hunk Xu)

2016-04-03 14:07:32 zzlyym 阅读数 5511

        我是初学者,在一家公司岗前培训,然后教了我七天的入门知识,然后和我说:“我觉得你基础比较好,接下来不教你了,自己琢磨自学吧。”然后一万个草泥马奔腾而过。然后度娘背后的大神们在指导我。现在我认识unity软件两周了,觉得挺有趣,决定创建个博客来记下我所认识的小知识点,我写的是我能实现的,如果大神觉得有错误,有更多方法,欢迎批斗。

        我自学的时候看到网上说的方法很多,就是不知道怎么去用,还要一直百度百度百度,所以我写详细点。

 1:打开unity软件,GameObject ~ 3D Object ~ cube,看着game视图,把cube拉伸到摄像机的整个屏幕。


2:拖一张图片到项目中,点击图片,属性里Texture类型,Wrap Mode改成Repeat.


3:右键创建Material球,shader我改的是Unlit/Transparent,属性里右边选择步骤2中的图片。


4:拖着材质球到你第一步创建好的Cube中,结果如图。图片如果是反的,在图中标记处旋转180°.


5:选中Cube,然后Window ~ Animation ~ Add Property 然后 随便起个名字,如下图,点右边的+号。左边出现下边第二张图的样子。页面右边能点红线,调整你想要多长时间循环一次,把他的Materal_main Tex_ST.z变为1,下边第三张图的样子,意思就是一秒循环往左循环一次。以后有相关知识或方法,我会及时更新。



2013-07-02 23:26:57 u011285268 阅读数 5753

真是抱歉,从今天起才认真的翻阅android game example 这个插件,开始熟悉一下外国佬的一些编程方式,相信很多人没有看过我就当做一个记录吧,都是一些简单的小东西。

首先就是这个滚动的背景图,也许叫“跑马灯”会比较好理解。

来看看效果:


看起来这博客系统还不那么差,至少可以播放gif。


这种滚动背景很容易让我想到的就是,跑酷类游戏,空战游戏,总之类似的横版游戏,当然了现在的游戏设计都变得很精致了,相信这样级别的背景还不能满足吧~


这个例子我们不借助任何第三方的精灵插件,都用原始的控件来,我们需要准备的就是一个cube,当然plane也可以。


现在新建一个场景,准备一个正交相机,一个plane,一个灯光,一个material,一张图片,现在调整好位置当该就变成了这样:





好吧现在我们让background上的贴图滚动(事实上这就1分钟的事儿,打成字居然这么麻烦,真是是该考虑制作视屏了),注意到这个了么:



试着变化一下offset的x的值,哇~图片变化了,好吧其实没有什么神奇的~

接着我们就让它自动变化便是了 

加上我们的滚动脚本:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using UnityEngine;
using System.Collections;
         
public class ScrollingByOffset : MonoBehaviour
{
    /// <summary>
    /// 滚动速度
    /// </summary>
    public float _Speed;
    /// <summary>
    /// 滚动的材质载体
    /// </summary>
    private Material _ScrollMaterial;
         
    void Start()
    {
        this._ScrollMaterial = renderer.material;
    }
         
    void Update()
    {
        this._ScrollMaterial.mainTextureOffset = new Vector2(_Speed * Time.time, 0);
    }
}

跑起来瞅瞅,似乎还不错。

接着调整一下灯光,图片的大小(图片最好大到超出相机的视野,效果会好很多)。


接着我把资源和代码贴上来,各位有兴趣可以试试。

http://www.kuaipan.cn/file/id_12421281643248523.htm

2019-12-11 17:02:28 qq_36102944 阅读数 256

Unity3D 制作游戏机循环滚动效果


最近需要在unity中制作一个2D的游戏滚动效果,全网百度了几遍也没有找到什么资料,于是现在我弄了一个出来分享给大家。我把模板做成了预制体,大家可以直接拿去使用然后解除与预制体的关联就行,里面随便放了一点图片做效果用的。这是运行时的效果
工程上传到了CSDN上可以搜索下载到。

没有更多推荐了,返回首页