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
4
Question by Soiha · May 13, 2010 at 10:41 AM · iphoneparticleslegacy

How to make a particle system with different particles for each emit?

Hello,

I have texture atlas in which there are several frames of animation. I'd like to make a particle emitter that for each emitted particle would pick one frame from this atlas and use that as the particle texture. I do NOT want the particle to animate its appearance over its lifetime (like it would if I used the UV animation properties on the Particle Renderer component), just have a different frame on each emitted particle.

I tried attaching a script and modifying the material texture offset on each call to Update() but this of course changes the appearance of all emitted particles, which again is not what I want.

I guess what I'd really want is a way to access the texture offsets of an already emitted particle (so I could just change them on the "newest" particle every frame). I know I can access all the particles that the emitter has emitted via the particles array in the ParticleEmitter class, but the Particle class does not seem to provide a way to access the texture offsets.

Any ideas how I could accomplish this with the standard particle components? I'd really prefer not to write an ad hoc particle emitter just for this.

I'm doing this for the IPhone, so performance is premium.

Thanks in advance.

Comment
Add comment · Show 2
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 2pizza · Oct 27, 2013 at 11:53 AM 0
Share

still no answer for this in 4.2? =/

avatar image meat5000 ♦ · Oct 27, 2013 at 11:54 AM 1
Share

@2pizza

Looking at the age of this question I'm guessing it deals with Legacy Particles.

The new Shuriken Particle System is very different. $$anonymous$$aybe find a newer post or start a new question.

I believe Shuriken can do this as a subsystem setup.

4 Replies

· Add your reply
  • Sort: 
avatar image
14

Answer by kefrens · Jul 13, 2014 at 04:25 PM

There is one simple but tricky way: 1 First create bitmap with particle images put in single column. 2 In Particle System enable subsystem "Texture Sheet Animation". 3 Into it set "Animation" to "SingleRow". Now when particle will be spawn the system will randomly choose image for it from column. During each update system will try to animate it by selecting random images across row, but because there is only one image in every row then the image will stay the same.

Comment
Add comment · Show 3 · 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 justinbowes · Jan 31, 2015 at 10:23 PM 0
Share

This worked well for me with Shuriken.

avatar image ecesis_llc · Dec 11, 2016 at 11:56 PM 2
Share

Thanks kefrens. Here is a screenshot of how to set this up in the particle system.

alt text

unity-random-texture-particles.png (217.9 kB)
avatar image Sunfire2490 ecesis_llc · May 21, 2019 at 12:45 PM 0
Share

It worked for me! Thank you!

avatar image
3

Answer by JPLKit · Jan 08, 2014 at 10:41 PM

I recently had to do this. It took a while to figure out, but it allows me to have > 10,000 particles each with a specific texture and color. The performance is reasonable on a macbook pro (i7, intel 4000 integrated graphics) I don't know how good it would be on a mobile platform.

I can update the position of each particle in the update portion of my game loop by updating the position field of the particles array associated with the emitter.

I have a texture atlas that is a grid of circles each one containing a number:

(1)(2)(3)

(4)(5)(6)

(7)(8)(9)

I want to choose which part of the texture atlas to display based on a value.

First I created the particle system, material and emitter:

private void SetupGameObject() { this.gameObject = new GameObject(this._id); this.gameObject.layer = Explorer.Application.LAYER_STAR;

         this.particleRenderer = this.gameObject.AddComponent<ParticleRenderer>();
         this.particleRenderer.maxParticleSize = 1e8f;
         this.particleRenderer.material.shader = Shader.Find("ParticleTextureChooser");

         this.particleRenderer.material.mainTexture = (Texture2D)Resources.Load("Common/Textures/MyTextureName");

         this.emitter = (ParticleEmitter)this.gameObject.AddComponent("EllipsoidParticleEmitter");
         this.emitter.emit = false;
         this.emitter.minSize = 1.0f;
         this.emitter.maxSize = 1.0f;
         this.emitter.minEnergy = 100000.0f;
         this.emitter.maxEnergy = 100000.0f;
         this.emitter.minEmission = 0.0f;
         this.emitter.maxEmission = 1.0f;
         this.emitter.localVelocity = Vector3.zero;
         this.emitter.rndVelocity = Vector3.zero;
         this.emitter.useWorldSpace = false;
     }

