- 博客(26)
- 收藏
- 关注
原创 Unity Avater
一致性是重定向的基石:保证所有动画资源使用同一个、正确的参考姿势进行解码,是避免混乱的前提。模型Avatar与动画Avatar应各司其职:前者负责“翻译应用”,后者负责“提供解码基准”,二者不必相同。标准化流程提升效率:通过建立一个“中央标准化Avatar”,开发者无需再逐一检查、修正每一个外来动画的参考姿势,实现了动画资源引入流程的标准化和自动化。
2026-03-11 13:26:56
414
原创 端口、套接字与多路分解/复用
端口本质:一个16位的逻辑数字(范围0-65535)。作用:在一台主机内,唯一标识一个正在进行网络通信的应用程序进程。它是运输层协议(TCP/UDP)的寻址地址。分类知名端口:0-1023,固定分配给HTTP、FTP等系统服务。注册/用户端口:1024-49151,用于用户应用程序。动态/临时端口:49152-65535,通常由客户端临时使用。套接字本质:操作系统提供的网络通信端点,是应用层与运输层之间的编程接口。作用:是通信连接的抽象句柄,进程通过它发送和接收数据。唯一标识UDP套接字。
2026-03-07 15:10:12
402
原创 Unity序列化
序列化是将内存中复杂的的对象状态转换为可存储或传输(如网络)的线性格式(如YAML,JSON)的过程,必要时能准确地还原回来。在Unity中,这主要意味着将游戏对象、组件和数据保存到磁盘文件(.prefab、.unity、.asset),以便下次加载时能准确还原。通过特性让自定义类/结构体参与Unity序列化系统。明确目的:区分"需要保存的数据"和"运行时临时数据"封装优先:多用代替public字段精简序列化:用标记不需要保存的public字段善用ScriptableObject:管理游戏配置、物品数据等。
2026-03-04 17:27:35
390
原创 协程优化单双击检测
目前我的单双击检测逻辑为:物体检测到点击则调用GameManager对应方法,记录下该物体为。若pendingItem(上一次点击的物体)不为空且未超过限定时间则判定双击事件,超出限定时间则判定单击事件。但是可以看到,每帧都要执行进行检查,即使无操作,而且单击事件有延迟,可能影响用户体验。我们可以使用协程来进行优化。这里是我原本代码逻辑直接转换为协程,避免了Update中检验时间,同时可以灵活的调整是否需要立即响应单击事件。
2026-01-26 20:11:08
213
原创 连击非第一击无伤害
我的标识逻辑基于动画事件,在动画开始的第一帧和结束的最后一帧设置变量。这里发现不是我预期的开始->退出->开始->退出->开始->退出,第一次退出与第二次开始,第二次退出与第三次开始之间相隔时间都接近0.14s,现在将一二段攻击间缩短过渡时间到0.07s。这与我得预期相同,状态开始与结束受到过渡时间的影响,下面我将过渡时间设置为0,应该就能解决只有第一段攻击有伤害的问题。现在我们加上过渡时间测试。发现第一次退出和第二次开始之间相隔时间大约0.07s,第二次退出与第三次开始之间相隔大约0.14s。
2026-01-23 16:34:47
284
原创 AI切换攻击滑步
敌人AI寻路追逐玩家,到面前切换到攻击状态出现滑动着攻击的情况,一般是因为没有彻底清除敌人的路径计算与速度。(还不行就调整动画过渡时间之类的)
2026-01-20 18:49:36
99
原创 OnMove方法输出不平滑
第一个参数表示当前值,第二个参数是目标值,第三个参数是当前速度,一定是类的成员变量(如果是局部变量,每次都会重置,平滑失效),第四个是接近目标值大约所需的时间。但是这个时候又遇到一个问题,如果角色移动时当前的smoothInput和rawInput差距过大会出现角色移动反应迟钝的问题,于是我们可以在角度过大时重置平滑过程,直接使用rawInput。InputSystem中OnMove方法获取的输出只有几个离散的值对应八个方向,这会导致使用混合树时,动画的切换会很僵硬,没有平滑的过渡。
2026-01-20 18:39:00
166
原创 C++:多重继承
MI描述的是有多个直接基类的类。与单继承一样,公有MI表示的也是is-a关系。例如,Worker派生出Singer和Waiter,再从Singer和Waiter派生出SingingWaiter。但多重继承会带来许多问题,最主要的两个便是就上述两个问题,下面根据举例Worker继承给出相关解决方法。
2025-05-26 23:48:58
980
原创 C++:虚函数与纯虚函数
本文介绍了C++中虚函数与多态继承的实现机制。虚函数通过在基类和派生类中声明virtual关键字实现动态绑定,使程序根据对象类型选择相应方法版本。虚函数通过虚函数表实现运行时动态联编,与静态联编的非虚函数形成对比。文章还讨论了纯虚函数与抽象类的概念,指出纯虚函数(如=0声明)强制派生类实现特定接口,抽象类不能实例化。此外,强调了继承关系中应将析构函数设为虚函数以确保正确析构,并提醒派生类重定义虚函数时可能隐藏基类同名方法。这些机制共同支撑了C++面向对象的多态特性。
2025-05-24 18:55:22
808
原创 C++:公有,保护及私有继承
使用保护继承或是私有继承时,如果想要基类的方法在派生类外可用有两种方法。第一种是定义一个使用该基类方法的派生类方法}//使用私有继承方法第二种则是将函数调用包装在另一个函数调用中,即使用using声明来指出派生类可以使用特定的基类成员,即使采用的是基类派生。...public:...上述using语句使得min(),max()函数以及重载运算符[ ]可用。使用using声明时只使用函数名(即不包括圆括号,特征标和返回类型)。
2025-05-12 17:37:43
1111
原创 C++:类的自动转换和强制类型转换
前面可以将数字转换为ST对象,而相反的转换也是可以实现的。这需要使用特殊的C++运算符函数——转换函数。如果定义了从ST到double的转换函数,就可以使用下面的转换。
2025-04-23 15:03:55
775
原创 C++:运算符重载与友元函数
上述加法的重载中,成员函数版本一个操作数通过this指针隐式地传递,另一个操作数作为函数参数显式传递;上面的例子是用成员函数重载运算符,我们可以借助友元函数实现非成员函数重载。通过让函数成为类的友元,可以赋予函数与类的成员函数相同的访问权限。它不属于成员函数,因此不能使用成员运算符来调用,但它的访问权限与成员函数相同。通过上述例子,我们可以使用成员函数或非成员函数来实现运算符重载。函数可以使用不同的参数列表来同时定义多个同名函数以实现函数重载。类似的也可以重载<<,*,-,=等运算符。
2025-04-19 14:44:34
609
原创 C++:类作用域与初始化
在类声明或成员函数定义时,可以使用未被修饰的成员名称。其他情况需根据上下文使用直接成员运算符(.),间接成员运算符(->)或作用域解析运算符(::)。在类中定义的名称的作用域都为整个类。所以不能从外部直接访问类成员,公有函数必须通过对象访问,定义成员函数时也必须使用作用域解析运算符(::)。可以在类声明之外使用单独的语句来进行初始化。从C++11标准开始,C++允许在类声明中直接初始化非静态成员变量,这一特性被称为类成员初始化。类内初始化为类成员设置默认值,若构造函数中显式初始化成员则会覆盖类内初始值。
2025-04-16 21:02:59
615
原创 C++:关于复制构造函数与赋值运算符浅复制导致的问题解释
如果类中包含了使用new初始化的指针成员,应当定义复制构造函数和重载赋值运算符,以复制的数据,而不是让多个对象的指针成员指向同一片空间(被称为浅复制)。浅复制会导致指针指向已被释放的空间,出现悬空指针。复制构造函数用于初始化过程,重载的赋值运算符用于常规赋值语句中。下面举一个实例来做有关说明,该实例声明并定义一个stringbad类(表示有问题的string)。声明中静态类成员不可在声明中初始化(除非使用const限定),静态类成员归属于类,而不属于具体的对象。下面是成员函数定义下面是测试函数。
2025-04-12 17:05:31
767
原创 C++:this指针与对象数组
这时我们发现一个问题,如果调用成员函数的对象是需要被返回的,我们不知道如何称呼它。C++解决这种问题的方案是:使用被称为this的特殊指针,它指向调用成员函数的对象。首先默认使用默认构造函数创建数组元素,然后花括号中的构造函数将创建临时对象并将临时对象的内容复制到相应的元素中。如果我们希望编写一个函数用于比较两个对象成员值的大小,并返回成员值大的那个对象。该函数最右侧的const表示调用成员函数的对象的成员值不允许改变,该函数隐式地访问一个对象,而显式地访问另一个对象,并返回其中一个对象的引用。
2025-04-11 21:06:25
419
原创 C++:构造函数与析构函数
构造函数的函数名应与类名保持一致,且无返回类型。下面声明一个原型//这里使用了默认参数//Stock类对应的构造函数再给出一种可能的定义if(n<0)shares=0;set_tot();不要将类成员名词用作构造函数的参数名,这种行为是未定义的。~Stock();//析构函数原型,名称必须与类名相同,无返回类型也无参数//无new分配内存,不用执行任何操作。
2025-04-10 13:34:50
674
原创 C++学习笔记:对象和类
类声明:以数据成员的方式描述数据部分,以成员函数的方式描述公有接口。类方法定义:描述如何实现类成员函数。将实现细节放在一起并将它们与抽象的公有接口分开被称为封装。根据上述例子,下面先实现一个类声明//refri.h#ifndef N//避免重复包含头文件#define Nprivate://私有属性:门状态//私有属性:存储的食物public://公有方法:定义冰箱的行为接口#endif。
2025-04-09 21:48:46
585
原创 C++学习笔记:名称空间(2)
C++允许通过定义一种新的声明区域来创建命名的名称空间。下面使用namespace关键字创建两个名称空间: 名称空间可以是全局的,也可以在另一个名称空间中,但不能在代码块中。(默认其中声明链接为外部) 除了用户定义的名称空间外,其他不在其中的声明变量都被描述为位于全局名称空间(对应文件级声明区域)。 可将名称加入到已有的名称空间中,对上述例子可有如下操作 开放性意味着名称空间的名称可能分散在多个地方, 这使得难以准确知道添加了哪些名称。
2025-03-25 23:47:08
521
原创 C++学习笔记:名称空间(1)
在C++中,名称可以是变量、函数、结构、枚举、类以及类和结构的成员。当随着项目的增大,名称相互冲突的可能性也将增加。使用多个厂商的类库时,可能导致名称冲突。
2025-03-24 23:29:58
371
原创 C++学习笔记:存储持续性、作用域和链接性
存储持续性描述了变量时如何存储的;作用域描述了名称在文件(翻译单元)的多大范围内可见;链接性描述了名称如何在单元间共享。下面将分别从自动存储持续性,静态存储持续性,动态存储持续性三个方面介绍相关知识。
2025-03-23 11:22:16
1344
原创 C++学习笔记:单独编译
与C相同,C++也鼓励程序员将组件函数放在独立的文件中,然后单独编译这些文件,让后将它们链接成可执行代码。头文件不应包含变量声明和函数定义(内联函数除外)。当同一个程序的多个文件包含同一个头文件时会导致函数或变量被定义两次,这会导致报错。
2025-03-22 17:35:33
308
原创 C++学习笔记:内联函数与默认参数
内联函数是C++为提高程序运行速度所做的一项改进。为了了解内联函数和常规函数的区别,下面介绍相关程序的执行过程。当执行到函数调用指令时,程序将在函数调用后立即存储该指令的内存地址,并将函数参数复制到堆栈,跳到标记函数起点的内存单元,执行函数代码,让后跳回到地址被保存的指令处(类似于阅读文章时停下看注释,看完后再返回之前的地方阅读)。内联函数多用于执行时间短的函数(节省的调用时间占比更大),对于C的宏定义函数在C++中尽量改为内联函数。但使用内联函数时,编译器将使用相应的函数代码代替函数调用(无需跳转)。
2025-03-20 12:00:00
355
原创 C++学习笔记:引用
引用是已知变量的别名,通过将引用变量用作参数,函数将使用原始数据而不是其副本。就像char*是指向char的指针一样,int&是指向int的引用。(a和r指向相同的值和内存单元)必须在声明引用时将其初始化,而不能像指针那样先声明再赋值。2.引用更接近const指针,一旦与某个变量关联起来便有一直效忠于它。
2025-03-19 22:19:18
366
原创 C++:函数重载及函数模板
有时候可以编写合适的函数调用来引导编译器做出你希望的选择。int a,b;a=1;b=2;//下面为函数调用#1#2#1中<>指出编译器应使用模板函数而不是非模板函数。#2中指出编译器应使用显式实例化得到的函数。
2025-03-19 13:40:44
1118
1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