当前位置:   article > 正文

Unity中SpriteRender实现广告牌效果_unity再游戏世界里显示的广告牌

unity再游戏世界里显示的广告牌

通过刷新修改SpriteRender组建来实现一个翻广告牌的效果,一般的资源原图最好是能两张或更多,实现起来就能类似广告牌那样展现,或者只有一张也可以单独作为一个显示图片的动画来用:
首先是游戏场景中对象的节点层次,这里的fatherObj分别为每张广告牌的父节点,有多少个广告牌就有多少个父节点,父节点的SpriteRender要直接引用图片资源,我以一张广告牌垂直分割为四张为例,如图为图片分割的效果示意图:
图片分割结果展示

需要做的:场景中的节点如图
游戏对象节点层次

SpriteRender中引用到的广告牌格式:
SpriteRender的原资源图分割

本文只贴一下比较关键的代码,既然翻广告牌的对象节点要求已经挫成这样了,代码结构也要继续挫下去,有点搞复杂了。我单独加了个类来存这样的结构:

public class AdCardItem
{
   //对应途中的广告牌节点fatherObj
   public GameObject father; 
   //存放广告牌碎片,对于fahterObj这个而言,需要把childObj1-childObj4都村进来,SubCardItem结构后面详写。
   public List<SubCardItem> cardSubList = new List<SubCardItem>(); 
   //维护多张图的时候才需要,其实单张图距用不到这个了,文本中暂不使用
   public int order =0; 
   //多此一举了,其实是fatherObj的SpriteRender组件
   public SpriteRender fatherRender;
   public AdCardItem(GameObject father, List<SubCardItem> cardSubList,int order,SpriteRender fathRender)
   {
        this.father = father;
        this.cardSubList = cardSubList;
        this.order = order;
        this.fathRender = fathRender;
   }
}

//存储广告牌子块的结构
public class SubCardItem
{
    public SpriteRender spriteRender;
    /*这个字典其实是用来做缓存优化的,把广告牌的每张小图在不同比例时的显示都缓存了,其实也不会太多。即所有的广告牌翻过一次之后,所有的小碎片都能被缓存到,避免每次用小碎片都直接实例化的尴尬*/
    public Dictionary<int,Sprite> sprDic; 
    
    //实例化的时候只需要传入碎片对象引用的SpriteRender组件
    public SubCardItem(SpriteRender spriteRender1)
    {
        this.spriteRender = spriteRender1;
        sprDic = new Dictionary<int,Sprite>();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

接下来简单的写一行实例化的代码,以一张广告牌的为例:

public class AdCardUpdate:MonoBehaviour
{
   List<AdCardItem> adCardList;
   //暂定只有2张广告牌,对象示意图中的命名为场景的对象摆放分别为fatherObj0,fatherObj1
   int CARD_COUNT = 2;
   GameObject fathObj;//广告牌父节点
   //假定大广告牌的总宽度为100
   float SUB_WIDE = 100/4;
   //此算法水平分割,因此所有子块和大图的显示高度一致,假定图片高100
   float SUB_HEIGHT =50;

   void Start()
   {
       adCardList = new List<AdCardItem>();
       int subCount =4;//为碎片个数,此处的把广告牌分成了四块
       for(int index = 0; index < CARD_COUNT; index ++)
       {
           List<SubCardItem> subList = new List<SubCardItem>();
           for(int subIndex=0;subIndex<subCount;subIndex++)
           {
              string path = "fatherObj/"+"childObj"+(index+1).ToString();
              if(GameObject.Find(path)!=null)
              {
                  subList.Add(new
SubCardItem(GameObject.Find(path).GetComponent<SpriteRender>));
                  Transform father = GameObject.Find("fatherObj"+index); 
                  if(father!=null)                  
                  {
                     adCardList.Add(new AdCardItem(father.gameObject,
                     subList,0,father.gameObject.GetComponet<SpriteRender>()));
                  }
              }
           }
       }
   }

    //描述填充的百分比(%100后使用,当showRate=100表示碎片全部显示)
    int showRate = 0; 
    int fullRate=100;
    int forehandIndex
    {
       get
       {
          int temp  = (bgIndex-1)<0?
          (adCardList.Count-1):(bgIndex-1));
          return temp<=0?0:temp;
       }
       set{}
    }
    int bgIndex=0;

    void Update()
    {
       showRate++;
       UpdateCard(forehandIndx,shoRate);
       
       if(showRate>fullRate)
       { 
          showRate =0;
          //该翻下一张广告牌了
          bgIndex++;
          if(bgIndex>=adCardList.Count)
          {
              bgIndex=0;
          }
          //完全翻牌子了
          ResetLayer();
       }
       
    }
    
    ///以下是刷新某张广告牌的详细实现
    ///其中,adIndex为adCardList中前景图的索引(慢慢消失的那张广告牌),后面的(bgIndex位置)慢慢全部显示出来
    void UpdateCard(int adIndex,float scale,bool needReturn=false)
    {
       if(needRetunr) //希望传入scale=0,即前景图全不显示直接隐藏该广告牌父节点
       {
          adCardList[adIndex].father.SetActive(false);
          return;
       }
       Rect fathRect =adCardList[adIndex].fathRender.sprite.textureRect;
       Texture2D texture2D = adCardList[adIndex].fatherRender.sprite.texture;
       float leftX = fathRect.x;
       float topY = fathRect.y;
       flot curWide = SUB_WIDE*scale*0.01f;//实际显示的碎片宽度
       int scaleIndex=(int)scale;
       for(int index=0;index<adCardList[adIndex].cardSubList.Count;index++)
       {
           SpriteRender render = adCardList[adIndex].cardSubList[index].spriteRender;
           //尚未缓存的
           if(!adCardList[adIndex].cardSubList[index].sprDic.ContainsKey(scaleInt))
           {
              //最关键的两行
              Rect rect = new Rect(index*SUB_WIDE+leftX,topY,curWide,SUB_HEIGHT);
              render.sprite=Sprite.Create(texture2D,rect,Vector2.zero);
              adCardList[adIndex].cardSubList[index].sprDic.Add(scaleInt,render.sprite);
           }
           else
           {
              render.sprite =adCardList[adIndex].cardSubList[index].sprDic[scaleInt];
           }
       }

       ///每次翻了新的广告牌,重置层次
       void ResetLayer()
       {
          adCardListp[bgIndex].father.SetActive(true);
          adCardListp[bgIndex].father.transform.localPosition=
          new Vector3(0,0,-0.1);
          
          adCardListp[forehandIndex].father.SetActive(true);
          adCardListp[forehandIndex].father.transform.localPosition=
          new Vector3(0,0,-0.12); //被翻的牌子forehandIndex放到前面
     
          //前后图片都按100%比例填充
          UpdateCard(forehandIndex,fullRate);
          UpdateCard(bIndex,fullRate);
       }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120

其实,这个实现只是一个思路,纯手打,不能保证不报错,部分空对象报错的保护代码没有加上,实际运行中某些对报错的时候还是需要额外加限制保护的

最后附上一张2个fatherObj(即只有两个广告牌,就是后面的广告慢慢显示出来,前面的慢慢完全消失:
单张广告牌gif动画

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号