Using the legacy particle system I was able to set the scale of the texture with:
this.emitter.renderer.material.SetTextureScale("_MainTex", new Vector2(1.0f/3.0f, 1.0f/3.0f));

(For a 3x3 grid I set size=1/3, for a 1x3 strip you would use Vector2(1/3, 1))

I though I could change the offset with SetTextureOffset, but it set the offset for the all particles and not on a per particle basis. I ended up writing a custom shader based on the particles/addiditve shader in the unity resources download(filename: Particle Add.shader).
(You can download these from: [The Unity Downloads page][1] select your version and choose "Built-in shaders in the right hand column")

In order to calculate the offset inside the shader, I needed to pass in the value I wanted displayed. I did this by using the RGBA fields in the color passed into the emit method to hold flags for color and value. The color seems to be the only field that is passed from the particle emitter through to the shader unadulterated.

//For each particle

tempcolor.r = (float)valueFlag/255.0f;

tempcolor.g = (float)colorFlag/255.0f;

this.emitter.Emit(

     Vector3.zero,  //position  

     Vector3.zero,  //velocity  

     1.0f,  

     1.0f,  

             tempColor);    //Color passes values through to shader  

I then extracted the valueFlag and colorFlag values from the appropriate fields in the color passed into the shader and set the color and uv offset accordingly inside the shader.

This is the Shader Code based on the Particles/Addiitive shader

Shader "ParticleTextureChooser" {

Properties {

 _TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5)  

 _MainTex ("Particle Texture", 2D) = "white" {}  

 _InvFade ("Soft Particles Factor", Range(0.01,3.0)) = 1.0  

}

Category {

 Tags { "Queue"="Transparent" "IgnoreProjector"="True"   

"RenderType"="Transparent" } Blend SrcAlpha One

 AlphaTest Greater .01  

 ColorMask RGB  

 Cull Off Lighting Off ZWrite Off Fog { Color (0,0,0,0) }  

 BindChannels {  

     Bind "Color", color  

     Bind "Vertex", vertex  

     Bind "TexCoord", texcoord  

 }  

 
 // ---- Fragment program cards
 SubShader {
     Pass {
     
         CGPROGRAM
         #pragma vertex vert
         #pragma fragment frag
         #pragma fragmentoption ARB_precision_hint_fastest
         #pragma multi_compile_particles

         #include "UnityCG.cginc"

         sampler2D _MainTex;
         fixed4 _TintColor;
         uniform float4 _MainTex_ST;
         
         struct appdata_t {
             float4 vertex : POSITION;
             fixed4 color : COLOR;
             float2 texcoord : TEXCOORD0;
             float2 texcoord1 : TEXCOORD1;
         };

         struct v2f {
             float4 vertex : POSITION;
             fixed4 color : COLOR;
             float2 texcoord : TEXCOORD0;
             #ifdef SOFTPARTICLES_ON
             float4 projPos : TEXCOORD1;
             #endif
         };

         //Custom method to set color based on colorFlag
         float4 setColor(float colorCode)
         {
             float4 outputColor;
             if(colorCode  <= 0.01)
             {
                 outputColor = float4(0.0, 1.0, 1.0, 0.6);
             }
             else if (colorCode  <= 1.1) //"O"
             {
                 outputColor = float4(0.0/255.0, 0.0/255.0, 255.0/255.0, 0.6);
             }

...

                                             return outputColor;


             } 
  
         //Custom method to set uv offset based on valueFlag  

         float2 updateTexCoord(float2 tcIn, float index)
         {
             //out of bounds check
             clamp(index, 0.01, 9.0);

             //This logic is based on a 3x3 texture with 9 circles each containing a number from 1-9
             // (1)(2)(3)
             // (4)(5)(6)
             // (7)(8)(9)
             float colNumber = 2.0-(floor((round(index)-1)/3.0));
             float rowNumber = fmod(round(index)-1, 3.0);    

             return  tcIn + float2((rowNumber), (colNumber) );
         }
         v2f vert (appdata_t v)
         {
             v2f o;
             o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
             #ifdef SOFTPARTICLES_ON
             o.projPos = ComputeScreenPos (o.vertex);
             COMPUTE_EYEDEPTH(o.projPos.z);
             #endif

             //The next 3 lines calculate and set the color and uv offset for the texture atlas
             float textureOffset = updateTexCoord(v.texcoord, v.color.g*255.0); //multiply by 255 to get valueFlag 1-9
             o.color = setColor(v.color.r * 255.0); //multiply by 255 to get colorFlag 1-n
             o.texcoord = TRANSFORM_TEX(textureOffset,_MainTex); //This sets the UV offset choosing the location in the texture atlas
             return o;
         }
         //The rest of the shader is unchanged from particle/additive
         sampler2D _CameraDepthTexture;
         float _InvFade;
         
         fixed4 frag (v2f i) : COLOR
         {
             #ifdef SOFTPARTICLES_ON
             float sceneZ = LinearEyeDepth (UNITY_SAMPLE_DEPTH(tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos))));
             float partZ = i.projPos.z;
             float fade = saturate (_InvFade * (sceneZ-partZ));
             i.color.a *= fade;
             #endif
             
             return 2.0f * i.color * _TintColor * tex2D(_MainTex, i.texcoord);
         }
         ENDCG 
     }
 }     
 
 // ---- Dual texture cards
 SubShader {
     Pass {
         SetTexture [_MainTex] {
             constantColor [_TintColor]
             combine constant * primary
         }
         SetTexture [_MainTex] {
             combine texture * previous DOUBLE
         }
     }
 }
 
 // ---- Single texture cards (does not do color tint)
 SubShader {
     Pass {
         SetTexture [_MainTex] {
             combine texture * primary
         }
     }
 }

} }

