Bootstrap

自由学习记录(11)

Surface Effector 2D

Platform Effector 2D

向上跳跃穿过天花板的功能

平台效应器不用变Trigger,因为本来就是要有碰撞的

use one way grouping是让所有相关联的碰撞器都可以单面跳墙

默认不勾选,左右两边没有摩擦力和弹力,要自己先设置side arc,表示你要生效的范围

在平台的两侧使用摩擦力和弹力 ,防止卡墙上不走(因为两个碰撞器之间默认有摩擦力),不设置确实可以贴在墙上不走

Point Effector 2D

Distance Scale应用于源和目标之间距离的缩放。在计算此距离时,按该比值对距离进行缩放,因此可以改变有效距离,从而控制施力的大小。

Force Mode有三种,两种吸力的不同算法而已,

constant一直保持一个力

linear就是线性减少,inverse就是曲线指数减少

Buoyancy Effector 2D

Area Effector 2D

恒定力用的比较少

relative force是相对刚体挂载的对象的坐标系加力

torque是旋转力

复合碰撞器

  • 物理材质:不同的物理材质(如摩擦系数和弹性系数)会影响碰撞后的行为。确保物体使用适当的材质可以改善效果。

为了获得更好的碰撞效果,可以:

  • 使用简单的碰撞体来代替复杂的Mesh Collider。
  • 定期检查并调整物理材质的设置。
  • 考虑物体的移动速度,确保不会因运动过快而导致穿透或不自然的碰撞响应。

复合碰撞器 (Composite Collider 2D) 独有的可以生成“空心”效果。具体来说,复合碰撞器配合 Geometry Type 设置为 Outlines,可以让碰撞器只在外边缘起作用,而内部是空的。

在 Unity 中,单独的 BoxCollider2DCircleCollider2DPolygonCollider2D 等通常是实心的,它们没有类似的设置来直接生成“空心”的效果只有复合碰撞器通过组合其他碰撞器(如 BoxCollider2D、PolygonCollider2D)并设置 Geometry Type 才能创建空心的几何结构

实现空心碰撞器的步骤:

  1. 给对象添加多个基础碰撞器,比如 BoxCollider2DPolygonCollider2D
  2. 添加 Composite Collider 2D 组件,Unity 会自动将这些基础碰撞器组合成一个整体。
  3. Composite Collider 2D 中,将 Geometry Type 设置为 Outlines,这样碰撞器只在边缘生效,内部将是空心的

这样就可以模拟出一个空心的物体,其他物体可以在它内部自由移动,只有当它们接触到外边的轮廓时才会发生碰撞。

Trigger

物理材质

所有 2D 碰撞器都可以通过设置 isTrigger 属性来控制它们是作为实心的物理碰撞体,还是仅作为触发器使用。无论是复合碰撞器还是单独的碰撞器组件,这个属性的行为是相同的。

isTrigger 属性

  • 实心碰撞器
    isTriggerfalse 时,碰撞器会作为物理碰撞体处理,物体会在碰撞时产生反弹、阻挡等物理效果。

  • 触发器 (Trigger)
    isTriggertrue 时,碰撞器会变成一个触发器。触发器不会产生物理碰撞效果,物体可以穿过它,但会触发 OnTriggerEnter2DOnTriggerStay2DOnTriggerExit2D 等事件。

在复合碰撞器中的行为

  • 如果你在一个对象上组合了多个碰撞器,比如 BoxCollider2DCircleCollider2D,你可以单独为每个碰撞器设置 isTrigger。这样,某些碰撞器可以作为触发器,而其他的保持实心。

    BoxCollider2D box = gameObject.AddComponent<BoxCollider2D>();

  • CircleCollider2D circle = gameObject.AddComponent<CircleCollider2D>(); box.isTrigger = false; // 实心碰撞器

  • circle.isTrigger = true; // 触发器

  • 复合碰撞器是否支持实心/触发器的混合
    如果你在一个对象上复合多个碰撞器,其中有些碰撞器是实心的,有些是触发器,它们的行为会独立存在。触发器的部分仍然只会触发事件,而实心部分会处理物理碰撞。

碰撞器

碰撞检测函数

trigger也是一样的

2D 碰撞器不仅限于 CircleCollider2DBoxCollider2D。你可以使用多种不同类型的 2D 碰撞器,而且可以将多个碰撞器组件组合在一起,从而创建更复杂的碰撞区域

