Unity中实现翻书效果——Book Page Curl Pro插件

1,097 阅读3分钟

一:效果演示


二:介绍

——插件下的Scripts文件夹下有四个脚本
BookPro脚本是挂载到BookPro预制体上的,最最重要
Auto Flip脚本是实现自动翻页或者按钮翻页的扩展脚本
PageFlipper和Tween由上面两个脚本调用


——每个Paper列表都包含两页,前页与后页,可以通过Paper列表进行添加页面

——Papers列表:存储所有页面的列表
——Flipping Range:可以限制可以翻页的范围,例如第一页是最后一页不可翻页
——Current Paper:当前的页数(第一页下标为0,最后一页下标为最后一页的下标+1)
——Update Pages Order:根据Current Paper数值重置页面顺序
——Update Pages Names:将所有的UI页面的按照页码排序重命名
——点击加号去添加页面,减号去移除页面,拖动页面可以任意交换层级
——若要修改某个页面,点击Show之后在Scene面板中选中进行修改
——每个页面都相当一个UI元素,默认有Image组件和Mask组件,不要删除Image和Mask组件,它负责将所有页面的内容保存在页面中
——可以在每个页面元素下添加任何UI元素
——场景中书的左侧为后页,右侧为前页


——在翻页时执行某些方法

可以在OnFlip回调中添加翻页时执行的函数

——拖动翻页的区域

LeftHotSpot和RightHotSpot分别为左右页面拖动翻页的区域


——添加Auto Flip脚本实现自动翻页

——ControledBook:控制的挂载了BookPro脚本的游戏物体
——Mode:翻页的方向,从左向右翻还是从右向左翻
——Page Flip Time:翻页动画的时间,类似与DoTween的第二个参数
——Delay Before Start:第一次翻页的延迟时间
——Time Between Pages:两次翻页的时间间隔
——Auto Start Flip:是否开启自动翻页,可以取消自动翻页之后在需要的地方通过代码调用StartFlipping方法
——Auto Flip脚本启用后会将BookPro的interactable设置为false


——添加Auto Flip脚本实现点击按钮进行翻页(Auto Start Flip必须勾掉)

按下按钮时调用Auto Flip脚本中的FlipRightPage和FlipLeftPage方法


三:实现步骤

——下载插件并导入Unity工程:download.csdn.net/download/LL…
(我将插件源码进行了小修改,方便动态添加页面)


——新建一个Canvas和EventSystem,将Book-Page Curl Pro—Prefabs下的BookPro预制体拖到Canvas下


——自定义了一个按下A键动态添加照片到相册的功能(插件中的Paper是数组类型,不方便动态添加,我将插件中的Paper类型修改为了List)

using System;
using UnityEngine;
using UnityEngine.UI;

public class DynamicAddPaper : MonoBehaviour
{
    public BookPro _bookPro;//BookPro的对象

    [Header("初始页为第几页")]
    public int pageIndex;//第几页(从0开始)
    [Header("是否显示第一页")]
    public bool showTheFirstPage;//是否显示第一页

    public Sprite sprites;//动态添加的图片

    private void Awake()
    {
        UpdateFlipRange();
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {
            if (pageIndex / 2 >= _bookPro.papers.Count)
            {
                AddPaper();
                SetPaper(sprites);
            }
            else
            {
                SetPaper(sprites);
            }
        }
    }

    /// <summary>
    /// 设置页面显示
    /// </summary>
    /// <param name="img">当前页面的图片</param>
    private void SetPaper(Sprite img)
    {
        if (pageIndex % 2 == 0)
        {
            _bookPro.papers[pageIndex / 2].Front.GetComponent<Image>().sprite = img;
        }
        else if (pageIndex % 2 == 1)
        {
            _bookPro.papers[pageIndex / 2].Back.GetComponent<Image>().sprite = img;
        }
        pageIndex++;
    }

    /// <summary>
    /// 添加页
    /// </summary>
    private void AddPaper()
    {
        //创建新的Paper对象
        //创建Paper对象中的前页与后页并设置属性
        Paper paperItem = new Paper();
        GameObject frontPaper = _bookPro.transform.GetChild(0).gameObject;
        GameObject backPaper = _bookPro.transform.GetChild(1).gameObject;
        frontPaper = Instantiate(frontPaper, _bookPro.transform);
        backPaper = Instantiate(backPaper, _bookPro.transform);
        frontPaper.name = String.Format("Page{0}", pageIndex);
        backPaper.name = String.Format("Page{0}", pageIndex + 1);
        frontPaper.GetComponent<Image>().sprite = null;
        backPaper.GetComponent<Image>().sprite = null;

        //添加一个新的页并赋值前页和后页
        _bookPro.papers.Add(paperItem);
        _bookPro.papers[_bookPro.papers.Count - 1].Front = frontPaper;
        _bookPro.papers[_bookPro.papers.Count - 1].Back = backPaper;
        //=====需要手动设置一下可翻页的范围并更新
        UpdateFlipRange();
    }

    /// <summary>
    /// 更新翻页的范围
    /// </summary>
    private void UpdateFlipRange()
    {
        if (showTheFirstPage)
        {
            _bookPro.StartFlippingPaper = 0;
        }
        else
        {
            _bookPro.StartFlippingPaper = 1;
        }
        _bookPro.EndFlippingPaper = _bookPro.papers.Count;
        _bookPro.UpdatePages();
    }
}

四:性能优化

此插件的默认设置在移动端会消耗大量的Drawcall
官方文档给了两种方案:
——如果你的书没有透明页面,就把Has Transparent Pages勾掉


——如果你的书中包含很多UI元素,建议把书放在单独的画布下,因为更新画布下的任何UI元素都会使整个画布完全更新。