【Unity小技巧】在Unity中实现类似书的功能(附git源码)

news2025/1/19 17:18:10

文章目录

  • 前言
  • 本文实现的最终效果
  • 素材
    • 1. 页面素材
    • 2. 卡片内容素材地址
  • 翻页实现
    • 1. 配置我们的canvas参数
    • 2. 添加封面和页码
    • 3. 翻页效果
    • 4. 添加按钮
    • 5. 脚本控制
    • 6. 运行效果
  • 页面内容
    • 1. 添加卡片内容
    • 2. shader控制卡片背面
    • 3. 页面背面显示不同卡片
  • 源码
  • 参考
  • 完结

前言

欢迎来到游戏的书籍之门,一个充满魔力和想象力的世界。在这里,你将体验到一种全新的游戏界面交互方式——翻书。通过Unity引擎的强大功能,我们成功地将书籍的神奇氛围融入到游戏中,为玩家带来了一种崭新、富有艺术感的页面选择方式。

你可以把这个效果用在任何地方,比如关卡选择,商店,故事介绍,物品背包,成就页面等等,这能极大的丰富你的游戏。

无疑,游戏UI交互是极为重要的,对比死板的页面,他能给玩家一种新颖感,让你的游戏在一开始就抓住每个玩家的心!

本文实现的最终效果

在这里插入图片描述

素材

1. 页面素材

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 卡片内容素材地址

https://www.freepik.com/free-vector/hand-drawn-months-year-element-collection_34654526.htm
在这里插入图片描述

翻页实现

1. 配置我们的canvas参数

防止适配不同的设备分辨率,防止页面变形
具体的介绍可以看我上一篇文章:【Unity小技巧】最简单的UI设置适配方案,萌新必看
在这里插入图片描述

2. 添加封面和页码

在这里插入图片描述

3. 翻页效果

翻页的原理就是修改页码y轴进行旋转翻页
在这里插入图片描述
你会发现现在的旋转点不太正确,物体是绕着轴心旋转的,我们只要把轴心移到要旋转的位置即可
在这里插入图片描述

4. 添加按钮

在这里插入图片描述
上一页按钮直接复制下一页按钮参数,把旋转z轴设未-180即可,切忌不要修改错了,如果修改y轴的值,虽然也能实现一样的页面效果,但是你会发现按钮没办法点击了
在这里插入图片描述

层级结构如下
在这里插入图片描述

5. 脚本控制

添加脚本book

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

public class book : MonoBehaviour
{
    // 定义一个序列化字段,表示页面的速度
    [SerializeField] float pageSpeed = 0.5f;
    // 定义一个序列化字段,表示页面的列表
    [SerializeField] List<Transform> pages;
    // 定义一个索引,初始值为-1
    int index = -1;
    // 定义一个布尔值,表示是否旋转,初始值为false
    bool rotate = false;
    // 定义一个序列化字段,表示后退按钮
    [SerializeField] GameObject backButton;
    // 定义一个序列化字段,表示前进按钮
    [SerializeField] GameObject forwardButton;

    private void Start()
    {
        InitialState();
    }

    // 定义InitialState方法,用于初始化状态
    public void InitialState()
    {
        // 遍历页面列表,将每个页面的旋转设置为初始状态
        for (int i=0; i<pages.Count; i++)
        {
            pages[i].transform.rotation=Quaternion.identity;
        }
        // 将第一个页面设置为最后一个子对象
        pages[0].SetAsLastSibling();
        // 将后退按钮设置为不活动状态
        backButton.SetActive(false);

    }

    // 定义RotateForward方法,用于向前旋转页面
    public void RotateForward()
    {
        // 如果正在旋转,则返回
        if (rotate == true) { return; }
        // 索引加1
        index++;
        // 定义一个角度,用于向前旋转页面
        float angle = 180; //为了向前旋转页面,需要将旋转设置为绕y轴旋转180度
        // 调用ForwardButtonActions方法
        ForwardButtonActions();
        // 将当前页面设置为最后一个子对象
        pages[index].SetAsLastSibling();
        // 开始协程,进行旋转
        StartCoroutine(Rotate(angle, true));

    }