常见的 2D 碰撞器类型:

  1. CircleCollider2D
    • 一个圆形的 2D 碰撞器,适用于圆形或球状的物体。
  2. BoxCollider2D
    • 一个矩形的 2D 碰撞器,适用于长方形或正方形的物体。
  3. PolygonCollider2D
    • 可以定义任意形状的多边形碰撞器,通过多个顶点连接来形成复杂的轮廓。适用于非规则形状的物体。
  4. EdgeCollider2D
    • 由一系列线段组成的碰撞器,不会包围任何区域,适用于地形或平台边缘。
  5. CapsuleCollider2D
    • 胶囊形的碰撞器,适用于长条状带有圆头的物体,比如角色碰撞体。

复合碰撞器的概念

复合碰撞器是指将多个简单的碰撞器(如 Circle、Box 等)组合在同一个对象上,以模拟一个更复杂的形状。例如,你可以将多个 BoxCollider2DCircleCollider2D 组合在一个物体上来准确包围其形状。

  • 通过添加多个碰撞器组件

    • 你可以在同一个 GameObject 上添加多个不同的碰撞器组件,比如同时添加 BoxCollider2DCircleCollider2D。这样,物体在碰撞时会按照这些碰撞器的组合形状来检测。

    gameObject.AddComponent<BoxCollider2D>(); gameObject.AddComponent<CircleCollider2D>();

  • Rigidbody2D 与复合碰撞器

    • 一个对象上有多个碰撞器时,通常需要配合一个 Rigidbody2D 使用。Rigidbody2D 将这些碰撞器视为一个整体,使它们一起运动和检测

PolygonCollider2D 的使用

PolygonCollider2D 是非常强大的工具,它允许你通过多个顶点来定义复杂的形状,因此在某些情况下,你可能不需要复合多个简单的碰撞器,而可以直接使用一个 PolygonCollider2D 来表示整个复杂形状。

  • 自定义形状: 你可以在 Unity 编辑器中手动调整 PolygonCollider2D 的顶点,或者通过代码动态生成顶点。

    PolygonCollider2D polyCollider = gameObject.GetComponent<PolygonCollider2D>(); polyCollider.SetPath

  • (0, new Vector2[] { new Vector2(0,0), new Vector2(1,0), new Vector2(0,1) });

使用多个碰撞器的优点

  • 更精确的碰撞检测
    对于非规则形状的对象,单一的 BoxCollider2DCircleCollider2D 可能无法精确模拟其边界。通过组合多个碰撞器,你可以更准确地定义物体的形状,减少不必要的物理计算或碰撞失误。

  • 优化性能
    复合多个简单的碰撞器有时比使用一个复杂的 PolygonCollider2D 更高效。虽然 PolygonCollider2D 能创建任意形状,但它的计算复杂度较高。

物体在碰撞之后的位移旋转,是依靠rigidbody

有了刚体只是受力的作用,还没有确定物体的大小和形状

rigidbodyAPI

1. 基础属性

  • velocity (Vector2)
    当前 Rigidbody2D 的速度向量,控制物体在 2D 空间中的移动速度。你可以直接设置它来让物体在某个方向上移动。

    rb.velocity = new Vector2(2, 0); // 设置刚体水平向右移动,速度为 2

  • angularVelocity (float)
    物体的旋转速度(角速度),以度/秒为单位。正值表示顺时针旋转,负值表示逆时针旋转

    rb.angularVelocity = 50f; // 设置刚体以 50 度/秒的速度顺时针旋转

  • mass (float)
    物体的质量,影响碰撞和物体受力的行为。

    rb.mass = 5.0f; // 设置刚体的质量为 5

  • drag (float)
    线性阻力,模拟空气或液体的阻力,减慢物体的移动速度

    rb.drag = 0.5f; // 设置阻力为 0.5

  • angularDrag (float)
    角阻力,减慢物体的旋转速度。

    rb.angularDrag = 0.3f; // 设置角阻力为 0.3

  • gravityScale (float)
    控制刚体受重力影响的强度,默认为 1(受正常重力影响)。设置为 0 时,刚体不受重力影响。

    rb.gravityScale = 0; // 取消重力影响

  • isKinematic (bool)
    如果 isKinematictrue,则刚体不再受物理引擎的控制(不受重力、碰撞等影响),而由脚本控制它的运动

    rb.isKinematic = true; // 将刚体设置为运动学刚体

  • interpolation (RigidbodyInterpolation2D)
    控制刚体在物理帧之间的插值方式。可以选择 NoneInterpolateExtrapolate。这是为了在帧率不稳定的情况下平滑显示物体的运动。

    rb.interpolation = RigidbodyInterpolation2D.Interpolate; // 开启插值

  • collisionDetectionMode (CollisionDetectionMode2D)
    设置刚体的碰撞检测模式,有 Discrete(默认)、Continuous 等模式。连续碰撞检测可减少高速运动物体穿过障碍物的问题。

    rb.collisionDetectionMode = CollisionDetectionMode2D.Continuous; // 使用连续碰撞检测

