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
1
Question by Ziron999 · Feb 04, 2015 at 03:21 PM · c#collisionphysicstriggeroptimization

Optimize hundreds of objects

How can i optimize hundreds of objects firing at each other? I've already got box colliders because they are the least memory usage by a long shot. everything is fine until i add this part:

 void OnTriggerStay(Collider other)
     {
         if (other.tag == "Enemy" )
         {
             if (inTrigger && Time.time > lastFireTime)
             {
                 lastFireTime = Time.time + delayTime;
                 Fire(other.transform);
             }
         }
         else
             Physics.IgnoreCollision(collider, other.collider);
     }
 void Fire(Transform currentTarget)
     {
         GameObject shot = Instantiate(bullet, transform.position, Quaternion.identity) as GameObject;
         shot.GetComponent<BulletPhysics>().target = currentTarget;
         Destroy((shot.gameObject), 2);
     }

basically i think the slowdown is coming from the way i'm doing my delay is there a better way? The profiler states 80k calls is being done in stay in a matter of seconds

Comment
Add comment · Show 3
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 AlucardJay · Feb 04, 2015 at 04:25 PM 0
Share

Duplicate post : http://forum.unity3d.com/threads/optimize-hundreds-of-objects.295841/

avatar image Ziron999 · Feb 04, 2015 at 11:32 PM 0
Share

your right it took so long for this to get approved i posted it on forums sorry about that

avatar image AlucardJay · Feb 04, 2015 at 11:47 PM 0
Share

Not a problem. The cross-reference is just a link for people to see what has already been suggested across both posts. If you let people know, then it might save someone giving the same answer you have somewhere else. If you get a solution, be sure to : mark as answered on UA; post how the problem was resolved in the Forums.

2 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by AndresBarrera · Feb 04, 2015 at 03:48 PM

Two things to keep in mind:

  1. Make sure that all your bullets are using only 1 Draw Call. Read about dynamic batching on Unity.

  2. Use Object Pooling. Search a bit about how to implement it, but the basic idea is to keep a Queue of the object you will be "creating" a lot (bullets). Instead of intantiate every single one (instantiate is slow), deactivate objects that you are no longer using and re-use them again when you need a new instance. For example:

      using System.Collections.Generic;
             
         //Pool
         private Queue<BulletPhysics> bulletPool = new Queue<BulletPhysics>();
             
         public BulletPhysics GetBulletFromPool()
         {
            BulletPhysics bullet = null;
             
            if (this.bulletPool .Count == 0)
            {
               bullet = Instantiate(this.bulletPrefab) as BulletPhysics;
            }
            else
            {
               bullet = this.bulletPool .Dequeue();
            }
             
             bullet.gameObject.SetActive(true);
             bullet.Init();
             return bullet;
         }
             
         public void ReturnBulletToPool(BulletPhysics bullet)
         {
            bullet.ClearData();
            this.bulletPool.Enqueue(bullet);
         }
    
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 Ziron999 · Feb 04, 2015 at 11:17 PM 0
Share

is queue better than list? for performance reasons with hundreds of objects this would matter a lot to me.

avatar image
0

Answer by andrew-lukasik · Feb 04, 2015 at 04:05 PM

Hi. OnTriggerStay() can potentially be called rather frequently. Consider switching to OnTriggerEnter() and OnTriggerExit(). But more importantly - if you seek performance then abandon Instantiate() immediately and use "prefab pooling". Runtime Instantiate() takes a lot of time and very probably it alone impacts performance in your script the most.