    // 定义ForwardButtonActions方法,用于处理前进按钮的行为
    public void ForwardButtonActions()
    {
        // 如果后退按钮不活动,则激活后退按钮
        if (backButton.activeInHierarchy == false)
        {
            backButton.SetActive(true); //每次向前翻页时,应激活后退按钮
        }
        // 如果当前页面是最后一个页面,则关闭前进按钮
        if (index == pages.Count - 1)
        {
            forwardButton.SetActive(false); //如果页面是最后一个,则关闭前进按钮
        }
    }

    // 定义RotateBack方法,用于向后旋转页面
    public void RotateBack()
    {
        // 如果正在旋转,则返回
        if (rotate == true) { return; }
        // 定义一个角度,用于向后旋转页面
        float angle = 0; //为了向后旋转页面,需要将旋转设置为绕y轴旋转0度
        // 将当前页面设置为最后一个子对象
        pages[index].SetAsLastSibling();
        // 调用BackButtonActions方法
        BackButtonActions();
        // 开始协程,进行旋转
        StartCoroutine(Rotate(angle, false));
    }

    // 定义BackButtonActions方法,用于处理后退按钮的行为
    public void BackButtonActions()
    {
        // 如果前进按钮不活动,则激活前进按钮
        if (forwardButton.activeInHierarchy == false)
        {
            forwardButton.SetActive(true); //每次向后翻页时,应激活前进按钮
        }
        // 如果当前页面是第一个页面,则关闭后退按钮
        if (index - 1 == -1)
        {
            backButton.SetActive(false); //如果页面是第一个,则关闭后退按钮
        }
    }

    // 定义一个协程,用于旋转页面
    IEnumerator Rotate(float angle, bool forward)
    {
        float value = 0f;
        while (true)
        {
            // 设置旋转为true
            rotate = true;
            // 定义目标旋转
            Quaternion targetRotation = Quaternion.Euler(0, angle, 0);
            // 增加value的值
            value += Time.deltaTime * pageSpeed;
            // 平滑地旋转页面
            pages[index].rotation = Quaternion.Slerp(pages[index].rotation, targetRotation, value); //平滑地旋转页面
            // 计算给定旋转角度和当前旋转角度之间的角度
            float angle1 = Quaternion.Angle(pages[index].rotation, targetRotation); //计算给定旋转角度和当前旋转角度之间的角度
            // 如果角度小于0.1f,则停止旋转
            if (angle1 < 0.1f)
            {
                // 如果是向后旋转,则索引减1
                if (forward == false)
                {
                    index--;
                }
                // 设置旋转为false
                rotate = false;
                break;

            }
            // 返回null,继续下一次循环
            yield return null;

        }
    }
}

挂载脚本,配置参数
在这里插入图片描述
绑定按钮事件
在这里插入图片描述
在这里插入图片描述

6. 运行效果

在这里插入图片描述

页面内容

1. 添加卡片内容

接下来丰富一下我们的页面,我们可以往页面里添加卡片内容
在这里插入图片描述
运行你会发现,虽然我们翻页了,但是上一页的内容出现在了我们下一页的背面,显然这是不符合逻辑的

2. shader控制卡片背面

我们可以写一个shader把卡片的背面进行隐藏,新建one-side.shader

Shader "Unlit/one-side"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        [Enum(UnityEngine.Rendering.CullMode)] _Cull("Cull", Float)=0
    }
    SubShader
    {
        Tags {"Queue"="Transparent" "RenderType"="Transparent"}
        Lighting Off ZWrite Off
        Cull [_Cull]

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                return col;
            }
            ENDCG
        }
    }
}

新建材质Front,挂载我们的one-side,并配置cull=Back
在这里插入图片描述
给我们所有的卡片挂载材质
在这里插入图片描述
运行效果
在这里插入图片描述

3. 页面背面显示不同卡片

