自由学习记录(17)
unity核心实践
设置Panel时,用背景图来遮挡后面的组件被点击
字典是存了每个要展示出来的面板的类型引用地址,如果对象本身删了,字典里面的那个匹配数据还会留在那里,字典中的引用仍然会保留,但它们将变得无效。
如果你尝试访问被删除对象的方法或属性,将会抛出异常(通常是 MissingReferenceException
),因为引用的对象已经被销毁。
所以为了避免这种不小心访问到空引用然后报异常的情况,需要我们自己手动管理字典里那些删除了引用原数据的空键和空值
通过一个脚本的名字与游戏物体本身的名字相同,直接可以通过脚本和游戏对象本身绑定起来
transform.setparent()
确保继承basepanel的脚本的名字和在场景中的该面板游戏对象的名字相同
这样Load<GameObject>传入string路径,直接可以通过脚本的类型名(游戏对象上挂载的)
再拼接目录/UI 得到对应的游戏物体
过场景不要移除canvas,UImanager管理的话,把canvas也当预设体创建出来使用
面板类可以继承mono,然后里面增加一个成员事件,需要什么事就往里面加,至于怎么调用时机,则丢给update,性能消耗不大
对于面板的显隐,可以只设置一个bool变量,需要隐藏的时候就改bool值,没必要担心增加死循环的消耗
c++的&
通过检查最低位,能够简单地判断某个数是奇数还是偶数:
- 如果最低位是 1,数为奇数。
- 如果最低位是 0,数为偶数。
对于两个二进制数,&
运算符的规则如下:
- 当两个相应的位都为 1 时,结果位为 1。
- 在其他情况下(即任一位为 0),结果位为 0。
在 C++ 中,&
运算符用于按位与运算,同样适用于整数类型(如 int
、unsigned int
、char
、long
等)。如果对不同类型的整数使用 &
运算符,编译器会根据类型规则进行隐式转换,但必须确保操作数的类型兼容。
#include <iostream>int main() {int a = 5; // 二进制 0101unsigned char b = 3; // 二进制 0011int result = a & b; // result 为 1,二进制 0001std::cout << "Result: " << result << std::endl; // 输出 1return 0;
}
也可以使用 &
运算符对布尔值进行逻辑与运算,但通常推荐使用 &&
运算符进行逻辑与。
&
还被用作引用运算符,用于声明引用变量。
如果尝试对不兼容类型(如 int
和 std::string
)使用 &
运算符,编译器会报错。
将一个数的二进制位向左移动指定的位数,左移后用0填充右侧空位。
- 左移和右移0的结果都为0。
- 位移操作通常用于需要调整数字大小或在某些算法中进行优化,但对于0来说,任何位移操作都不会改变其值。
右移操作中的填充:
- 有符号数:根据符号位(0 或 1)填充左侧空位。
- 无符号数:始终用 0 填充左侧空位。
大部分语言都自带统计二进制数中 1 的数目的库函数
return (n & k) == k ? __builtin_popcount(n ^ k) : -1;
如果 n
中的位与 k
的位进行与运算后,结果等于 k
,则说明 n
中的每一位都可以覆盖 k
中的对应位。换句话说,k
的所有位都在 n
中为1。
^
是按位异或运算符,用于比较 n
和 k
的每一位
__builtin_popcount(x)
是 GCC 和 Clang 提供的一个内置函数,返回整数 x
中二进制表示中 1 的个数。
所以 __builtin_popcount(n ^ k)
返回 n
和 k
之间不同的位的数量,也就是需要变更的位数。
SetLookAtWeight
SetLookAtWeight 是 Unity 中 Animator 组件的一个方法,用于控制角色的“注视”行为,通常与反向运动学(IK)一起使用。
weight: 控制注视的强度。值在 0 到 1 之间,0 表示不进行注视,1 表示完全按照目标的方向注视。
bodyWeight: 控制角色身体朝向目标的权重,通常也是在 0 到 1 之间。这个值决定身体部分对目标的朝向程度。
举例说明
如果你调用 SetLookAtWeight(1, 1, 1)
,意味着:
- 整个角色会完全朝向目标(
weight
为 1)。 - 身体会完全转向目标(
bodyWeight
为 1)。 - 头部会完全转向目标(
headWeight
为 1)。
Animator动画分层
void OnAnimatorIK(int layerIndex) {
// 检查 Animator 是否有效
if (animator) {
// 设置右手的目标位置
if (rightHandTarget) {
animator.SetIKPositionWeight(AvatarIKGoal.RightHand, 1);
animator.SetIKPosition(AvatarIKGoal.RightHand, rightHandTarget.position);
}
// 设置左脚的目标位置
if (leftFootTarget) {
animator.SetIKPositionWeight(AvatarIKGoal.LeftFoot, 1);
animator.SetIKPosition(AvatarIKGoal.LeftFoot, leftFootTarget.position);
}
}
}
在攻击层中,你可以设置权重来调节攻击动画的显示程度,确保在移动时攻击动画能与移动动画兼容。
权重调整:通过设置权重,你可以动态地调整攻击动画在移动时的影响,比如在攻击时降低移动动画的权重,使得攻击动画更加突出。
混合树可以将移动和攻击动画组合在一起。
即使有了子状态机,你仍然可以在主状态机中设置一个“移动与攻击”状态,这样在角色移动时可以选择不同的攻击方式。例如,在“移动”子状态机中,你可以添加一个状态来处理“移动并攻击”的情况。
权重设置相对简单,适合用于基本的动画过渡,但在处理复杂的动画混合时,可能会显得力不从心。
Blend Tree可以是一维或二维的,允许你在多个方向上进行更精细的动画控制。例如,二维Blend Tree可以根据角色的速度和方向同时进行动画混合。Blend Tree支持更复杂的混合模式,可以同时处理多个输入参数,比如前进、后退、左转、右转等。
多个维度上控制动画混合,而不仅仅是通过单一权重来实现。
在Additive模式下,新动画会叠加在当前动画之上,而不是完全替换它。
动画重叠
- Sync还可以用于处理动画重叠情况。例如,当角色正在进行攻击,而又触发了行走动画,Sync可以帮助控制这些动画的开始和结束时间,使其在视觉上协调一致,避免突兀的动画切换。
实践案例
假设你在制作一个角色游戏,角色在行走的同时可以进行攻击。你可以创建两个层:
- 行走层:用于控制角色的行走和跑步动画。
- 攻击层:用于控制角色的攻击动画。
在行走时,攻击层的权重可以设置为0,而当角色进行攻击时,将攻击层的权重设置为1,同时将行走层的权重设置为0,这样角色就会播放攻击动画而不再播放行走动画。
SQL连通集
在关系数据库中,“联系集”通常指的是关系(或表)之间的连接或关联。这些联系可以通过外键(foreign key)来实现,外键是指一个表中的字段引用另一个表的主键。联系集帮助在不同表之间建立逻辑关系,从而允许更复杂的数据查询和管理。
主要概念:
-
关系:关系数据库中的表,包含多行记录和多列字段。
-
外键:一种用于建立和强化两个表之间联系的字段,它在一个表中引用另一个表的主键。
-
一对多关系:一个表中的一行可以与另一个表中的多行相关联。例如,一个作者可以写多本书。
-
多对多关系:需要通过一个中间表来实现的关系,例如学生与课程之间的关系。
-
数据完整性:通过外键约束确保数据的准确性和一致性。
示例:
假设有两个表:
-
Authors(作者表)
- author_id (主键)
- name
-
Books(图书表)
- book_id (主键)
- title
- author_id (外键,引用Authors表的author_id)
在这个例子中,Books表通过author_id与Authors表建立了联系集,表示每本书都与一个作者相关联。
UPDATE Book SET shopNum = shopNum + ROUND(shopNum * 0.50) WHERE bookNo IN ( SELECT bookNo FROM Borrow GROUP BY bookNo HAVING COUNT(*) > 2 );
在这条 SQL 语句中,ROUND(shopNum * 0.50)
是一个数学表达式,用于计算 shopNum
字段值的50%,并将结果四舍五入到最接近的整数。
具体来说:
-
shopNum * 0.50
:这部分计算shopNum
字段值的50%,即将shopNum
乘以0.50(或者除以2)。 -
ROUND()
:这是一个数学函数,用于将数值四舍五入到最接近的整数。如果计算结果的小数部分大于等于0.5,则向上取整;如果小于0.5,则向下取整。
所以,ROUND(shopNum * 0.50)
的作用是将 shopNum
的值增加其自身的50%,并将增加后的结果四舍五入到最接近的整数。
这条 SQL 语句的整体作用是更新 Book
表中的 shopNum
字段,增加每个 shopNum
值的50%,并且这个增加只发生在那些在 Borrow
表中出现次数超过2次的书籍上。这是通过 WHERE
子句中的 IN
条件和子查询实现的,子查询从 Borrow
表中选择出现次数超过2次的书籍编号(bookNo
)。
c++string可调用函数
size_t len = str.size(); // 或者 str.length();
if (str.empty()) { /* ... */ }
str.push_back('a');//char类型
str.pop_back();//移除字符串末尾的字符。
string sub = str.substr(0, 3); // 获取前 3 个字符
size_t pos = str.find("abc");
str.replace(0, 3, "xyz"); // 替换前 3 个字符为 "xyz"
str.append("def");//append(const string& str):
const char* cstr = str.c_str();
function<void(string &)>
:
function
是 C++ 标准库中的一个模板类,可以用来定义可调用对象(比如函数指针、Lambda 表达式等)。<void(string &)>
表示这个函数接受一个string
类型的引用作为参数,并且没有返回值(即返回类型为void
)。
dfs = [&](string& s) { ... };
:
dfs
是一个变量名,用于保存 Lambda 表达式。&
表示这个 Lambda 可以捕获外部作用域中的变量(通过引用)。如果是=
,则是按值捕获。(string& s)
是 Lambda 的参数列表,表示这个 Lambda 接受一个string
类型的引用作为参数。
#include <iostream>
#include <functional>
#include <string>using namespace std;int main() {string text = "Hello, World!";// 定义一个 Lambda 表达式,打印字符串auto printString = [&]() {cout << text << endl;};// 调用 LambdaprintString();return 0;
}
#include <iostream>
#include <string>
#include <functional>using namespace std;int main() {string str = "abc";function<void(string &)> dfs = [&](string& s) {// 输出当前字符串cout << s << endl;for (size_t i = 0; i < s.length(); ++i) {// 递归调用string newStr = s.substr(0, i) + s.substr(i + 1); // 去掉第 i 个字符dfs(newStr); // 继续递归}};dfs(str); // 从完整字符串开始return 0;
}
spine
需要导入Spine库,只需要了解库里的API怎么用就可以了
Spine是一个软件,要做骨骼动画是在这个软件里面做的,需要导出成某个文件之后,再拿去unity里面用
Slots相当于unity的自带的换装分组
spine的代码事件监测
spine的图像转向
spine里的可加特性
spine attachment配合插槽使用,选择插槽里的附件(就是要换的装)
spine slot
sa.skeleton.findbone
设置插槽上的附件(传入了两个字符串,因为加了spineslot特性,spineattachment特性,直接inspector里调)
SkeletonGraphic拖入场景选择UI形式