Unity3d游戏开发之主场景视差效果开发心得

来源:互联网 发布:中国 国防人工智能 编辑:程序博客网 时间:2024/04/29 03:32
效果图

分析
    什么是视差滚动?度娘的解释:让多层背景以不同的速度移动,形成立体的运动效果。从效果图可以看出,主场景背景大致分为3层,草地、山河还有云彩,每一层的速度都不一样。接着分析,虽然度娘的解释是以速度来阐述,但用速度来计算并不合适,因为主层(即草地层)的滚动是跟随我们手指的移动,所以应该把速度转换为位移来计算。既然用位移来计算,每一层的位移不同,怎么样才能把多个层同步起来,我使用了归一化方法,把整个场景的滚动看作是0~1之间的归一化位移,每个层的滚动只需乘以各自层的最大位移。有了归一化位移来实现视差滚动,接下来就是让场景的滚动跟随手指移动,现在其实很好实现,只需要根据手指移动的距离(X方向)和主层的最大位移计算。最后要分析的就是惯性,在手指离开屏幕后场景仍将滚动一段时间,其实就是一个减速运动。(终于分析完了,人家不会分析,憋到现在已经内伤了
 

实现
第一步,实现SetPosition()方法,通过这个方法设置归一化位置,然后将所有层移动到正确位置。
  1. public Transform[] Layers;//每个层的Transform。
  2.      public float[] Offsets;//对应每个层的最大位移。
  3.      int count;
  4.      float location;//定义归一化位置。
  5.      void Start ()
  6.      {
  7.                count = Layers.Length;
  8.      }
  9. public void SetPosition(float position)
  10.      {
  11.                location = Mathf.Clamp01(position);
  12.                for (int i = 0; i < count; i++)
  13.                {
  14.                         Layers[i].localPosition = new Vector3(Offsets[i] * location ,0, 0);
  15.                }
  16.      }
复制代码
  

    当location0时显示各个层最左边的内容,为1时显示各个层最右边的内容。将各个层的根节点赋给Layers属性。如下图所示:


整体效果如下:


    然后将层往左边移动直到显示最右边的内容,这个时候根节点的X坐标就是我们要的最大位移,将这个值赋给对应的Offsets(这个值为负数)。
第二步,实现手指跟随的滚动。
  1. bool dragged;
  2. float lastTouch;
  3. float dragOffset;
  4. float touchToPos;
  5. void Start ()
  6. {
  7.           count = Layers.Length;

  8.           dragged = false;
  9.           touchToPos = 1f / Screen.width * camera.orthographicSize * 2f * camera.aspect / Mathf.Abs(Offsets[0]);
  10. }
  11. void Update ()
  12. {
  13.           if (Input.GetMouseButtonDown(0))
  14.           {
  15.                    dragged = true;
  16.                    lastTouch = Input.mousePosition.x;
  17.           }
  18.           if (Input.GetMouseButtonUp(0))
  19.           {
  20.                    dragged = false;
  21.           }
  22.           if (dragged)
  23.           {
  24.                    float currTouch = Input.mousePosition.x;
  25.                    dragOffset = lastTouch - currTouch;
  26.                    lastTouch = currTouch;
  27.                    dragOffset *= touchToPos;
  28.                    location += dragOffset;
  29.                    SetPosition(location);
  30.           }
  31. }
复制代码
 
    这段代码就是计算每次手指移动时,场景归一化位置改变量——dragOffset,并将该量与当前location相加后使用SetPosition来更新各个层。
第三步,实现惯性。

  1. bool tweened;
  2. float tweenTime;
  3. const float MaxTweenTime = 0.5f;
  4. void Start ()
  5. {
  6.           count = Layers.Length;
  7.           dragged = false;
  8.           tweened = false;
  9.           touchToPos = 1f / Screen.width * camera.orthographicSize * 2f * camera.aspect / Mathf.Abs(Offsets[0]);
  10. }
  11. void Update ()
  12. {
  13.           if (Input.GetMouseButtonDown(0))
  14.           {
  15.                    dragged = true;
  16.                    tweened = false;
  17.                    lastTouch = Input.mousePosition.x;
  18.           }
  19.           if (Input.GetMouseButtonUp(0))
  20.           {
  21.                    dragged = false;
  22.                    tweened = true;
  23.                    tweenTime = 0f;
  24.           }
  25.           if (dragged)
  26.           {
  27.                    ……
  28.           } else if (tweened)
  29.           {
  30.                    tweenTime += Time.deltaTime;
  31.                    if (tweenTime > MaxTweenTime)
  32.                    {
  33.                             tweened = false;
  34.                    } else
  35.                    {
  36.                             float offset = dragOffset * (1 - tweenTime / MaxTweenTime);
  37.                             location += offset;
  38.                             SetPosition(location);
  39.                    }
  40.           }
  41. }
复制代码


    这里利用到第二步中所计算的dragOffset,将最后一次计算(即手指离开屏幕前)得出的dragOffset在最大惯性时间MaxTweenTime内减为0并累加到location上,以达到减速运动的效果,而且移动的距离和手指移动的速度相关。
终于写完了,还是代码爽 

0 0
原创粉丝点击