Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Turkeybag · Oct 10, 2014 at 11:21 AM · performanceoptimizationcolliderspooling

A way to optimize moving a huge group of colliders at once

I'm making a 2D top down game where the player runs around and random segments will spawn so that they are constantly surrounded by a 3x3 group of segments giving the illusion of an endless map. These segments have a box collider and a huge amount of primitive colliders as child objects. (100-300 colliders per segment give or take) and a bunch of sprites. Here is an example of a segment:

alt text

I'm using an object pooling system with a total of 24 segments, 9 being used at a time and the rest off screen (disabling them caused a bigger spike than just moving them). No matter what method I try I can't escape the massive physics.simulate spike. I've considered trying a mesh collider instead of primitives but that would require an enormous amount of work with all the segments I've already made and may not even help. Does anyone know a way to remove or reduce the spike caused by this? Note that I've tried having a kinematic ridgedbody on all colliders, just the parent colliders, and on none of the colliders and it doesn't seem to make much of a difference.

Here's the code that 'generates' the segments:

     IEnumerator GenSegments() {
         //Move all segments outside of the 3x3 box back into the segment pool (objects at y -1000 are in this pool)
         foreach (Transform OtherSeg in UseableSegments)
         {
             if (Vector3.Distance(CurrentSegment.position, OtherSeg.position) > 80 && OtherSeg.position.y > -500)
             {
                 //Move the segment
                 OtherSeg.position = new Vector3(0, -1000, 0);
             }
             //Stagnate the spike to avoid a frameskip
             yield return new WaitForFixedUpdate();
         }
         //CheckPos is used to check for existing segments before moving in a new one
         Vector3 CheckPos = new Vector3 (CurrentSegment.position.x + 50, 25, CurrentSegment.position.z);
         //Checks all 9 spots where a segment can be
         for (int A = 0; A < 8; A++)
         {
             if (!Physics.Raycast (CheckPos, Vector3.down, out SegmentRay, 30f, SegmentLayerMask))
             {
                 //If there is no segment, grab a random one from the pool and move it to the empty spot
                 Transform CurrentSeg = null;
                 int RandomInt = Random.Range(0, 11);
                 while (!CurrentSeg)
                 {
                     if (UseableSegments[RandomInt].position.y < -500) CurrentSeg = UseableSegments[RandomInt];
                     else {
                         RandomInt++;
                         if (RandomInt > 11) RandomInt = 0;
                     }
                 }
                 //Move the segment
                 CurrentSeg.position = new Vector3(CheckPos.x, 0, CheckPos.z);
             }
             //Used to move CheckPos to the next segment spot
             if (A == 1 || A == 2){
                 CheckPos.x -= 50;
             } else if (A == 3 || A == 4){
                 CheckPos.z -= 50;
             } else if (A == 5 || A == 6){
                 CheckPos.x += 50;
             } else if (A == 0){
                 CheckPos.z += 50;
             }
             //Stagnate the spike to avoid a frameskip
             yield return new WaitForFixedUpdate();
         }
     }

I am using 3D colliders as I found that most of the 2D features did not have top down games in mind and that made things difficult. All movement is based on raycasting so there is no actual physics. I would greatly appreciate any help you gives can give.

segmentexample.png (283.9 kB)
Comment
Add comment · Show 5
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image bubzy · Oct 10, 2014 at 11:26 AM 0
Share

you might want to add a collision mask so that the colliders aren't registering collision with other colliders of the same type

http://docs.unity3d.com/$$anonymous$$anual/LayerBasedCollision.html

avatar image Turkeybag · Oct 10, 2014 at 11:32 AM 0
Share

Already got that set up. All those colliders don't register collisions with anything and are only used by raycasts.

avatar image Sisso · Oct 10, 2014 at 12:18 PM 0
Share

2D physic is always a better alternative if you don't use 3d. I don't know where do you get "2D features did not have top down games in $$anonymous$$d".

In general case, the problems are caused by us developers,and not the engine. Using many colliders with move/enable/disable should not cause any problem.

The "foreach (Transform OtherSeg in UseableSegments)" and "while (!CurrentSeg)" are very dangerous code, but you take care and I don't see real problems. I can see some $$anonymous$$or improvements like remove while (!CurrentSeg) with a list of availables, but nothing to solve.

Unfortunatelly I think that you need to profile more. Did you have unity pro to check code/physic spikes? You could use http://wiki.unity3d.com/index.php/Profiler to understand what time take each look.

avatar image Turkeybag · Oct 10, 2014 at 12:40 PM 0
Share

