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 ConanHorus · Feb 20, 2012 at 12:48 AM · setpixelsgetpixelsbullet-marks

SetPixels too slow

I am having trouble with making bullet holes in an airplane model I put together in Maya. The crux of the issue seems to be the speed at which either SetPixels() or mainTex.Apply() operate since that is what all my debugging points to. Right now a single bullet hole will slow the game to a very sad 0.9 seconds per frame. The textures being edited are both 2048 X 2048 which I know is quite large (I am thinking about cutting this up into smaller textures and mapping them separately on each part of the airplane).

Without too much talking, I present my commented code for your help and ask this one question: "How can I speed up the operations?"

 var mainTex : Texture2D[]; // all editable textures of the object (some objects will have two or more) added before runtime
 
 private var holesArray = new Array(); // x (x position), y (y position), z (radius)
 private var holeTimers = new Array(); // cooling timer
 
 
 function Update () {
     UpdateBulletHoles(); // cycle through the bullet holes that already exist and aply their texture changes
 }
 
 // this function is called by the bullet, explosive, or other such object which comes in contact with this object
 function AddHole (xPos : float, yPos : float, rad : float) {
     holesArray.Push(Vector3(xPos * mainTex[0].width, yPos * mainTex[0].height, rad)); // x and y are set up for positioning the hole on the texture; z takes the radius of the projectile
     holeTimers.Push(0.0); // all bullet holes start at zero cooling time
 }
 
 function UpdateBulletHoles () {
     if (holesArray.length == 0) // if there are no active bullet holes then don't do anything
         return;
     
     // this block of code is used to remove holes that have fully cooled and to ensure that the hole is drawn as being fully cooled
     var holesToRemove = new Array();
     for (i = 0; i < holesArray.length; i++)
     {
         holeTimers[i] += Time.deltaTime * 10;
         if (holeTimers[i] >= 20)
         {
             holesToRemove.Push(i);
             holeTimers[i] = 20;
         }
     }
     
     // cycle through textures
     for (l = 0; l < mainTex.length; l++)
     {
         
         // cycle through holes
         for (k = 0; k < holesArray.length; k++)
         {
             
             // don't draw holes on parts of the geometry that have not had their UV coordinates layed out perfectly (nor ever will)
             if (holesArray[k].x >= 5 || holesArray[k].y <= 2040)
             {
                 
                 var pix : Color;
                 // get a square of pixels from the texture that is as wide and as tall as the drawn hole and centered on that hole
                 var pixels = mainTex[l].GetPixels(holesArray[k].x - holesArray[k].z - 3, holesArray[k].y + holesArray[k].z + 3, (holesArray[k].z * 2) + 6, (holesArray[k].z * 2) + 6, 0);
                 var pixPos : Vector2;
                 
                 // set up ring color to show its cooling progress
                 if (holeTimers[k] <= 10)
                     pix = Color.Lerp(Color(1, 1, 0, 1), Color(1, 0.5, 0, 1), holeTimers[k] / 10);
                 else
                     pix = Color.Lerp(Color(1, 0.5, 0, 1), Color(0.5, 0.5, 0.5, 1), (holeTimers[k] - 10) / 10);
                 
                 // cycle through the square of pixels just extracted from the texture
                 for (i = 0; i < pixels.length; i++)
                 {
                     
                     // this block of code finds the distance of each pixel from the center of the hole
                     var dist : float;
                     pixPos.x = ((i / (holesArray[k].z + 3)) - Mathf.Floor(i / (holesArray[k].z + 3))) * (holesArray[k].z + 3);
                     pixPos.y = Mathf.Floor(i / (holesArray[k].z + 3));
                     dist = Mathf.Sqrt(Mathf.Pow(pixPos.x - (holesArray[k].z + 3), 2) + Mathf.Pow(pixPos.y - (holesArray[k].z + 3), 2));
                     
                     // draw the ring on the outside of the hole 3 pixels thick and punch a hole with the previously given radius
                     if (dist <= holesArray[k].z + 3 && dist > holesArray[k].z)
                         if (pixels[i].a > 0.5)
                             pixels[i] = pix;
                     if (dist <= holesArray[k].z)
                     {
                         pixels[i] = pix;
                         pixels[i].a = 0;
                     }
                 }
                 
                 // set the square of pixels with the altered pixels
                 mainTex[l].SetPixels(holesArray[k].x - holesArray[k].z - 3, holesArray[k].y + holesArray[k].z + 3, (holesArray[k].z * 2) + 6, (holesArray[k].z * 2) + 6, pixels, 0);
                 
             }
         }
         
         mainTex[l].Apply(); // send the pixel changes to the graphics card
     }
     
     // remove fully cooled holes from the arrays
     for (i = 0; i < holesToRemove.length; i++)
     {
         holesToRemove.RemoveAt(i);
         holesArray.RemoveAt(i);
         holeTimers.RemoveAt(i);
     }
 }

