简体   繁体   English

在统一 2D 中在未占用区域实例化预制件的性能问题

[英]Performance issue instantiating prefabs in unoccupied area in unity 2D

I have a grass-prefab that instantiates iteself in one of 8 positions around itself after some time creating a grid of prefabs.我有一个草预制件,它在创建预制件网格一段时间后在其周围的 8 个位置之一中实例化自身。 Currently I check for other grass-prefabs using 8 trigger-colliders per prefab.目前,我使用每个预制件 8 个触发器对撞机检查其他草预制件。 See screenshot below:请看下面的截图:

在此处输入图片说明

The problem is that unity slows down after instantiating only a bunch of them.问题是在仅实例化其中的一堆之后,unity 会变慢。

I'm open to any suggestions concerning performance improvements.我愿意接受有关性能改进的任何建议。

Here's my code:这是我的代码:

using UnityEngine;
public class GrassController : MonoBehaviour
{
    [SerializeField] private float growthRate = 1.1f;
    [SerializeField] private float maxSize = 1f;
    [SerializeField] private float reproduceEffort = 0.1f;
    [SerializeField] private GameObject prefab;
    [SerializeField] private GameObject sprite;
    [SerializeField] private ReproduceHitBoxController[] reproduceHitBoxes;
    [SerializeField] private float size = 0f;
    private float initialSize = 0.1f;
    private void Awake()
    {
        size = initialSize;
        ApplyGrowth();
    }
    private void FixedUpdate()
    {
        if (size < maxSize) Grow();
        else Reproduce();
    }
    private void Grow()
    {
        size *= growthRate;
        if (size >= maxSize) size = maxSize;
        ApplyGrowth();
    }
    private void ApplyGrowth()
    {
        sprite.transform.localScale = new Vector3(size, size, sprite.transform.position.z);
    }
    private void Reproduce()
    {
        var reproduceHitBox = reproduceHitBoxes[Random.Range(0, reproduceHitBoxes.Length)];
        if (reproduceHitBox.tagInCollider == true) return;
        Instantiate(prefab, reproduceHitBox.transform.position, Quaternion.identity);
        size -= reproduceEffort;
    }
}

Edit : Seems like the main drag on performance are all the physics-checks.编辑:似乎对性能的主要拖累都是物理检查。 Are there ways to check for other gameObjects in a certain area that are more performant?有没有办法检查某个区域中性能更高的其他游戏对象?

在此处输入图片说明

disable the plant rendering component.禁用植物渲染组件。 which are not appearing on the screen.没有出现在屏幕上。

What I'm currently seeing in the profiler.我目前在分析器中看到的内容。

Physics is a very broad term of Unity, that tells you that Nvidia Physx is in use. Physics是 Unity 的一个非常宽泛的术语,它告诉您Nvidia Physx正在使用中。 It is responsible for "Performant*" collision checks, and this is what you are currently seeing.它负责“Performant*”碰撞检查,这就是您目前看到的。

Because on how Physx works, for objects that are "close-by" you are doing basically check "each-with-each" on each FixedUpdate .因为关于 Physx 的工作原理,对于“附近”的对象,您基本上是在每个FixedUpdate上检查“each-with-each”。

There is more information in the profiler on which subsystems of Physix is currently taking 800ms this given frames span.分析器中有更多关于 Physix 子系统当前在此给定帧跨度上占用 800 毫秒的信息。

How to fix this issue如何解决这个问题

Stop using collision, colliders, and triggers for everything that will never be moved by Unity Physics.停止对 Unity Physics 永远不会移动的所有内容使用碰撞、碰撞器和触发器。 Instead use clever data structures to make check for "if the grass is next to the object" without doing check "each-with-each"而是使用巧妙的数据结构来检查“草是否在对象旁边”而不进行“每个与每个”的检查

  1. Keep reference of each grown grass nearby and use list of such objects to check if there is a grass nearby (Tricky to implement but very optimal) NOTE: You should never have more then 8 objects in such list.保留附近每株生长的草的参考,并使用此类对象的列表来检查附近是否有草(实现起来很棘手,但非常理想)注意:此类列表中的对象不应超过 8 个。
  2. Implement a "Grid" based system or so-called Chunks.实现基于“网格”的系统或所谓的块。 Then check for grass in each of the Grid Cells if the given cell is occupied.如果给定的单元格被占用,然后检查每个网格单元格中的草。 This will only work if you have everything in equal distance from each other, but can be adapted to work without this restriction - (this is the most universal solution that you should use, also easiest o implement.)这只有在所有东西彼此距离相等时才有效,但可以在没有此限制的情况下进行调整 - (这是您应该使用的最通用的解决方案,也是最容易实现的。)
  3. Use Quadtree (Octree for 3D).使用四叉树(八叉树用于 3D)。 This will create contant-size nested "Chunks" of increased resolution that will give you O(LogN) performance for checking if something is next to you.这将创建分辨率更高的常量大小嵌套“块”,这将为您提供 O(LogN) 性能以检查您旁边是否有东西。 (This is best for confined space games, that you know have limits on map size). (这最适合密闭空间游戏,您知道地图大小有限制)。 NOTE: This is what Physx uses under the hood, but it's bloated for 3D and Physics movement注意:这是 Physx 在引擎盖下使用的,但它对于 3D 和物理运动来说是臃肿的
  4. BRUTE FORCE METHOD If you know that you will never have more then let's say 1000 grass objects and you know that the "Grow" method will be used less than once per frame, you can have a Controler with a list of all of Grass objects.蛮力方法如果你知道你永远不会有更多的草对象,那么假设 1000 个草对象,并且你知道“生长”方法每帧使用不到一次,你可以拥有一个包含所有草对象列表的控制器。 Iteration over 1000 elements in a list will take 0.01-0.05ish milliseconds depending on the platform.根据平台,对列表中 1000 个元素的迭代将花费 0.01-0.05 毫秒。 So I would say the bearable cost to live with.所以我会说可以承受的生活成本。

Personally, I would go with number 4 for now, and expand to number 2 or 3 when the cost of Grow will generate a lag-spikes for low-end platforms.就我个人而言,我现在会选择第 4 位,当 Grow 的成本会为低端平台产生滞后峰值时,我会扩展到第 2 位或第 3 位。 (3-5ms or more) (3-5ms或更多)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM