初始化obs/Unity仓库

This commit is contained in:
2026-05-03 14:06:26 +08:00
commit 0d9e5282f3
95 changed files with 14419 additions and 0 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

@@ -0,0 +1,49 @@
![[Pasted image 20241218120120.png]]
RigidBody组件是Unity引擎内置的物理组件,他的存在可以使得GameObject拥有物理属性.但没有物理形状,形状有Collider控制
从上往下以此讲解该组件的全部属性.
### Mass
物体的质量,不影响下落速度
### Drag和AngularDrag
这两个均为阻力,线性阻力和角阻力
### UseGravity
是否启用重力,启用之后物体收到重力影响
### IsKinematic
是否启用运动学,启用之后物体不受到物理引擎的运动学效果
例如:
1.不会与其他物体产生碰撞反应
2.不会有重力,力,冲量的影响.
但是可以通过脚本来驱动该物体的运行.
### InterPolate
![[Pasted image 20241219223339.png]]
展开后为上图所示
该选项的作用是是否启用插值可以选择提前插值,也可以选择延后插值,
具体效果可以修复游戏在游玩时候的卡顿过程.
注意:有时候游戏在引擎当中游玩不会有卡顿,在Built之后会有卡顿.
### Collision Detection 碰撞检测
![[Pasted image 20241219223512.png]]
一共有4种选择,他们分别是离散检测,持续检测,动态持续检测,推断性检测
#### Discrete (离散检测)
该检测的频率与FixUpdata相同,因此适用于大部分的场合
#### Continuous(连续模式)
==一个动态物体和一个静态物体(没有刚体的碰撞器)之间可以使用==
该模式修复了离散模式在物体速度过快时出现的穿墙现象,优点显著
但是缺点同样显著,其一是系统开销大
缺点之二是该方法是通过撞击时间 (TOI) 算法,通过扫掠对象的前向轨迹来计算对象的潜在碰撞(采用对象的当前速度).因此会忽视物体的角运动,导致物体可能在侧边会出现穿墙现象.
#### Continuous Dynamic(连续动态模式)
类似于Continuous,但是==支持高速移动的物体和其他动态物体的检测==,系统开销最大.
#### Continuous Speculative(连续推测模式)
系统开销介于离散模式和连续模式之间.
同样基于预测,可以防止物体穿墙现象.
可以避免Continuous(连续模式)中忽视角运动侧边穿墙的问题.
具体原理:https://docs.unity.cn/cn/2022.3/Manual/ContinuousCollisionDetection.html
Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