2. 力和碰撞

  • AddForce(Vector2 force, ForceMode2D mode = ForceMode2D.Force)
    向刚体施加一个力。mode 参数可以是 Force(连续施加力)或 Impulse(瞬间施加力)。

    rb.AddForce(new Vector2(10, 5)); // 向刚体施加一个向右上方的力

  • rb.AddForce(new Vector2(10, 5), ForceMode2D.Impulse); // 瞬间施加一个力

  • AddTorque(float torque, ForceMode2D mode = ForceMode2D.Force)
    向刚体施加一个扭矩(使物体旋转的力)。

    rb.AddTorque(20f); // 施加一个使物体旋转的力

  • MovePosition(Vector2 position)
    手动将刚体移动到一个新位置。如果 isKinematictrue,可以使用此方法直接控制刚体位置。

    rb.MovePosition(new Vector2(3, 5)); // 将刚体移动到 (3, 5) 位置

  • MoveRotation(float angle)
    手动将刚体旋转到一个新的角度(以度为单位)。适用于 isKinematictrue 的刚体。

    rb.MoveRotation(90f); // 将刚体旋转到 90 度

  • IsTouchingLayers(int layerMask)
    检查刚体是否接触某个特定层的物体。

    bool isTouching = rb.IsTouchingLayers(LayerMask.GetMask("Ground")); // 检查是否接触名为 "Ground" 的层

  • Sleep()
    使刚体进入休眠状态,停止它的物理计算。刚体可以通过碰撞或其他事件重新唤醒。

    rb.Sleep(); // 让刚体进入休眠

  • WakeUp()
    唤醒刚体,开始物理计算。

    rb.WakeUp(); // 唤醒刚体

3. 碰撞事件

这些事件是和 Rigidbody2D 物体碰撞时触发的,可以用来处理游戏中的碰撞逻辑。

  • OnCollisionEnter2D(Collision2D collision)
    Rigidbody2D 与另一个物体发生碰撞时触发。

    void OnCollisionEnter2D(Collision2D collision)

  • { Debug.Log("Collided with " + collision.gameObject.name); }

  • OnCollisionExit2D(Collision2D collision)
    Rigidbody2D 与另一个物体停止碰撞时触发

  • OnTriggerEnter2D(Collider2D collider)
    Rigidbody2D 进入触发器(Trigger)区域时触发。

  • OnTriggerExit2D(Collider2D collider)
    Rigidbody2D 离开触发器区域时触发。

4. 常见方法

  • SetRotation(float angle)
    设置刚体的旋转角度。

    rb.SetRotation(45f); // 直接设置刚体旋转到 45 度

  • SetRotation(Quaternion rotation)
    设置刚体的旋转为四元数形式。

  • OverlapPoint(Vector2 point)
    检查刚体的碰撞体是否覆盖某个特定的点

    bool isOverlapping = rb.OverlapPoint(new Vector2(2, 2)); // 检查某个点是否被刚体覆盖

静态刚体和只加碰撞器有什么区别

运动学刚体

simulated有些不同,

额外多了use full kinematic contacts

切换刚体类型

Interpolate 选项解释

Rigidbody2DInterpolate 属性有以下三个选项:

  1. None(默认值):

    • 没有插值,也就是说物体的运动只会在每一帧物理计算后更新。这意味着物体的运动会非常“生硬”,尤其是在帧率波动较大的情况下,物体的运动可能显得不连贯或卡顿。
    • 如果你的游戏物理运算足够快,且帧率稳定,这种方式是性能最高的。
  2. Interpolate

    • Unity 会基于前一帧的物理位置和平滑插值来推测物体当前帧的渲染位置,使物体看起来运动更加平滑。它通过插值的方式,计算出一个基于当前帧时间的中间位置。
    • 适合当物理更新频率较低,或者帧率不稳定的情况。插值会让视觉效果更流畅。
  3. Extrapolate

    • Interpolate 相反,Extrapolate 是通过前一帧的物理位置和速度向外推测出物体的下一帧位置。这意味着 Unity 会根据上一帧的运动状态预估当前帧的位置。
    • 适合物体运动变化较为均匀和帧率稳定的情况。Extrapolate 对于突然发生加速或减速的物体,可能会产生不准确的预测。

使用场景

  • None:当你的游戏物理运算频率和帧率非常稳定时,不需要额外插值,可以使用 None 来获得最佳性能。
  • Interpolate:如果你的游戏场景中,2D 物体的运动偶尔出现轻微卡顿或不平滑,使用 Interpolate 可以有效解决这个问题,特别是在帧率不稳定的情况下。
  • Extrapolate:适用于物体运动较为稳定和线性的情况(比如恒定速度运动的物体),但如果物体运动有频繁的速度变化,Extrapolate 可能会出现误差。

