Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 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 Danor · Apr 03, 2017 at 03:14 PM · c#physicsperformanceperformance optimization

Improve Script Performance Physics

My friend found this script and it works pretty well but there's some framedrops so i wanted to ask if you guys have any ideas on how to improve it's performance.

We're using this script + OnTriggerEnter on our enemies so they explode when the player dashes through them. The enemy is shattered into many pieces(+-900) and that causes performance issues, especially on the CPU with physics.processing, i think shattering in 100 pieces would be better but not sure how to make that work.

+Edit: I now set Time.timeScale to 0.1f at the start and back to 1 at the end and this seems to help a little but i'm still stuck at reducing the amount of triangles

 IEnumerator SplitMesh()
     {
         MeshFilter MF = GetComponent<MeshFilter>();
         MeshRenderer MR = GetComponent<MeshRenderer>();
         Mesh M = MF.mesh;
         Vector3[] verts = M.vertices;
         Vector3[] normals = M.normals;
         Vector2[] uvs = M.uv;
         for (int submesh = 0; submesh < M.subMeshCount; submesh++)
         {
             int[] indices = M.GetTriangles(submesh);
             for (int i = 0; i < indices.Length; i += 3)
             {
                 Vector3[] newVerts = new Vector3[3];
                 Vector3[] newNormals = new Vector3[3];
                 Vector2[] newUvs = new Vector2[3];
                 for (int n = 0; n < 3; n++)
                 {
                     int index = indices[i + n];
                     newVerts[n] = verts[index];
                     newUvs[n] = uvs[index];
                     newNormals[n] = normals[index];
                 }
                 Mesh mesh = new Mesh();
                 mesh.vertices = newVerts;
                 mesh.normals = newNormals;
                 mesh.uv = newUvs;
 
                 mesh.triangles = new int[] { 0, 1, 2, 2, 1, 0 };
 
                 GameObject GO = new GameObject("Triangle " + (i / 3));
                 GO.transform.position = transform.position;
                 GO.transform.rotation = transform.rotation;
                 //GO.AddComponent<MeshRenderer>().material = MR.materials[submesh];
                 GO.AddComponent<MeshRenderer>().materials = MR.materials;
                 GO.AddComponent<MeshFilter>().mesh = mesh;
                 GO.AddComponent<BoxCollider>();
                 GO.AddComponent<Rigidbody>().AddExplosionForce(100, transform.position, 30);
                
 
                 Destroy(GO, 5 + Random.Range(0.0f, 5.0f));
             }
         }
         MR.enabled = false;
 
         Time.timeScale = 1.0f;
         yield return new WaitForSeconds(0.8f);
         Time.timeScale = 1.0f;
         Destroy(gameObject);
     }
     /*void OnMouseDown()
     {
         StartCoroutine(SplitMesh());
     }*/
 }

alt text

alt text