@@ -0,0 +1,128 @@
对于碰撞器而言,基本的碰撞器形状,碰撞器的作用不必多谈,这里着重强调的是碰撞器和触发器,以及他们碰撞和触发的三种状态.
### Enter Stay Exit
以上三种状态表示了物体碰撞刚刚进入的一帧,物体持续碰撞,和物体离开碰撞的一帧
他们分别对应了代码当中的
OnCollisionEnter
OnCollisionStay
OnCollisionExit
以及触发器的
OnTriggerEnter
OnTriggerStay
OnTriggerExit
他们的用法相同,区别在于方法传入的参数不同
碰撞器提供的参数类型是Collision
触发器提供的参数类型是Collider
### 筛选
我们需要在碰撞器和触发器内部进行许多逻辑上的处理,这里有一个关键是如何筛选物体
比如NPC和玩家同时触发开门触发器,我们只希望玩家触发时才会开门,需要进行筛选.
常见的筛选方法有2种: 签名. 层
#### 签名
由于为我们提供了参数,我们可以获取到触发的物体,所以我们可以使用签名进行筛选
譬如:
`if (collision.gameObject.tag==("Player"))`
`{`
`}`
`if (collision.gameObject.CompareTag("Tag"))`
`{`
`}`
二种方式均可,其中第二种方式的效率更高,因为:
Unity将标签单独储存在一个数据结构当中,CompareTag方法可以直接访问该数据结构效率更高.
#### 层
在Unity当中,层被储存为整数,因此使用层进行筛选的效率比Tag高.
层的筛选也需要分为筛选特定的单层,和多层
比如你需要玩家单独可以开门,那么就可以使用单层筛选
但是如过你想要多个物体都可以开门,那么就需要多层
#### 单层检测
![[Pasted image 20241219231058.png]]
#### 多层检测
![[Pasted image 20241219231128.png]]
### **1. 关键概念**
#### **Layer 和 LayerMask**
- **Layer(层)** Unity 中的每个 `GameObject` 都可以设置一个 `Layer`,用于分组、筛选或逻辑处理。每个层的编号是从 `0``31` 的整数。
- **LayerMask(层掩码)** `LayerMask` 是一个 32 位的整型数,每一位(bit)对应一个 Layer。如果某一位是 `1`,则表示该层被包含在掩码中;如果是 `0`,则表示不包含。
例如:
- 如果 `LayerMask` 的值是 `5`(即二进制 `00000000 00000000 00000000 00000101`),表示包含第 0 层和第 2 层。
- 具体映射:
- 第 0 位 = 1 → 包含第 0 层
- 第 1 位 = 0 → 不包含第 1 层
- 第 2 位 = 1 → 包含第 2 层
---
### **2. 拆解逻辑**
#### **(1) `collision.gameObject.layer`**
- 获取发生碰撞的对象的层编号(一个整数,例如 `0``1``2` 等)。
#### **(2) `(1 << collision.gameObject.layer)`**
- **位移操作 `<<`** `1 << x` 表示将 `1` 左移 `x` 位。例如:
- `1 << 0``00000000 00000000 00000000 00000001` (表示第 0 层)
- `1 << 2``00000000 00000000 00000000 00000100` (表示第 2 层)
**结果:** 这个操作生成一个位掩码,只有对应层的位置是 `1`,其余位置是 `0`
#### **(3) `targetLayers | (1 << collision.gameObject.layer)`**
- **按位或操作 `|`**`targetLayers` 和生成的位掩码进行按位或运算。
- 如果 `targetLayers` 中已经包含对应的层(对应位置是 `1`),运算结果不变。
- 如果 `targetLayers` 中不包含对应的层(对应位置是 `0`),运算结果会将该位置变为 `1`
**例子:**
- `targetLayers = 00000000 00000000 00000000 00000101` (包含第 0 层和第 2 层)
- `collision.gameObject.layer = 1`
- `1 << 1 = 00000000 00000000 00000000 00000010` (表示第 1 层)
- 运算结果:`00000000 00000000 00000000 00000111` (包含第 0、1 和 2 层)
#### **(4) 比较:`targetLayers == ...`**
- 比较 `targetLayers` 和运算结果是否相等。
- 如果相等,说明碰撞对象的 `Layer` 已经在 `targetLayers` 中。
- 如果不相等,说明碰撞对象的 `Layer` 不在 `targetLayers` 中。
---
### **3. 具体判断逻辑**
代码的核心逻辑是:
1. 通过 `1 << collision.gameObject.layer` 获取碰撞对象的层对应的位掩码。
2.`targetLayers | ...` 检查碰撞对象的层是否在 `targetLayers` 中。
3. 如果运算结果和 `targetLayers` 相等,说明碰撞对象的层已经被包含。
**简化版本:** `(targetLayers | (1 << collision.gameObject.layer))` 实际上就是在“试探性”地将碰撞对象的层加入 `targetLayers`,然后检查是否变化。如果没有变化,说明碰撞对象的层已经在 `targetLayers` 中。
---
### **4. 更直观的判断方式**
可以使用 `LayerMask` 的内置方法 `LayerMask.Contains`(在较新 Unity 版本中),或者稍微改写代码,提升可读性:
#### 替代写法:
csharp
复制代码
`if (((1 << collision.gameObject.layer) & targetLayers) != 0) { // 进行内部逻辑 }`
#### **逻辑解析:**
- `(1 << collision.gameObject.layer)` 生成碰撞对象层的位掩码。
- `&`(按位与)检测目标层掩码是否包含该层。
- 如果结果不为 `0`,说明目标层掩码包含碰撞对象的层。