Draw calls for meshes using same material

Let me preface this by saying I’m a game dev neophyte, so “Duh… that’s the way it works.” is valid, but a link to resource would be appreciated in addition.

Here’s the situation:

I have a ball prefab object that has a base sphere mesh and I have a texture/material that is basically a texture atlas. The default prefab has the material tiling set to show the first skin. The ball also has a sphere collider and physic material (though I assume that’s not relevant).

In order to change the “skin” on the ball I am changing the UV offsets of the mesh. I take a copy of the original mesh (static copy on first instatiation) then use that to create the offset UVs. See example code below for what I’m doing roughly. Works a charm, uses the same material (which is great) but I’m getting a draw call for each ball I instantiate on screen (and no batching). The meshes are of course mesh instances since they are being done in code. I was expecting less draw calls or batching by using the same material.

using UnityEngine;
using System;
using System.Collections;

public class MyBall : MonoBehaviour 
{
		
	private int ballSkinId = 1;	
	private bool dirty = false;	
	
	public int BallSkinId
	{
		get {return ballSkinId;}
		set 
		{
			ballSkinId = value;
			dirty = true;			
		}
	}
	
	private MeshFilter mesh;
	private static Vector2[] originalUVs;
	private Vector2[] uvs;	
	
	void Start () 
	{
		//Get mesh to edit
		mesh = GetComponent<MeshFilter>();		
		
		if(mesh!=null)
		{
			if(originalUVs == null)
			{
			 	originalUVs = new Vector2[mesh.mesh.uv.Length];		
				mesh.mesh.uv.CopyTo (originalUVs,0);
			}		
			
			uvs = new Vector2[mesh.mesh.uv.Length]; //initialize array for modified UVs
			dirty = true;
		}
	}
	
	
		
	
	void Update()
	{
		if(dirty)
		{
			if(ballSkinId<1) return;//sanity check.. all positive number are fine, though results may vary
			
			int xOffset = (int)Math.Floor((ballSkinId-1)/15.0);
			int yOffset = (ballSkinId+14)%15;		
			
			Vector2 offset = new Vector2(xOffset,yOffset);
	
			for(int i = 0; i < mesh.mesh.uv.Length; i++)
			{
				uvs _= originalUVs *+ offset;*_

* }*

* mesh.mesh.uv = uvs; *

* dirty = false; *
* }*

* }*

}
Is this expected behavior? Is there a better way to go about this?
All balls are created programmatically (none in scene at start). There will however be a known max number of balls in a scene at any one time.

Dynamic batching has limitations on the amount of information that can included per object (polygons etc.), otherwise the overhead for batching would exceed the overhead for draw calls, thus defeating the entire purpose. The default sphere is too complex to use with dynamic batching.

I ran a quick test. I create a base game object with just a renderer and a mesh filter. I attached a script to the object to create a new mesh at runtime including random variation in the mesh. And then I instantiated a bunch of these at runtime. They all shared the same material (assigned at runtime). I ended up with 1 draw call (100 batched). Note for your situation, if you make any changes in the material at runtime (change the color, change the texture, change the blend…), you get a new instance of the material, and that object will not be batched.

the uv offset is probably a red herring and the problem could be much simpler- when you create the sphere, set its renderer.sharedMaterial to your material. Unity loves to create redundant copies of materials by default, always specifying sharedMaterial when you’re trying to batch is key.