The key method above is v2f vert (appdata_t v) and the key line in vert to change the vu offset and choose which section of your texture atlas you want to display for that particle is

o.texcoord = TRANSFORM_TEX(textureOffset,_MainTex); //This sets the UV

I set the desired offset and color at the beginning and leave them unchanged, but by getting the array of particles from the emitter and changing the color.r and color.g values you could alter the offset and color from a script.

This post is long and convoluted (much like writing the shader was) so I welcome questions and am happy to add clarification/edits to make it easier to understand. [1]: http://unity3d.com/unity/download/archive

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
1

Answer by JonManatee · Jun 16, 2010 at 09:58 PM

All the particles in a system will read from the same material. You've probably noticed that objects that share a material will all be affected by the material's properties, including offset. Therefore, you will most likely need to have separate emitters with different materials attached to each one.

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
1

Answer by ivanp · Feb 04, 2012 at 09:38 AM

A common technique is for each particle to randomly pick a tile in the atlas. In order to achieve this we need to be able to set the uv coordinates of each particle to a random index in the texture atlas. We don't need to assign a new material for each particle and we don't need to modify the material assigned to the particle system either. Unfortunately I can't find a way to access the uv index of the particle through the particle class either. This would be good. Alternatively just having a 'pick random start frame' checkbox in the particle renderer would be even easier

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 BCFEGAmes · Feb 21, 2018 at 02:03 PM 0
Share

Bump on this one, spawning a different particle from a sheet, on new emit, but not random, actually controlling what particle to spawn in script: if value in script changes from x to y, leave existing particles alone and next emit spawn different particle from sheet or sprite, it appears that a trail of pooled instantiate is more suitable, but would love to keep the other particles properties. Tried messing with Start frame, row, frame over time, but as you change the parameter, all existing particles also change, was trying to set up a sub emitter that would spawn the sheet, but my head nearly exploded! Any thoughts>

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

9 People are following this question.

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

Related Questions

Blocking particles then destroy then reduce health 0 Answers

The name 'Joystick' does not denote a valid type ('not found') 2 Answers

Keep particles to defined area, destroy on collision 0 Answers

smooth follow camera problem in unity iphone 0 Answers

Programatically driven particles 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