Thanks in advance

  • Edit2: Here's the full working script:

    using UnityEngine; using System.Collections;

    public class ShatterScript : MonoBehaviour{ //Change this value to split into bigger pieces int size = 15; Vector3[] newVerts = new Vector3[3]; Vector3[] newNormals = new Vector3[3]; Vector2[] newUvs = new Vector2[3];

       //Check for collision with player or enemy if this is an ally
         private void OnTriggerEnter(Collider other)
         {
             if (this.name == "Virus" && other.name == "Player")
             {
                     PlayerControl playerControl = other.GetComponent<PlayerControl>();
                     if (playerControl.boosting) StartCoroutine(SplitMesh());
             } else if(this.name == "Drone" && other.name == "Virus") {
                 StartCoroutine(SplitMesh());
             }
         }
         IEnumerator SplitMesh()
         {
             MeshFilter MF = GetComponent<MeshFilter>();
             MeshRenderer MR = GetComponent<MeshRenderer>();
             Mesh M = MF.mesh;
             Vector3[] verts = M.vertices;
             Vector3[] normals = M.normals;
             Vector2[] uvs = M.uv;
             //Half timeScale to create a minor slow-mo effect
             Time.timeScale = 0.5f;
             for (int submesh = 0; submesh < M.subMeshCount; submesh++)
             {
                 int[] indices = M.GetTriangles(submesh);
                 for (int i = 0; i < indices.Length; i += size)
                 {
                     for (int n = 0; n < 3; n++)
                     {
                         int index = indices[i + n];
                         newVerts[n] = verts[index];
                         newUvs[n] = uvs[index];
                         newNormals[n] = normals[index];
                     }
     
                     Mesh mesh = new Mesh();
                     mesh.vertices = newVerts;
                     mesh.normals = newNormals;
                     mesh.uv = newUvs;
     
                     mesh.triangles = new int[] { 0, 1, 2, 2, 1, 0 };
     
                     GameObject GO = new GameObject("Triangle " + (i / size));
                     GO.transform.position = transform.position;
                     GO.transform.rotation = transform.rotation;
                     //GO.AddComponent<MeshRenderer>().material = MR.materials[submesh];
                     GO.AddComponent<MeshRenderer>().materials = MR.materials;
                     GO.AddComponent<MeshFilter>().mesh = mesh;
                     GO.AddComponent<BoxCollider>();
                     GO.AddComponent<Rigidbody>().AddExplosionForce(100, transform.position, 75);
         //Comment to use gravity again
                     GO.GetComponent<Rigidbody>().useGravity = false;
                    
     
                     Destroy(GO, 2 + Random.Range(0.0f, 3.0f));
                 }
             }
             MR.enabled = false;
             yield return new WaitForSeconds(0.3f);
             Time.timeScale = 1.0f;
             Destroy(gameObject);
         }
     }
    
    
    
    
    
untitled.png (94.5 kB)
untitled.png (123.8 kB)
Comment
Add comment · Show 11
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 TreyH · Apr 03, 2017 at 03:17 PM 0
Share

Well that is an awful lot of instantiation going on during a per-triangle iteration.

If you comment out the "AddForce" call, what happens to your profile?

avatar image Danor TreyH · Apr 03, 2017 at 03:48 PM 0
Share

The object that's supposed to explode is duplicated and both remain there.

i'm clueless on how to do this but what if i'd only instantiate half of the objects? would they split in bigger pieces and cause less of an issue?

avatar image TreyH Danor · Apr 03, 2017 at 03:55 PM 0
Share

Oh, I meant what happens to your profiler log? I asked to try and narrow down the bulkiest task you're asking the engine to do.

Can you expand that "Physics.Processing" node, so that we can see its specific contents?

Show more comments
avatar image Mikael-H · Apr 03, 2017 at 03:54 PM 1
Share

If you could clarify your question a bit and explain what you actually want to accomplish so we don't have to trawl through the code then you may get better answers.

I think you are probably approaching this the wrong way, but it is hard to tell without a clear description and pictures. I THIN$$anonymous$$ you could probably get something good enough using particles ins$$anonymous$$d of entire game objects for every triangle. If you can't then maybe an object pool might be a better fit than instantiating and destroying tons of game objects.

avatar image Mikael-H Mikael-H · Apr 03, 2017 at 03:57 PM 0
Share

actually, if you just want to try a dirty fix then try putting

yield return null;

on line 41. you could also let it run say x iterations and then yield.

avatar image Danor Mikael-H · Apr 03, 2017 at 06:48 PM 0
Share

a vid will work better than a pic in this case so i uploaded 1 to youtube: https://youtu.be/cjanf$$anonymous$$VDWgw

i tried adding yield return null; on line 41 and pieces of the mesh shoot out of the model.

Show more comments
avatar image tanoshimi · Apr 03, 2017 at 03:55 PM 0
Share

What are you trying to do here?

 Time.timeScale = 1.0f;
 yield return new WaitForSeconds(0.8f);
  Time.timeScale = 1.0f;
avatar image Danor tanoshimi · Apr 03, 2017 at 05:47 PM 0
Share

i don't understand it either, my friend found this script online.

2 Replies

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

Answer by aditya · Apr 04, 2017 at 05:51 AM