总结

  • None:没有插值,直接使用物理引擎计算的位置更新,性能最高,但可能导致卡顿。
  • Interpolate:通过插值平滑物体运动,适合帧率不稳定的情况。
  • Extrapolate:通过预测平滑物体运动,适合物体运动较为稳定和线性的情况。

物体的碰撞器上有就用碰撞器上的

子物体没材质,父物体的rigidbody的材质会把子物体一起捎上

图集

1. 打包图集后,SpriteRenderer 是否自动更新

  • 不会自动更新:即使你将图片打包成图集,原先代码中通过文件名引用的 Sprite 还是会指向原来的单独图片,而不是图集里的 Sprite。要让 SpriteRenderer 使用图集中的 Sprite,你需要手动更新这些引用。
  • 如果希望图片引用更新到图集,通常需要修改代码或使用 Unity 提供的 Sprite Atlas 系统来管理 Sprite 资源。

2. 图集的好处

  • 性能优化:将图片打包成图集可以减少 Draw Calls(绘制调用),因为 Unity 会将同一个图集中的 Sprite 一次性加载到显存中,减少了渲染过程中的切换成本。如果你的场景中使用了很多不同图片,将它们打包成图集会大大提升渲染效率。

3. 如何让 SpriteRenderer 使用图集

  • 手动调整:打包成图集后,需要将 SpriteRenderer 引用的 Sprite 改为图集中的对应 Sprite。如果手动调整不方便,可以编写脚本动态加载图集并更新引用。

4. 动态打包图集的注意事项

  • 打包时,Unity 会自动将相同的 Packing Tag 的图片打包进一个图集。如果你之前没有指定 Packing Tag,需要在图集打包时手动设置,确保相关图片被打包到同一个图集中。

总结:

  • 如果你之后将图片打包成图集,引用 SpriteRenderer 的图片不会自动更新到图集中的 Sprite,需要手动或者通过脚本更新引用。
  • 打包成图集有助于性能优化,尤其在减少 Draw Calls 方面,但要确保 SpriteRenderer 使用图集中的资源才能生效。

在 Unity 中,GetComponent<T>() 不会自动创建组件。如果你调用 GetComponent<T>() 时,没有找到目标组件,它会返回 null,而不是自动为你添加一个新组件。

SpriteAtlas需要引用命名空间

  • Read/Write Enabled

    • 如果启用,表示纹理可以在运行时被脚本读取或修改。这会占用更多内存,因此在不需要时关闭。
  • Generate Mip Maps

    • 生成多级纹理(Mip Map),用于在不同距离上显示不同分辨率的纹理,从而提高性能和画质。通常在3D场景中使用。
  • sRGB

    • 如果启用,表示纹理将按照 sRGB 色彩空间加载。对于颜色数据(例如 UI 或环境光贴图),sRGB 是合适的选项,而对于法线贴图或其他不涉及颜色的纹理数据,则应禁用
  • Filter Mode (Bilinear)

    • 定义纹理在缩放时如何被过滤。常见模式包括:
      • Point:像素化处理,没有插值,适合像素艺术风格
      • Bilinear:双线性过滤,会对纹理进行平滑处理。
      • Trilinear:在 bilinear 基础上加入多级纹理之间的平滑过渡,适合需要更高质量的场景。
  • Platform-Specific Settings (Default, iOS, Android)

    • 允许你为不同的平台设置不同的纹理参数。每个平台可以有不同的最大纹理尺寸、格式、压缩设置等。这有助于优化不同平台上的性能和内存占用。
  • Format (Automatic)

    • 纹理的存储格式,通常你可以将其设置为 "Automatic",让 Unity 为目标平台自动选择最佳格式。可以手动选择特定格式,如 RGB、RGBA 或压缩格式。
  • Compression

    • 纹理压缩质量的设置。选项通常包括:
      • None:不压缩,最高质量但占用内存较大。
      • Low Quality:高压缩,较低质量,适合不重要的纹理。
      • Normal Quality:标准压缩,平衡质量和内存使用。
      • High Quality:较低压缩,较高质量。
  • Use Crunch Compression

    • Crunch 压缩是一种特殊的压缩格式,能大幅减少磁盘空间占用,但加载时间稍长。适合需要减少存储大小的项目。
  • Objects for Packing

    • 这是用于精灵图集(Sprite Atlas)打包的选项。可以将多个精灵添加到列表中,Unity 会将它们打包为一个图集,以减少绘制调用(Draw Calls)并提高性能。
  • Pack Preview

    • 预览打包的效果,查看将如何处理这些纹理。

Java多线程

;