Problem is you have to have the 2D colldiers side on and that made a lot of things like LookAt not work and it also made it just a whole lot more confusing as almost all examples around the web are expecting top down games to be looking from top down. There would probably have been a way to do it but I wasn't really confidant enough to try. Also I originally planed to use navmeshs and they don't work side on.

I've been using the profiler from unity pro to check everything. Here's one of the spikes that occurs when I move the segments: alt text

The GPU spikes are caused by RenderTexture.SetActive so I assume they are to do with me still enabling and disabling my zombies when I return them to the their pool. The CPU Physics.Simulate are the spikes caused by the segments.

spikes.png (111.7 kB)
avatar image smoggach · Oct 10, 2014 at 01:54 PM 0
Share

Sisso I think what he means by "2D features did not have top down games in $$anonymous$$d" is that it's not very obvious how to set up a top down 2d game with what unity gives you. A blank 2D project starts with every object's transform.forward facing the same direction as the camera and gravity is down on the Y axis. This is only useful for sidescrollers really.

While it is the responsibility of the developer I can't help but shame Unity for kind of ignoring the top-down style. Any beginner is going to have a tough time.

2 Replies

· Add your reply
  • Sort: 
avatar image
0

Answer by _dns_ · Oct 10, 2014 at 04:07 PM

Hi, a physics engine uses some optimizations to reduce the number of collisions tests it makes. Those optimizations rely on structures that are fast to do some things, but slow to do some other things. You can read more about this here : http://jitter-physics.com/wordpress/?tag=sweep-and-prune.

In your case, I believe when you move a segment, the physics internal structs must be updated for lots of colliders in the same frame so it causes a spike. Enabeling + disabeling colliders usually causes the same structure update. You can read Unity's blog about physics in Unity 5.0 here: http://blogs.unity3d.com/2014/07/08/high-performance-physics-in-unity-5/ it explains some of this stuff. Hopefully, Unity 5 could fix your problem, you may be able to ask for a beta to check if it does, and then maybe you can live with the spikes until 5.0 is released.

Another way to fix this would be to reduce the number of active colliders. Your map has some kind of islands of those colliders, maybe you can regroup each island under a bigger sphere that would be a trigger (this sphere object would have childs containing colliders). When your player enters that trigger, it enables all the childs colliders it contains (and disable them when exiting). This way, you would force the physics system to update its internal structs very often, but only with a limited amount of colliders and this should not "spike". Also, as all the colliders from other segments would be disabled (except the few triggers), I think the spike of moving them should disappear. This is the same kind of "divide & conquer" thing physics engine broadphase does, but made specific to your game.

This solution may not work if you have lots of other objects that must raycast on those spheres, like enemies. They would also have to trigger enabeling/disabeling lots of colliders and this could lead to other spikes. If this is the case, I would switch to the 2D colliders system as it is faster (I'm sure you can write an editor script that could "convert" all your 3D objects in 2D).

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Turkeybag · Oct 11, 2014 at 02:38 AM 0
Share

Thank you for your links! Unity 5 looks promising. There are up to 100 zombies spawned at a time so all the colliders would always be active, that is a very cool idea that I may use in the future though :D

I've decided that the combination of a huge amount of colliders, needing to move them, and needing a large number of AI to navigate them all at once is a terrible idea for android. It was my own inexperience that lead to this but I have learned a lot from it and that's what counts! A good resigned of the gameplay shouldn't be too hard with all I've learned along the way.

avatar image
0

Answer by drudiverse · Oct 10, 2014 at 05:06 PM

When you are moving, you will have to move 1 object every frame or 2, so put a yield wait for fixed update line or wait for seconds in the loop that finds what to move. actually, find what to move, and every time the loop finds a moveable, add 1 to a var called moveable delay, multiply the process time that actually moves the object by that incremental number, so you can run teh compare move loop in 1 frame but actually move teh objects in 100 frames say.

so you never move more than 1 object ever 0.02 seconds for example.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Turkeybag · Oct 11, 2014 at 02:33 AM 0
Share

I've done this with a the segments themselves but the sheer amount of colliders would take a fair amount of time to move using yield and the player would reach them before they got moved. I could probably try doing it on groups of colliders though but that would cause constant low FPS rather than a lag spike. I'll give it a go though!

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

7 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

enemy pooling 1 Answer

How do I get my game to run faster? 4 Answers

Merging together all GameObjects of an Array? 1 Answer

Windows Phone performance 0 Answers

Sprite Alpha Performance 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges