Unity性能优化——Rigidbody2D详解
在移动或旋转⼀个物体时,往往会直接使⽤Transform来执⾏这些操作。⽐如使⽤如下代码来移动⼀个GameObject:
void Update(){
}
这种⽅法对于不具物理特性的GameObject来说,是可⾏的。但是⼀旦GameObject上附带有Rigidbody2D,这种⽅式就会带来性能的损失。
Rigidbody2D
先看看Rigidbody2D,先引⽤官⽅⽂档对Rigidbody2D⼯作原理的说明:
How a Rigidbody 2D works
Usually, the Unity Editor’s Transform component defines how a GameObject (and its child GameObject
s) is
青春正能量我是女神
positioned, rotated and scaled within the Scene. When it is changed, it updates other components, which may update things like where they render or where colliders are positioned. The 2D physics engine is able to move colliders and make them interact with each other, so a method is required for the physics engine to communicate this movement of colliders back to the Transform components. This movement and connection with colliders is what a Rigidbody 2D component is for.
The Rigidbody 2D component overrides the Transform and updates it to a position/rotation defined by the Rigidbody 2D. Note that while you can still override the Rigidbody 2D by modifying the Transform component yourlf (becau Unity expos all properties on all components), doing so will cau problems such as GameObjects passing through or into each other, and unpredictable movement.
Any Collider 2D component added to the same GameObject or child GameObject is implicitly attached to that
Rigidbody 2D. When a Collider 2D is attached to the Rigidbody 2D, it moves with it. A Collider 2D should never be moved directly using the Transform or any collider offt; the Rigidbody 2D should b
e moved instead. This offers the best performance and ensures correct collision detection. Collider 2Ds attached to the same Rigidbody 2D won’t collide with each other. This means you can create a t of colliders that act effectively as a single compound collider, all moving and rotating in sync with the Rigidbody 2D.
When designing a Scene, you are free to u a default Rigidbody 2D and start attaching colliders. The colliders allow any other colliders attached to different Rigidbody 2Ds to collide with each other.
Tip
Adding a Rigidbody 2D allows a sprite to move in a physically convincing way by applying forces from the scripting API. When the appropriate collider component is also attached to the sprite GameObject, it is affected by collisions with other moving GameObjects. Using physics simplifies many common gameplay mechanics and allows for realistic behavior with minimal coding.
重点已经⽤粗体标出来了。为英⽂不好的朋友⼤致翻译⼀下:
所有被附加在同⼀个具有Rigidbody2D组件的GameObject、以及其⼦GameObject上的Collider2D,都会被隐式地附加到该
Rigidbody2D上。当Collider2D被附加到Rigidbody2D上后,它将随着Rigidbody2D移动。⼀个Collider2D不应该直接使⽤Transform 或者其offt属性来移动它,⽽是应该使⽤Rigidbody2D的移动代替之。这样会得到最好的表现和正确的碰撞检测。被附加在同⼀个Rigidbody2D的Collider2D之间不会发⽣碰撞。所以我们可以创建⼀个包含多个Collider2D的复合Collider2D,这样所有的Collider2D的移动、旋转都将与Rigidbody2D的运动同步。
那么针对之前使⽤Transform移动的⽅式,我们应该改为如下⽅式:
void FixedUpdate()
钻石证书查询{
rigidbody2D.MovePosition (rigidbody2D.position + Vector2.left * speed * Time.fixedDeltaTime);
}
或者如下⽅式:
void Start (){
rigidbody2D.velocity = Vector2.left * speed;
}
注意前⼀种⽅式每⼀物理帧设置⼀次Rigidbody2D的位置,看起来Rigidbody2D在以⼀定速度移动,但实际上它的velocity依旧是零。
后⼀种⽅式则不存在上⾯的问题,设置好velocity后,物理系统会⾃动对它进⾏模拟,代码看起来也更简洁。
再看看Rigidbody2D的Body Type属性:
它有三个可选项:Dynamic(动态,默认)、Kinematic(运动学)、Static(静态)。
这三种类型确定了不同的运动⾏为(移动和旋转)和碰撞⽅式。
注意虽然Rigidbody2D描述了与其他物体碰撞,但是如果没有附加Collider2D组件,它仍然是不能检测到碰撞的。
关于Body Type,这个属性不要在运⾏时去修改它。原因还是引⽤官⽅⽂档的说明:和女生聊天话题
Changing the Body Type of a Rigidbody 2D can be a tricky process. When a Body Type changes, various mass-related internal properties are recalculated immediately, and all existing contacts for the Collider 2Ds attached to the
Rigidbody 2D need to be re-evaluated during the GameObject’s next FixedUpdate. Depending on how many contacts and Collider 2Ds are attached to the body, changing the Body Type can cau variations in performance.
粗体部分是重点,意思就是运⾏时去改变此属性会引起不同的表现。具体什么表现,就是前⾯说的会⽴即引发⼀系列的重计算,这会是性能的额外开销。
再看看三种不同的Body Type究竟确定了哪些不同的运动⾏为和碰撞⽅式。
Body Type —— Dynamic
A Dynamic Rigidbody 2D is designed to move under simulation. It has the full t of properties available to it such as
finite mass and drag, and is affected by gravity and forces. A Dynamic body will collide with every other body type, and is the most interactive of body types. This is the default body type for a Rigidbody 2D, becau it is the most common body type for things that need to move. It’s also the most performance-expensive body type, becau of its dynamic nature and interactivity with everything around it. All Rigidbody 2D properties are available with this body type.
Do not u the Transform component to t the position or rotation of a Dynamic Rigidbody 2D. The simulation repositions a Dynamic Rigidbody 2D according to its velocity; you can change this directly via forces applied to it by scripts, or indirectly via collisions and gravity.
Dynamic Rigidbody2D被设计⽤来制作在物理模拟下会移动的物体。它会与所有类型的Rigidbody2D进⾏碰撞,是最常⽤的
Rigidbody2D类型、默认的类型,同时也是最耗费性能的类型。
⽂档中粗体部分的意思就是千万不要使⽤Transform组件来设置Dynamic Rigidbody2D的position和rotation。
前车可鉴如果想要移动或旋转它,可以使⽤上⾯提到的⽅式,通过Rigidbody2D的接⼝来完成。
Body Type —— Kinematic
A Kinematic Rigidbody 2D is designed to move under simulation, but only under very explicit ur control. While a
Dynamic Rigidbody 2D is affected by gravity and forces, a Kinematic Rigidbody 2D isn’t. For this reason, it is fast and has a lower demand on system resources than a Dynamic Rigidbody 2D. Kinematic Rigidbody 2D is designed to be repositioned explicitly via Rigidbody2D.MovePosition or Rigidbody2D.MoveRotation. U physics queries to detect collisions, and scripts to decide where and how the Rigidbody 2D should move.
A Kinematic Rigidbody 2D does still move via its velocity, but the velocity is not affected by forces or gravity. A
Kinematic Rigidbody 2D does not collide with other Kinematic Rigidbody 2Ds or with Static Rigidbody 2Ds; it only collides with Dynamic Rigidbody 2Ds. Similar to a Static Rigidbody 2D (e below), a Kinematic Rigidbody 2D behaves like an immovable object (as if it has infinite mass) during collisions. Mass-related properties are not available with this Body Type.
Kinematic Rigidbody2D被设计⽤来制作在物理模拟下会移动、但是仅仅在明确的⽤户控制下运动的物体,它不会受到重⼒和AddForce、AddTorque等⼒相关的函数的影响。
⽂档中粗体部分的意思是Kinematic Rigidbody2D对系统资源的要求⽐Dynamic Rigidbody2D更低(所以更有效率)。Kinematic Rigidbody2D被设计⽤来通过Rigidbody2D.MovePosition或Rigidbody2D.MoveRotation来进⾏重定位。
对于Kinematic Rigidbody2D,velocity属性对它依旧有效,只不过施加⼒和重⼒都不会对velocity造成影响。
Kinematic Rigidbody2D仅仅只会与Dynamic的Rigidbody2D发⽣碰撞(在不勾选U Full Kinematic Contacts的情况下),它在碰撞⾏为上类似于Static Rigidbody2D,可以理解为具有⽆限质量、⽆法被撼动(不能通过⼒或碰撞改变速度,但是可以设置其速度和位置、旋转)的刚体。
Body Type —— Static
A Static Rigidbody 2D is designed to not move under simulation at all; if anything collides with it, a Static Rigidbody 2D
behaves like an immovable object (as though it has infinite mass). It is also the least resource-intensi
ve body type to u. A Static body only collides with Dynamic Rigidbody 2Ds. Having two Static Rigidbody 2Ds collide is not supported, since they are not designed to move.
Only a very limited t of properties are available for this Body Type.
Static Rigidbody2D被设计⽤来制作在物理模拟下不会移动的物体。它在表现上可以理解为⼀个具有⽆限质量、不可移动的物体。此时velocity、AddForce、gravity、MovePosition、MoveRotation都是不可⽤的。
⽂档中粗体部分意思是Static Rigidbody2D对资源最不敏感(对性能要求低),Static Rigidbody2D仅仅会与Dynamic Rigidbody2D发⽣碰撞。两个Static Rigidbody2D之间也不会发⽣碰撞,因为他们本来就被设计成不可移动的。
Rigidbody2D属性
Simulated(模拟)
U the Simulated property to stop (unchecked) and start (checked) a Rigidbody 2D and any attached Collider 2Ds and Joint 2Ds from interacting with the 2D physics simulation. Changing this property is much more memory and
processor-efficient than enabling or disabling individual Collider 2D and Joint 2D components.
该属性就是字⾯意思,设置为true(勾选)时开启模拟;设置为fal(不勾选)时关闭模拟。
模拟包括:
运动
Collider2D的碰撞鱼的主要特征
Joint2D的约束效果
是否驻留在内存
粗体部分的意思是更改此属性在内存和处理上,都⽐直接启⽤/禁⽤Collider2D组件和Joint2D组件更有效率。要知道原理的话,可以查看官⽅⽂档,这⾥就不再作详细解释了。
U Full Kinematic Contacts
炸乳扇
如果想要Kinematic Rigidbody2D与所有类型的Rigidbody2D发⽣碰撞,可以勾选此选项。勾选上后,它在碰撞上类似于Dynamic Rigidbody2D,但是不会受到⼒的影响。
当此属性被设置为fal(不勾选)时,该Kinematic Rigidbody2D只会与Dynamic Rigidbody2D发⽣碰撞;它不会与其他的Kinematic Rigidbody2D或Static Rigidbody2D(设置为trigger时除外)发⽣碰撞。所以此时脚本上的碰撞检测函数
(OnCollisionEnter2D,OnCollisionStay2D,OnCollisionExit2D)不会被触发。
所以⼀般情况下,如果想要制作⼀个完全由⽤户控制的Rigidbody2D、同时还能接受所有碰撞,就使⽤Kinematic Rigidbody2D并勾选U Full Kinematic Contacts选项。
总结
1、在操作附加了Rigidbody2D的物体时,不要直接通过操作Transform来移动、旋转它。
2、要接受碰撞的Rigidbody2D必须添加Collider2D组件。
3、如果⼀个Rigidbody2D需要移动,但不接受⼒的作⽤,那么需要将它设置成Kinematic;如果它附加了Collider2D组件,在Rigidbody 的U Full Kinematic Contacts属性为fal(不勾选)时,它只会与Dynamic的Rigidbody2D碰撞,⽽不会与Kinematic的或者Static 的Rigidbody2D发⽣碰撞;如果需要它能与受所有类型的Rigidbody2D碰撞,那就设置U Full Kinematic Contacts为true(勾选)。
4、如果⼀个Rigidbody2D需要移动,并且接受完全的物理模拟,包括重⼒、碰撞、施加⼒等,那么需要将Rigidbody2D设置成Dynamic,并附加Collider2D组件。
5、如果⼀个Rigidbody2D不需要移动,也不需要接收⼒的作⽤,但是需要接受碰撞,那么需要将Rigidbody2D设置为Static,并附加Collider2D组件。
6、在运⾏中不要修改Rigidbody2D的Body Type属性。
7、在运⾏中,如果想要停⽌/启⽤对⼀个Rigidbody2D进⾏物理模拟,那么将这个Rigidbody2D的Simulate属性设置为fal/true会⽐关闭/打开它的Collider2D、Joint2D组件效率⾼。
公司运动会口号