simply change the value of the second for loop like this for (int i = 0; i < indices.Length; i += 15) but this value should always be a MULTIPLE OF 3 (Read comments for WHY) ... instead of 3 change it to something bigger, bigger value means less pieces ... and remove those two Time.TimeScale lines from there as they are doing nothing but don't remove waitForSeconds line

Important : You might also need to change the value of third for loop with the same value as of second for loop. For Eg, if you changed the value of second for loop by 15 then change the value of third for loop by 15 as well

Comment
Add comment · Show 6 · 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 Mikael-H · Apr 04, 2017 at 05:55 AM 0
Share

This is a clever idea. Also, you could increase the scale of each resulting gameobject by as much as you increase the iteration interval to make it look as about the same total amount of triangles.

avatar image TreyH · Apr 04, 2017 at 03:24 PM 0
Share

It's += 3 because of the fact that your indices in that list are the governing indices for triangles.

Changing it to += 10 might give you very strange values, but a larger multiple of 3 could work.

avatar image hrgchris · Apr 04, 2017 at 03:39 PM 0
Share

Whilst this would probably speed things up, as TreyH says, the 3 is there specifically because it's stepping over the indices 3 at a time - 3 verts per triangle.

You could increment the index by some multiple of 3 - say 15. That'd basically mean you only took every 5th triangle.

10 would go pretty crazy though as it'll start getting confused about which indices belong to which triangles - the 2nd one you tried to build would be made up of the last vert of the 3rd triangle and the first 2 verts of the fourth one :)

avatar image brunocoimbra · Apr 04, 2017 at 06:42 PM 1
Share

Also, you could move those lines to the top (along with the other variable declarations):

 Vector3[] newVerts = new Vector3[3];
 Vector3[] newNormals = new Vector3[3];
 Vector2[] newUvs = new Vector2[3];

This way, you will re-use those vectors, ins$$anonymous$$d of creating a new in each loop (as you will be re-populating them anyway).

avatar image aditya · Apr 05, 2017 at 07:13 AM 0
Share

@TreyH @hrgchris thanks for pointing it out, answer updated

Show more comments
avatar image
1

Answer by hrgchris · Apr 05, 2017 at 08:04 AM

Hey there

The info in the previous example suggests how to reduce the number of triangles in order to reduce the cost of the function, so I won't go over that again! However I would like to suggest an alternate approach in case its useful.

This kind of thing is always going to be horrendously expensive, as you're instantiating loads of stuff. You might be able to save on a bit of time by removing the box collider unless you really want these bits to bounce off things.

However a mesh explosion effect is typically achieved with a shader. On explosion, you generate a mesh that is similar to the input one, however for each triangle in the source you generate 3 unique vertices + 2 triangles (back/forward faces). Your code is already doing something similar to this, when it generates a mini mesh with these vertices/triangles in.

Once you have your 'explosion mesh' (which you can generate in advance to save time), you can then use a vertex shader to animate the vertices flying outwards from their triangle's normal.

That all takes a bit of work, so I appreciate it might be out of the scope of this question, but if you come back to it again and want another go at making it super efficient, that's the general approach to mesh explosion effects, as the heavy work can be done on load, and the effect is then performed extremely efficiently as part of the shader - you could detonate 100s of meshes at once at see it work fine.

As a middle ground, if you weren't worried about it looking identical, you might even get good results just using the unity particle system, setting up a roughly triangle shaped particle and emitting one from the centre of each particle on your enemy. It won't look the same, but might still look cool :)

-Chris

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 Danor · Apr 06, 2017 at 05:01 PM 0
Share

Hey man

Thanks for sharing those other approaches, we might look into that in the future and it's definitely good to know for future projects. I apreciate it!

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

328 People are following this question.

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

Related Questions

[C#] Game runs oddly slow 2 Answers

Alternative to getComponent? 3 Answers

Is calling GetComponent multiple times bad? 2 Answers

Job System, workers are idle even though Asked to complete 0 Answers

Understanding Raycast How Actually works in Unity [As Algorithm] 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