Thanks, -Conan Horus

Comment
Add comment · Show 1
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 Eric5h5 · Feb 20, 2012 at 02:03 AM 4
Share

Nothing to do with SetPixels; when you use Apply() it has to upload the entire texture no matter how few or how many pixels have changed.

2 Replies

· Add your reply
  • Sort: 
avatar image
0

Answer by Ronnymonny · Jul 19, 2019 at 06:17 PM

@ConanHorus, I'm no expert, but I would say you might have better luck using particles facing away from the plane at the correct angle. Not only are particles cheap resource-wise, but they also allow you to modify the bullet hole's appearance as a separate texture rather than hardcoding it. The only major issue with this approach are the angles. Perhaps these could be inferred from the collider? While you're tinkering, you might need to view the Unity documentation here: https://docs.unity3d.com/Manual/ParticleSystems.html

Comment
Add comment · 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
0

Answer by JonPQ · Jul 19, 2019 at 10:19 PM

A few ideas and pointers for you. Looks like you are directly modifying pixels in a texture... If you have to do it that way....

Note:- sqrt is slow, pow is probably slow also.... you don't really want to be doing math on the processor, per pixel. (hint:- thats what the graphics hardware is for)

version 1.5 it would be better if you have a collection of pre-drawn textures of bullet holes (there are many on the asset store) perhaps pre-processed into 2d arrays, and do direct pixel copies, copy one array into the other... with no sqrt/pow math required. It would be much faster. Your method is slow to write pixels, but is fast for rendering and 0 cost (except when adding or removing holes) once you have modified the texture.

version 2.0 (aim for this soln if you can ) you could use a blit or camera with render to texture to draw to your texture. This is replacing your loop code, with hardware blit to draw the bullet hole into the render texture... take a look here... https://docs.unity3d.com/ScriptReference/Graphics.Blit.html

Alternate idea is to use decals.. when your raycastHit... impacts, the collision point information returns a point position and a normal. You could place a single quad, at that position, and parent it to the plane's transform, so it moves with the gameObject, orient it with its surface pointing up along the normal (something like... decal.transform.up=hit.normal; ) that quad would have a bullet hole texture/material on it.
it could have a timer script that destroys itself, or you could have a manager with a list of decals.. that manages the timers on all of them. Decals are quick and easy to implement, but suffer issues when hitting corners and edges, they intersect, or overlap outside. For example. small bullet hole decals on large walls work great mostly. But when the size of the hole gets large compared to the curve on surfaces or detail size, they look bad. There is also some performance cost.. the more decals, the more quads must be drawn and add to objects in the scene. Decals also work anywhere, and don't require keeping copies of textures to modify.

One last option... projecting / calculating geometry (small patch) to match the impact shape and geometry, and project the bullet hole texure onto that. Complex solution, that will look good..... but take a lot of work. (unless it exists on the asset store already)

good luck

Comment
Add comment · 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

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

8 People are following this question.

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

Related Questions

Is it expensive to use SetPixels() every frame for a second or 2? 1 Answer

Baking decals into a texture 3 Answers

Fade Out Background Based On Movement or Lack Thereof (Webcam Texture) 0 Answers

How to paint color on plane in runtime on mouse position? 0 Answers

Setpixels leads to a blank texture? 1 Answer


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