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
2
Question by qbertreynolds · Sep 03, 2014 at 03:21 AM · batchingdrawcallsmaterialpropertyblock

Setting MaterialPropertyBlocks breaks batching

I have a prefab with the CircleCollider and following script attached:

 using UnityEngine;
 using System.Collections;
 
 public class ShakeMaterialOnTrigger : MonoBehaviour {
 
     public float shakeTime = 0.2f;
     public float amplitude = 0.1f;
     public int oscillations = 3;
 
     private static int offsetID = -1;
 
     void Awake () {
         if (offsetID == -1) offsetID = Shader.PropertyToID("_Offset");
     }
 
     void OnTriggerEnter2D (Collider2D collider) {
         StartCoroutine("Shake");
     }
 
     IEnumerator Shake () {
         float t = 0;
         while (t < shakeTime) {
             t += Time.deltaTime;
             float frac = Mathf.Clamp01(t / shakeTime);
             float x = Mathf.Sin(frac * oscillations * 2 * Mathf.PI) * amplitude * (1-frac);
             SetOffset(new Vector4(x,0,0,1));
             yield return new WaitForEndOfFrame();
         }
         SetOffset(new Vector4(0,0,0,1));
     }
 
     public void SetOffset (Vector4 offset) {
         MaterialPropertyBlock props = new MaterialPropertyBlock();
         renderer.GetPropertyBlock(props);
         props.AddVector(offsetID, offset);
         renderer.SetPropertyBlock(props);
     }
 }
 

It also has a material using the following shader:

 Shader "Custom/Offset Verts" {
   Properties {
     [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
     _Offset ("Vertex Offset (X, Y, Angle, Size)", Vector) = (0,0,0,1)
   }
 
   SubShader {
     Tags { 
       "Queue"="Transparent" 
       "IgnoreProjector"="True" 
       "RenderType"="Transparent" 
       "PreviewType"="Plane"
       "CanUseSpriteAtlas"="True"
     }
 
     Cull Off
     Lighting Off
     ZWrite Off
     Fog { Mode Off }
     Blend SrcAlpha OneMinusSrcAlpha
 
     Pass {
       CGPROGRAM
       #pragma vertex vert
       #pragma fragment frag
       #include "UnityCG.cginc"
       
       struct appdata_t {
         float4 vertex   : POSITION;
         float4 color    : COLOR;
         float2 texcoord : TEXCOORD0;
       };
 
       struct v2f {
         float4 vertex   : SV_POSITION;
         fixed4 color    : COLOR;
         half2 texcoord  : TEXCOORD0;
       };
       
       float4 _Offset;
 
       v2f vert(appdata_t IN) {
         v2f OUT;
         OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
 
         float ang = radians(_Offset.z);
         float2 pos = OUT.vertex.xy * _Offset.w;
         pos = float2(pos.x*cos(ang) - pos.y*sin(ang), pos.x*sin(ang) + pos.y*cos(ang));
         pos += _Offset.xy;
         OUT.vertex.xy = pos;
 
         OUT.texcoord = IN.texcoord;
         OUT.color = IN.color;
         return OUT;
       }
 
       sampler2D _MainTex;
 
       fixed4 frag(v2f IN) : SV_Target {
         fixed4 c = tex2D(_MainTex, IN.texcoord) * IN.color;
         return c;
       }
       ENDCG
     }
   }
 }
 

There are a few hundred of these in the scene. They're all marked as static. When I hit play, the draw call sits at 2 (one for the character, one for all of the grass), saved by batching is at a few hundred. The effect I'm looking for is there (grass shakes as you walk through it), but each time another object gets triggered, draw calls go up, batch count goes down. Am I misunderstanding something about how MaterialPropertyBlocks work? For completeness, I've also tried clearing the block before setting it.

Comment
Add comment · Show 4
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 Mikeysee · Oct 31, 2014 at 04:01 AM 1
Share

Did you ever get to the bottom of this?

avatar image unityB · Nov 09, 2015 at 10:38 PM 0
Share

I'm having the same issue.

avatar image jknight-nc · Apr 17, 2016 at 05:20 PM 0
Share

I am also attemping to use $$anonymous$$PB to achieve lower draw calls while using different colors.

avatar image joergzdarsky · May 26, 2016 at 10:33 AM 0
Share

Same issue here, am trying to render multiple objects with the same $$anonymous$$aterial- and $$anonymous$$esh-Instance, and also with the same $$anonymous$$aterialPropertyBlock (but different values with the $$anonymous$$aterialPropertyBlock), but it seems to break batching.

But my understand of the $$anonymous$$aterialPropertyBlock is that is exactly made for that use, so changing material properties without breaking the batching.

Wonder if I miss something?!

2 Replies

· Add your reply
  • Sort: 
avatar image
2

Answer by Bunny83 · May 26, 2016 at 11:11 AM

Whenever you change any global shader properties the objects can't batch. See this forum thread for more details.

Batching means to combined the geometry of multiple objects before it's send to the GPU and render it as one object. Of course all shader globals need to be the same as they are not part of the streaming vertex data. So whenever you change any material property, no matter how, the objects won't batch unless they have the same properties.

The MaterialPropertyBlock is ment for situations where you have a lot different instances with parameters that change a lot. So you don't have to duplicate the materials but you dynamically set the shader globals with the same MaterialPropertyBlock. It's not ment to save drawcalls but to save overhead.

The way you use the MaterialPropertyBlock however is extremely counter productive since you create a new MaterialPropertyBlock each time and let it be GCed each frame during your shake.

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 joergzdarsky · May 26, 2016 at 11:42 AM 0
Share

Thank you Bunny83 for the clarification. Seems I was wrong about the $$anonymous$$aterialPropertyBlock's intention.

Looks like I need to wait for the GPU Instancing feature of Unity 5.4 in my case and hope that it is flexible enough for my usecase - I want to draw the same mesh but with different textures and computebuffers assigned (which right now results in thousands of draw calls).

Thank you for the clarification.

avatar image
0

Answer by Shadowphax · Nov 05, 2018 at 10:17 AM

Quite old but I think the problem is that you don't have [PerRendererData] on the offset property, so Unity will just create a new instance anyway.

This is a good blog post on the material property block.

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

29 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

Related Questions

DrawCalls affected by localScale? 2 Answers

Draw calls on instantiated prefabs? help 0 Answers

Dynamic Batching not working even adhering to all rules 3 Answers

How can I combine object pool objects in a single draw call ? 1 Answer

Texture atlases on iphone 3 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