可能你还想在每个页面的背面显示新的卡片内容,这也很简单,只需要新建材质Back,挂载我们的one-side,并配置cull=Front
在这里插入图片描述
页面新增4个内容,挂载我们的Back材质
在这里插入图片描述
运行效果
在这里插入图片描述

源码

https://gitcode.net/unity1/unity-book
在这里插入图片描述

参考

【视频】https://www.youtube.com/watch?v=peJ22VmW7QQ

完结

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,以便我第一时间收到反馈,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

好了,我是向宇,https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,出于兴趣爱好,于是最近才开始自习unity。如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我可能也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/925855.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【两区域系统的自动发电控制】任何区域突然负荷变化的情况下,如何测量两个区域共享的功率研究(Simulink)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

No message found under code ‘-1‘ for locale ‘zh_CN‘.

导出中的报错&#xff1a;No message found under code -1 for locale zh_CN. 报错原因&#xff1a;页面中展示的数据和后端excel中的数据不一致导致 具体原因&#xff1a;

ray-分布式计算框架-集群与异步Job管理

0. ray 简介 ray是开源分布式计算框架&#xff0c;为并行处理提供计算层&#xff0c;用于扩展AI与Python应用程序&#xff0c;是ML工作负载统一工具包 Ray AI Runtime ML应用程序库集 Ray Core 通用分布式计算库 Task -- Ray允许任意Python函数在单独的Python worker上运行&…

矢量调制分析基础

前言 本文介绍VSA 的矢量调制分析和数字调制分析测量能力。某些扫频调谐频谱分析仪也能通过使用另外的数字无线专用软件来提供数字调制分析。然而&#xff0c;VSA 通常在调制格式和解调算法配置等方面提供更大的测量灵活性&#xff0c;并提供更多的数据结果和轨迹轨迹显示。本…

Codeforces Round #894 (Div.3)

文章目录 前言A. Gift Carpet题目&#xff1a;输入&#xff1a;输出&#xff1a;思路&#xff1a;代码&#xff1a; B. Sequence Game题目&#xff1a;输入&#xff1a;输出&#xff1a;思路&#xff1a;代码&#xff1a; C. Flower City Fence题目&#xff1a;输入&#xff1a…

keepalived双机热备 (四十五)

一、概述 Keepalived 是一个基于 VRRP 协议来实现的 LVS 服务高可用方案&#xff0c;可以解决静态路由出现的单点故障问题。 原理 在一个 LVS 服务集群中通常有主服务器&#xff08;MASTER&#xff09;和备份服务器&#xff08;BACKUP&#xff09;两种角色的服务器…

nuxt2-storybook-vite:环境搭建、基础使用 / nuxt项目组件库

一、创建 nuxt2 项目 安装 - NuxtJS | Nuxt.js 中文网 yarn create nuxt-app <项目名> 二、安装 storybook 2.1、初始化 Storybook pnpm add -g storybook/cli npx -p storybook/cli sb init 命令解释 序号命令命令解释1npx -p storybook/cli sb init是一个命令行…

基于JSP+Servlet+mysql员工权限管理系统

基于JSPServletmysql员工权限管理系统 一、系统介绍二、功能展示四、其他系统实现五、获取源码 一、系统介绍 项目类型&#xff1a;Java web项目 项目名称&#xff1a;基于JSPServlet的员工权限管理系统[qxxt] 项目架构&#xff1a;B/S架构 开发语言&#xff1a;Java语言 …

【ag-grid-vue】column

网格中的每一列都使用列定义(ColDef)来定义。列根据在网格选项中指定的列定义的顺序在网格中定位。 列定义 下面的例子展示了一个定义了3列的简单网格: <template><ag-grid-vuestyle"height: 300px; width: 1000px"class"ag-theme-balham":colum…

最新外卖点餐微信小程序源码系统 完整前后端+安装部署教程

分享一个完整的外卖点餐微信小程序源码系统&#xff0c;含完整代码程序包和详细的安装搭建教程。 系统为多用户&#xff0c;可以无限多开&#xff0c;轻松帮助商家开发各种外卖点餐小程序。系统功能特别强大。 小程序源码下载地址&#xff1a;春哥技术博客获取