You can use mine prefab pooling script from below (you don't have to undestand it really and it's very simple to use - after creating PoolingManager.cs just replace every "Instantiate" with "PoolingManager.Instantiate"). But keep in mind that it will work ONLY if you disable instantiated gameobject and not destroy them (just replace your "Destroy(gameObject)" with "gameObject.SetActive(false)").

 using UnityEngine;
 using System.Collections;
 #if UNITY_EDITOR
 using UnityEditor;
 #endif
 
 public class PoolingManager : MonoBehaviour {
 
     ///////////////////////////////////////////////////////////////////////////////
     // FIELDS & PROPERTIES ////////////////////////////////////////////////////////
 
     private static PoolingManager _singleton = null;
     private static PoolingManager singleton {
         get {
             if( _singleton==null ) InstantiateSingleton();
             return _singleton;
         }
     }
     public static Transform poolingContainer { get { return singleton.transform; } }
     public GameObject[] pool = new GameObject[0];
     private GameObject[] poolSourceGameObjects = new GameObject[0];
 
     ///////////////////////////////////////////////////////////////////////////////
     // MONOBEHAVIOUR MESSAGES /////////////////////////////////////////////////////
 
     // AWAKE //
     void Awake () {
         if( _singleton==null ) _singleton = this;
         else if( _singleton!=this ) Destroy( this );
     }
 
     // ON DESTROY //
     private void OnDestroy () {
         #if UNITY_EDITOR
         foreach( GameObject go in poolSourceGameObjects ) go.SetActive( true );
         #endif
     }
 
     ///////////////////////////////////////////////////////////////////////////////
     // PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
 
     // GET POOL INDEX //
     private int GetPoolIndex ( GameObject go ) {
         int result = -1;
         for( int i = 0 ; i<pool.Length ; i++ ) {
             if( !pool[i] ) {
                 pool.Remove( ref pool , i );
                 i--;
             }
             else if( !pool[i].activeInHierarchy && pool[i].name==go.name ) {
                 result = i;
                 break;
             }
         }
         if( result==-1 ) {
             AddToPool( go );
             result = pool.Length-1;
         }
         return result;
     }
     
     // ADD TO POOL
     private void AddToPool ( GameObject paramGameObject ) {
         if( paramGameObject.activeSelf ) paramGameObject.SetActive( false );
         GameObject instance = Instantiate( paramGameObject ) as GameObject;
         #if UNITY_EDITOR
         if( instance.activeSelf ) Debug.Log( "disable prefab for proper pooling: "+instance.name );
         //instance.SetActive(false);
         #endif
         instance.name = paramGameObject.name;
         instance.transform.parent = transform;
         pool.Add( ref pool , instance );
         paramGameObject.SetActive( true );
     }
 
     // INITIATE SINGLETON //
     private static void InstantiateSingleton () {
         new GameObject( "#PoolingManager" , typeof(PoolingManager) );
     }
 
     ///////////////////////////////////////////////////////////////////////////////
     // PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
 
 
 
     ///////////////////////////////////////////////////////////////////////////////
     // PUBLIC STATIC FUNCTIONS ////////////////////////////////////////////////////
 
     // INSTANTIATE POOLED //
     public static void InstantiatePooled ( GameObject paramPrefab , Vector3 paramPosition , Quaternion paramRotation ) {
         int poolIndex = singleton.GetPoolIndex( paramPrefab );
         _singleton.pool[poolIndex].transform.position = paramPosition;
         _singleton.pool[poolIndex].transform.rotation = paramRotation;
         _singleton.pool[poolIndex].SetActive( true );
         #if UNITY_EDITOR
         MaintainPoolSourceGameObjects( paramPrefab );
         #endif
     }
 public static void InstantiatePooled ( GameObject paramPrefab , Vector3 paramPosition , Quaternion paramRotation , out GameObject instance ) {
     int poolIndex = singleton.GetPoolIndex( paramPrefab );
     _singleton.pool[poolIndex].transform.position = paramPosition;
     _singleton.pool[poolIndex].transform.rotation = paramRotation;
     _singleton.pool[poolIndex].SetActive( true );

     instance = _singleton.pool[poolIndex];

     #if UNITY_EDITOR
     MaintainPoolSourceGameObjects( paramPrefab );
     #endif
 }
 
     #if UNITY_EDITOR
     // MAINTAIN POOL SOURCE GAMEOBJECTS //
     private static void MaintainPoolSourceGameObjects ( GameObject paramSourceGo ) {
         foreach( GameObject entry in _singleton.poolSourceGameObjects ) {
             if( entry==paramSourceGo ) return;
         }
         _singleton.poolSourceGameObjects.Add( ref _singleton.poolSourceGameObjects , paramSourceGo );
     }
     #endif
 
 
 }
Comment
Add comment · Show 2 · 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 andrew-lukasik · Feb 04, 2015 at 04:28 PM 0
Share

If you would like to use then you Fire function would like this:

     void Fire(Transform currentTarget)
     {
         GameObject shot;
         Pooling$$anonymous$$anager.InstantiatePooled(bullet, transform.position, Quaternion.identity , out shot);
         shot.GetComponent<BulletPhysics>().target = currentTarget;
     }

and ins$$anonymous$$d of "Destroy((shot.gameObject), 2);" attach this script to every bullet prefab:

 using UnityEngine;
 using System.Collections;
 
 public class DisableGameObjectAfterDelay : $$anonymous$$onoBehaviour {
     [SerializeField] private float delay = 2f;
 
     private void OnEnable () {
         Invoke("Execute",delay);
     }
 
     private void Execute () {
         gameObject.SetActive(false);
     }
 }

it will properly disable it after given delay

avatar image Ziron999 · Feb 04, 2015 at 11:19 PM 1
Share

You have extremely well written code i tend to put as little in singleton as possible though hmm....Would have no use for OnEnable to...need them to only fire when in a detection range I've created. Could easily modify this to my needs though. thanks for the info

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

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

Related Questions

Script calling onCollisionEnter2D and onTriggerEnter2D while disabled 1 Answer

rigidbody2D.addforce in collider 1 Answer

OnCollisionEnter, Trigger funktioniert nicht. 1 Answer

Object collision triggering null reference at runtime when colliding with clone of itself after being childed. 1 Answer

Box collider not triggering OnCollisionEnter 2 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