一些碎碎念
2024.8.17
之前瞎看书看到这么一个概念,叫做“警惕无知”,其中提到我们应该警惕对自身水平的无知。我觉得很有道理,于是那段时间我开始有意识地去注意我和一些优秀的同龄人之间的差距。然后我就自闭了,因为我发现差距还是挺大的。
不过后面心态倒是稳定了,想了想,自己是从大四开始才转游戏开发的,和优秀的那批人有差距才是正常的事情, 不然这个世界的数值就有点不平衡了。客观地认识自己,知道自己在哪里还有欠缺,然后针对性地设立目标,去进步,就可以了。
然后我建立了这个Blog,主要是对之前的知识做一个记录总结,帮助我巩固技能树,同时也对自己的技术树有更加清晰的认知。也发挥一点“开源精神”,毕竟自己也受益于许多大佬的博客。
大概如此。
2024.9.2
前天抱着好奇心下了最近很火的乙游《恋与深空》,结果一整个周末基本就沉浸其中了。然后我跟朋友感叹:“为什么恋与深空的世界不能真实存在呢?”
说实话我之前也经常会这么感叹,我希望海拉鲁是真的,希望宝可梦的世界是真的,希望我所经历的虚拟世界都真实地存在着。而在感叹的同时我也会产生某种庆幸,庆幸选择了计算机,庆幸选择了游戏开发,庆幸选择了站在离我所盼望的虚 ...
我做的同人-林克的大逆转特辑
这篇文章记录了我所参与制作的游戏新春会节目《林克的大逆转》,只要我还在继续做,这篇文章应该就会一直更新下去。
喜报:2025年了,我还在做林克的大逆转!
2023-2024林克的大逆转2024&特别法庭链接:林克的大逆转2024
链接:林克的大逆转特别法庭
1 加入新春会的原因一开始是在空间看到了任饭新春会的招募海报。
往常这种同人制作活动,我是搭不上什么关系的,虽然很早就对做同人、做动画什么的挺感兴趣,但苦于自己没有什么才艺(画画啊Cos啊等等),也不懂视频制作,因此大部分时间下都只能默默远观。
但这次却不一样,我定睛一看,怎么在招游戏程序啊!我没有多想,马上就扫描了二维码,生怕报名晚了没选上(后来我发现整个新春会制作组就我一个程序XD,然后就是被制作人们狠狠奴役了)。
.onbxwdjbfwgx{zoom:50%;}
因为刚好在游戏行业,专业十分对口,我很快就通过了筛选。加入后我总算知道他们为什么要招募游戏程序。
23年春节的时候,他们做了一个塞尔达版的逆转裁判,当时把视频制作的老师累得半死。于是第二年他们学聪明了,觉得像这种逆转like,可能做成游戏会更省事一点(制作人o ...
我做的游戏
【毕业前的项目基本没有什么记录,所以这篇文章从毕业之后开始写。】
【太好了!我还在一直做游戏qwq】
2023宇宙尽头的酒馆 2023.9
链接:宇宙尽头的酒馆
制作时间:2023.9~2023.10
酒馆是我毕业之后做的第一款游戏,本科的时候沉迷于赛博朋克酒保行动,就一直想做一款酒保like游戏,后面当我决定参加机核9月份的BooomJam的时候,我发现机核群里机组的防门老师发了制作招募,定睛一看居然就是我想做的酒保like,于是我毫不犹豫地加入了。
整个游戏的制作过程非常愉快,身为制作人的防门老师有多次的制作经验,带领我们井然有序地结束了整个游戏的制作,程序组的小伙伴们也非常靠谱,我们各司其职,算得上是稳稳地完成了整个游戏的开发(这也为后面我们又一次合作参与了防门老师下一款游戏的程序制作埋下了伏笔:第二次合作:少女奇旅)。
不过我在这次游戏的制作中负责的程序内容不多,主要是完成了小模块【音乐盒】的开发,主要功能是选择新一天需要轮询播放的音乐、预听音乐、查看音乐专辑的一些信息。
虽然工作比较简单,但我还是很享受的,这是我做游戏以来第一次游戏团队里拥有这么强大的美术和音乐阵容,也是第 ...
C++笔记
分类参考《C++ primer》第五版。
C++基础1 变量和基本类型1.1 引用在C++中,引用(Reference) 的本质是为对象起的别名,引用并非一个独立的对象。
1.1.1 基础使用123int ival = 1024;int& refVal = ival; int& refVal2; // 报错:引用必须被初始化
1.1.2 注意项
引用必须被初始化
无法获取引用的地址
在 C++ 内存模型中,只有对象和函数拥有可寻址的地址
对引用取地址,得到的结果是它指向的原始变量的地址
内存占用
逻辑上,引用只是对象的别名,不占用额外的内存空间
对引用执行sizeof操作,得到的结果是它指向的原始变量的大小
物理上
当引用作为局部变量时,编译器会将其直接优化掉,所有对引用的操作,都会被优化为对它指向的原始变量的地址的操作,因此没有额外的内存开销
当引用不作为局部变量,它在编译器内部通常被存储为类似常量指针的形式,当定义int &r = i;,编译器内部会将其存储为int* const p = &i;,因此占用一个指针大小的内 ...
图论
0 前言参考视频
1 图的存储1.1 邻接矩阵.mbsexbnnlgbs{zoom:80%;}
代码实现
1int matrix[n][m];
优点
容易判断两个顶点间是否有边
容易计算顶点的度
1.2 邻接表12345// 定义一个vector数组std::vector<int> adj[n];//如果是带权图std::vector<std::pair<int, int>> adj[n];
1.3 对比degree是度的意思。
存储方案
空间复杂度
判断 i→j 是否有边
遍历所有邻居
适用场景
邻接矩阵
$O(n^2)$
$O(1)$
$O(n)$
顶点数较少、稠密图
邻接表
$O(n + e)$
$O(degree(i))$
$O(degree(i))$
顶点数较多、稀疏图
2 图的遍历2.1 深度优先搜索(DFS)深度优先搜索 (Depth First Search, DFS) 是一种用于遍历或搜索树或图的算法。它的核心思想是“不撞南墙不回头”:从起始节点开始,沿着一条路径尽可能深地探索下去,直到无法继续(到 ...
常用的查找算法
0 前言辅助学习视频:视频地址
1 顺序查找略。
2 二分查找 binarySearch2.1 基础二分查找(Binary Search)是一种在有序数组中查找特定元素的极其高效的算法。
它的核心思想是“折半”:每次通过比较中间元素和目标值,直接排除掉一半的数据范围,从而迅速缩小搜索区间。
时间复杂度为$O(logn)$。
1234567891011121314151617181920212223#include <vector>//前提条件:数组本身是有序的//假设这是一个升序数组int binarySearch(const std::vector<int>& nums,int target){ if(nums.empty()){ return -1; } int left = 0; int right = nums.size()-1; while(left<=right){ int mid = left+(right-left)/2; ...
常用的排序算法
0 前言本文代码部分主要基于C++语言,因为我平时用C#比较多,所以也增加了部分C#知识点。
1 稳定性排序算法的稳定性指的是:对于两个相等的数据,它们的先后顺序在排序结束后依旧保持原样。
2 插入排序 insertionSort2.1 描述它的工作原理很像我们平时打扑克牌时整理手牌的过程:每摸到一张新牌,都会将其插入到左手已经排好序的牌堆中,直至所有的牌都在手里排列整齐。
12345std::array<int,3> temp = {2,3,1};// 假设{}内为已排序部分// 初始 {2},3,1// 一次 {2,3},1// 二次 {1,2,3}
2.2 实现12345678910111213#include <vector>void insertionSort(std::vector<int>& arr) { int n = arr.size(); for (int i = 1; i < n; ++i) & ...
浅析游戏同步技术:帧同步和状态同步
0 前言一年多以前,当我从上一家公司离职时,我对“帧同步”这三个字几乎一无所知,仅有的了解只是八股文里那些冰冷的理论。而加入新公司的这一年多,我几乎一半的时间都在和项目的帧同步框架打交道,因为这段经历,我对帧同步以及其他的同步技术有了更多的理解,以此文章作为记录,仅作学习使用。
一个之前项目主程推荐的帧同步框架:Github地址
1 同步机制同步机制的目标是让所有客户端看到一致的世界状态(渲染一致+数据一致),同步机制主要分两大类:客户端模拟型和服务器权威型,典型的例子就是帧同步和状态同步。
2 帧同步帧同步作为客户端模拟型机制,其核心就是所有的逻辑计算放在客户端,服务器不做任何逻辑处理,只做转发操作。
但商用实现中,服务器也会运行逻辑代码,在纯帧同步中,服务器运行逻辑主要用于哈希校验;在混合变体中,则作为权威仲裁。
2.1 实现帧同步的一般流程是:
每个玩家都会在每固定逻辑Tick里产生输入命令(如移动角色、释放技能等),这些命令通常很小(几字节),客户端会将这些输入命令发送给服务器
服务器收集所有客户端在本次逻辑Tick中的输入,而后广播给所有客户端
所有客户端在同一逻辑Tick ...
UGUI性能优化
减少Draw CallDraw Call
在Unity里,Draw Call指的是CPU发出的绘制请求,其中包含了绘制所需的所有信息,如纹理信息、着色器等,Draw Call太多会增加CPU的消耗,会产生更多的发热和耗电,减少Draw Call就是合并请求(合批),以减少CPU在提交命令上花费太多时间。
Frame Debugger
分析工具我主要使用的是Unity的Frame Debugger(Window-Analysis-Frame Debugger),这个工具可以在游戏运行时冻结特定帧,并查看用于渲染该帧的各个渲染调用的具体情况。在Frame Debugger里,一个渲染调用称为Draw Mesh,通常就是一个Draw Call。
例外情况:当启用GPU Instancing时,多个相同网格的绘制可能合并为一个Draw Call,但在Frame Debugger中可能仍显示为多个”Draw Mesh”。
.akipdfsyznvu{zoom:50%;}
减少Draw Call
减少Draw Call即尽可能地进行合批,UI合批要求UI在同一个Canvas下,并拥有相同的材质(M ...