python SystemRDL 包介绍

对于芯片验证&#xff0c;在验证寄存器环节&#xff0c;如果我们需要根据大量的寄存器来构建我们的sequence或者激励&#xff0c;比如irq测试&#xff0c;我们需要测试irq信号源到寄存器门口的连接是否正常&#xff0c;irq 寄存器各个field的接线排序是否有弄错&#xff0c;以及…

Linux常用命令——dhcpd命令

在线Linux命令查询工具 dhcpd 运行DHCP服务器。 语法 dhcpd [选项] [网络接口]选项 -p <端口> 指定dhcpd监听的端口 -f 作为前台进程运行dhcpd -d 启用调试模式 -q 在启动时不显示版权信息 -t 简单地测试配置文件的语法是否正确的&#xff0c;但不会尝试执行任何网络…

五度易链最新“产业大数据服务解决方案”亮相,打造数据引擎,构建智慧产业!

自2015年布局产业大数据服务行业以来&#xff0c;“五度易链”作为全国产业大数据服务行业先锋企业&#xff0c;以“让数据引领决策&#xff0c;以智慧驾驭未来”为愿景&#xff0c;肩负“打造数据智能引擎&#xff0c;构建智慧产业新生态”的使命&#xff0c;坚持着精益生产、…

地下水资源监控中应用的深水液位传感器

地下水是水资源重要的组成部分,虽属可再生资源,但地下水更新和自净非常缓慢,一旦被污染,所造成的环境与生态破坏,往往长时间难以逆转。目前中国90%的城市地下水遭受污染,已呈现由点向面扩展的趋势。因此,加强对地下水的监控和相应技术的开发成为一种迫切需要。 环境监测是环境…

大数据(一)定义、特性

大数据&#xff08;一&#xff09;定义、特性 本文目录&#xff1a; 一、写在前面的话 二、大数据定义 三、大数据特性 3.1、大数据的大量 (Volume) 特性 3.2、大数据的高速(Velocity)特性 3.3、大数据的多样化 (Variety) 特性 3.4、大数据的价值 (value) 特性 3.5、大…

Linux下套接字TCP实现网络通信

Linux下套接字TCP实现网络通信 文章目录 Linux下套接字TCP实现网络通信1.引言2.具体实现2.1接口介绍1.socket()2.bind()3.listen()4.accept()5.connect() 2.2 服务器端server.hpp2.3服务端server.cc2.4客户端client.cc 1.引言 ​ 套接字(Socket)是计算机网络中实现网络通信的一…

【算法】双指针求解盛最多水的容器

Problem: 11. 盛最多水的容器 文章目录 题目解析算法原理讲解复杂度Code 题目解析 首先我们来解析一下本题 题目中说到&#xff0c;要找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。 那我们现在来看最外侧的两根&#xff0c;一个高度为8&#…

GaussDB数据库SQL系列:DROP TRUNCATE DELETE

目录 一、前言 二、GaussDB的 DROP & TRUNCATE & DELETE 简述 1、命令简述 2、命令比对 三、GaussDB的DROP TABLE命令及示例 1、功能描述 2、语法 3、示例 四、GaussDB的TRUNCATE命令及示例 1、功能描述 2、语法 3、示例 4、示例 五、GaussDB的DELETE命令…

一文速学-让神经网络不再神秘,一天速学神经网络基础-激活函数(二)

前言 思索了很久到底要不要出深度学习内容&#xff0c;毕竟在数学建模专栏里边的机器学习内容还有一大半算法没有更新&#xff0c;很多坑都没有填满&#xff0c;而且现在深度学习的文章和学习课程都十分的多&#xff0c;我考虑了很久决定还是得出神经网络系列文章&#xff0c;…

VSCode配置终端默认为cmd命令行方式

1、新建终端 2、点击默认配置文件 3、选择第一个即可&#xff01;