OpenGL学习记录——入门篇
笔者在网上能找到的C++与OpenGL的教程几乎都是基于Windows+VisualStudio展开的,也因为其直观和简易的环境配置流程,让初学者更专注于学习知识本身。这对作为Mac用户的笔者就很不友好了,需要额外了解CMake的工作原理、要选什么样的编译器等等诸如此类的,都是笔者要去搞清楚的点。
C++基础头文件和CPP文件的区别在(游戏引擎架构)[https://book.douban.com/subject/25815142/]这本书中,介绍了头文件和CPP文件的区别:头文件通常用于在多个翻译单元之间共享信息,例如类型的声明以及函数原型。C++编译器并不了解头文件,实际情况是,C++预处理器预先把每个#include语句替换成相应的头文件内容,然后再把翻译单元送交源一起。这是头文件和源文件之间一个细微但是非常重要的区别。从程序员的角度看,头文件是独立的文件,但多亏了有预处理器把头文件展开,编译器接收到的才都是翻译单元。翻译单元的定义是:因为编译器每次只编译一个C++源文件至机器码,所以在技术上,源文件被称为翻译单元。那么像Mac上用的clang就是编译器的前端,负责预编译和编译的 ...
UnityAndroid平台自适应刷新率设备设置120HZ刷新率无效问题解决记录
国产厂商的对安卓系统的特殊调教⭕️ 安卓层的尝试 遇到了getHolder获取不到surfaceView的问题 原因是什么unity3d.player.I cant cast to surfaceView⭕️ Unity层的尝试 使用SysInfo.Resolutions获取当前设备所有支持的分辨率+刷新率,从中挑选出那个最高分辨率的,然后调用setResolution接口设置上⭕️ 还有一种策略没尝试:如果一个设备支持120HZ刷新率,但是支持多种分辨率下的120HZ刷新率,我最高的分辨率设置上去不生效,那如果设置最低的呢?另外要取消勾选FramePacing,还要把V Sync关掉
解除帧率限制(Android)对一些安卓高刷屏来说,进游戏时屏幕刷新率会被设置成60,这应该和Android系统的策略有关,因此通过Screen.currentResolution.refreshRateRatio接口拿到的屏幕刷新率是不准确的,如果要开启高刷,则需要关闭 ProjectSettings -> Player -> Resolution and Presentation 下的 ...
MacOS与WindowsOpenGL开发环境搭建
本篇博客记录以JoeyDeVries的OpenGL教程为指导在MacOS和Windows系统上搭建OpenGL的过程和疑惑。在参考的OpenGL教程中使用的开发平台是Windows系统上的VisualStudio,但是Mac系统上的VisualStudio不能进行C++开发,为了在Mac和Windows上保持相同的开发体验,我决定在MacOS和Windows上统一使用VSCode + CMake + Ninja + Clang的开发方案。
前置知识OpenGL是什么?OpenGL十分类似面向对象编程思想中的接口和虚方法,它只是定义了一个框架,而没有任何具体的实现。所有的实现需要显卡生产厂商自己实现。可以说OpenGL是一套规范。
GLFW和GLADGLFW是一个专门针对OpenGL的C语言库,它提供了一些渲染物体所需的最低限度的接口。它允许用户创建OpenGL上下文、定义窗口参数以及处理用户输入。
因为OpenGL只是一个标准/规范,具体的实现是由驱动开发商针对特定显卡实现的。由于OpenGL驱动版本众多,它大多数函数的位置都无法在编译时确定下来,需要在运行时查询。所以任务就落在了开发 ...
关于依赖注入
起因是,笔者在调研如何实现一套高效的UI换皮框架的时候,接触到了依赖注入的概念。所谓UI换皮,就是在UI的交互和显示文本内容信息等功能模块不变的情况下,仅仅是需要做美术资源的替换或者动画的修改。在笔者过往的开发过程中,UI的交互模块和动效模块并没有分割。那么就导致了一个问题:当项目进入一个大量美术风格测试的阶段时,比如,有十套美术风格要上线测试,按照之前的方案,笔者就要复制十分类似的预制体,然后为这十套预制体各自编写一套控制脚本,很麻烦的一点是,页面中的按钮、文本信息都是一样的,而我需要在十份不同的脚本中编写十次,并且,当其中某一个按钮的点击功能或者文本的内容发生改变时,我就要去改十份脚本中的内容,维护成本实在是太高了,因此笔者希望找到一种解决方案,能够将UI中的功能模块与动效模块隔离开,只需要编写一次功能模块,表现模块由于动画实现方式等原因必定是要定制的。 由此,笔者了解到了Zenject或许可以解决我们的问题。我们的问题在于,在不同的页面中,按钮、文本等交互组件的节点是无法保证的,每一种美术风格如何向UI的交互模块的代码中传入正确的Button或Text组件呢?这就是我们的问题
依 ...
游戏精细化迭代中美术风格管理框架
框架整理框架职责
新增一套美术风格
删除一套美术风格
新增某一美术风格一类动效
删除某一美术风格的某一类动效
新增某一美术风格某一类动效的新风格
删除某一美术风格的某类动效的某一个风格
新增某一美术风格下的宝石块的风格
删除某一美术风格下的宝石块的某一风格
新增一套运行时美术风格切换策略(美术风格承接策略)
删除一套运行时美术风格切换策略(美术风格承接策略)
新增某一美术风格下某一页面上的交互/表现组件
删除某一美术风格下某一页面上的交互/表现组件实验字段分类风格管理框架是对以下六类实验的管理和组织:
美术风格实验字段,有些字段是单纯的控制美术风格的(美术风格实验字段), 应该要保证这些实验字段中只有一个是生效的(做保底和冲突检查) (约束管理初始美术风格的实验字段)
美术风格策略实验,某些实验字段天生会带一些逻辑(素材承接实验字段),在运行时会切换美术风格, 在风格管理框架中将这类实验字段映射为一套策略, 也许Session内会有多个可以生效的美术风格切换策略,只会有一个字段真正生效,所以要做保底和冲突检查 (约束Session内更新美术风格的实验字段)
特定风格特定动效实验 ...
UnityAssetBundle笔记
AssetBundle基础AssetBundle原理⭕️ AssetBundle在内存中如何加载、存储
AssetBundle、AssetBundle-Browser与AddressableAssetBundle是Unity推出的一种内置的资源压缩格式,能够允许开发者在运行时动态加载需要的资源。用不用取决于开发者自己。当你在Unity中创建、导入任何非代码资源或者文件夹的时候,在Inspector窗口的下面都会有一个AssetLabel:
Addressable是基于AssetBundle的一套完整的Unity资源管理框架,也就是说,如果我们使用Addressable进行开发,项目中的资源如何进行打包、加载Addressable都帮我们规划好了,我们只需要按照它给定的规范和接口使用资源就可以了。但是如果我们只是使用AssetBundle,那么我们还需要开发一套自己的资源管理框架。
另外,Unity还推出了AssetBundle-Browser用来可视化AssetBundle的构建过程。应该说Unity是先推出了AssetBundleBrowser然后推出了Addressable。二者都 ...
UnityAndroid工程包体优化
包体构成使用AndroidStudio中的Build -> ApkAnalyzer来对包体内容进行分析,可以看到安卓包内的基本结构如下:
Resources目录下的文件都会被打包进assets/bin/Data/data.unity3d文件中,游戏启动的时候会一次性把这个文件加载到内存中,因此应该要尽可能地减小放在resources目录下的文件体积。
libil2cpp.so内容分析https://blog.csdn.net/linxinfa/article/details/116572369
AssetRipper使用AssetRipper的GitHub链接👉👉👉 https://github.com/AssetRipper/AssetRipper
下载到本地解压后在根目录打开终端,运行./AssetRipper.GUI.Free在浏览器中启动。
UnityResources目录下的内容都被打包进了一个unity_3d的目录下,
AssetBundle打包问题资源冗余如果两个ab A和B中的一些资源都依赖了一个没有被指定要打包的资源C,那么C就会同时被打进ab A和B中, ...
RPG游戏开发记录(三):Player模型与动画
状态机Unity的Animator系统本质上也是一个状态机,笔者认为在此引入状态机有利于功能的实现。在表现上,人物会跑、跳、飞等动作,而与之对应的是与这些动作相关的数据发生了变化,注意这里面的先后关系:先是由于数据发生了变化,然后才导致了表现上角色动画行为的变化。秉承着上述数据驱动表现的原则,我们类比Animator状态机,为我们的数据层也建立一个状态机。其实任何逻辑你都可以去用状态机进行组织,只要你能够抽象出几种互斥的状态,然后在每种状态内部去实现该状态下的所有逻辑。我们先来看一下状态机的基本写法。
状态机可以被分成两部分,第一部分是状态,第二部分是管理这些状态的部分。这两个部分的具体表现都是类,上面我们说要在
本节将我们控制的Player由圆柱体替换成有人形骨骼的模型
模型Unity中的动画系统实现一个可以静止、移动切换的动画状态
静止状态下随机播放动画
要写一个状态机设计一个主角的状态机
主角有Idle、Move、Jump等状态
1sm.AddState(StateEnum, StateClass(Host, Animation ....))
类似上面的状态注册,将Animato ...
3D数学基础-多个坐标空间
本篇博客是笔者结合《UnityShader入门精要》和《3D数学基础——图形和游戏开发》两本书对Shader所需要的数学知识的整理。
在《3D数学基础——图形和游戏开发》第三章中,作者介绍了坐标空间的知识,第三章中有三个很有意思的知识点:直立空间、变换坐标空间的两种视角:绝对视角和局部视角、从矢量的角度进行坐标变换
书中对世界空间的描述笔者在此有必要提及:The world coordinate system is a special coordinate system that establishes the “global” reference frame for all other coordinate system to be specified. In other words, we can express the position of other coordinate spaces in terms of the world coordinate space, but we cannot express the world coordinate space in term ...
RPG游戏开发记录(二):相机控制
基本思想巫师3中的相机是锁头的,如果Player的头和摄像机之间有遮挡就会位移相机的运动可以被拆分成相机跟随、水平转向、俯仰(竖直)转向三个分运动。因此,在笔者设计的相机跟随的方案中,相机组件会被设计成一个具有三层嵌套关系的结构——最外层负责跟随角色移动、中间层负责相机水平方向上的转向、最内层负责相机竖直方向的转向。
用到的接口
Transform.InverseTransformDirection(Vector3 direction);传入一个世界空间坐标下表示的三维向量,得到这个transform对象空间坐标下该向量的表示
Transform.TransformDirection(Vector3 direction);传入一个在该transform坐标空间下表示的三维向量,得到这个向量在世界空间坐标下的表示
Transform.RotateAround(Vector3 point, Vector3 axis, float angle);使一个物体绕着穿过某一点的某一个方向的轴旋转angle角度,在左手坐标系中,顺时针为正向旋转。
Vector3.SmoothDamp(Vector3 ...