码迷,mamicode.com
首页 > 其他好文 > 详细

从gif到unity sprite——批量转换gif、批量导入texture packer图集为sprite、批量生成sprite预制体

时间:2014-05-07 04:41:30      阅读:694      评论:0      收藏:0      [点我收藏+]

标签:des   blog   class   code   tar   ext   

背景是我有几百个角色gif资源,每个都有:站立、攻击、技能攻击的gif,我想用此资源作2d unity游戏,因此第一关就是如何把gif转成unity动画

 

GIF 转 PNG —— http://blog.csdn.net/leinchu/article/details/24806433 ,不再赘述了。

 

之后是批量gif用tp打包,我用php写了一个脚本遍历目录,下的gif把他们重命名并每个角色建立一个文件夹,把它的所有动作的png序列移动到他自己的目录去,再用tp打包:

上php代码,因为我是分布做的,你根据自己的情况改改吧

 

<?php
$arr = scandir(dirname(__FILE__));

$count = 0;
foreach($arr as $f)
{	
	if($f==‘.‘||$f==‘..‘ ||!is_dir($f) || in_array($f,array(‘LAsset‘,‘deal_name.php‘))) continue;
	$strs = explode("_",$f);
	$pre = $strs[0];
	$id = str_replace(‘.png‘,‘‘,$strs[1]);
	$num = intval(preg_replace("/[^\d]/","",$strs[2]));
	
	$folder = ‘bb_‘.$id;
	if(!file_exists($folder)) mkdir($folder);
	
	if($num<1) $num =1;
	$cmd = "move ".$f.‘ ‘.$folder.‘/‘.$pre.‘_‘.$num.‘.png‘;
	exec($cmd);
	$cmd = ‘C:\TexturePacker\bin\TexturePacker --trim-sprite-names  --inner-padding 1 --disable-rotation ‘.$f.‘ --data ‘.$f.‘/‘.$f.‘.txt --format unity --sheet LAsset/‘.$f.‘.png --max-width 8192 --max-height 8192‘;
	exec($cmd);
	$txt = file_get_contents($f.‘/‘.$f.‘.txt‘);
	$arr =(array) json_decode($txt);

	$a = array();
	$h = $arr[‘meta‘]->size->h;
	$arr = (array) $arr[‘frames‘];


	//var_dump($arr);die();
	foreach($arr as $name=>$fr){
		$a[] = $name.‘,‘.$fr->frame->x.‘,‘.$fr->frame->y.‘,‘.$fr->frame->w.‘,‘.$fr->frame->h
		.‘,‘.$fr->spriteSourceSize->x//用于计算Pivot
		.‘,‘.$fr->spriteSourceSize->y
		.‘,‘.$fr->spriteSourceSize->w
		.‘,‘.$fr->spriteSourceSize->h
		.‘,‘.$h//tp的原点在左上角,unity的在右下角,需要用图集高度来转换
		.‘,‘.$fr->sourceSize->w
		.‘,‘.$fr->sourceSize->h
		;
	}
	file_put_contents(‘LAsset/‘.$f.‘.txt‘,implode("\r\n", $a));
	echo $f." OK\n";
	//if($count++<5) echo $cmd."\n";else break;
}

 

之后是自动把png图集转换成sprite集合,我写了脚本,你只要把这个脚本放进你的项目就可以了,然后再asset目录下建立个目录LAsset,右键这个目录把png图集导入进来,就会自动转成sprite集合了

 

using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using System.IO;

/*
Your origin picture diretory should be like:
/folder
/folder/LAsset/hero_1
/folder/LAsset/hero_1/spriteAltas.png
/folder/LAsset/hero_1/spriteAltas.txt
/folder/LAsset/hero_2/spriteAltas.png
/folder/LAsset/hero_2/spriteAltas.txt

spriteAltas.txt should be in format of "stand_1,x,y,width,height\r\nstand_2,x,y,width,height\r\nattack_1,x,y,width,height\r\nattack_2,x,y,width,height\r\nattack_3,x,y,width,height"
and finally you will got two prefabs(hero_1, hero_2) both of them has a sprite which has five members(sprites): stand_1,stand_2,attack_1,attack_2,attack_3
 */
public class LAssetPostprocessor : AssetPostprocessor
{
		void OnPostprocessAllAssets (
		string[] importedAssets,
		string[] deletedAssets,
		string[] movedAssets,
		string[] movedFromAssetPaths)
		{	
				Debug.Log ("====================== *OnPostprocessAllAssets* ===================");
				foreach (string str in importedAssets) {
						Debug.Log ("Reimported Asset: " + str);
				}

				foreach (string str in deletedAssets) {
						Debug.Log ("Deleted Asset: " + str);
				}

				for (int i=0; i < movedAssets.Length; i++) {
						Debug.Log ("Moved Asset: " + movedAssets [i] + " from: " + movedFromAssetPaths [i]);
				}
		}

		void OnProcessSprite ()
		{
				Utils.log ("++++++++++++++++++++ OnProcessSprite ++++++++++++++++++", 1);
		}

		public static string autoPathMark = "Pets";//
		private string spriteLoadFrom = "C:/D/2014/poke/img/images/bb/test/Result/LAsset/";
		private int padding = 1;
		
		void OnPreprocessTexture ()
		{
				Utils.log ("OnPreprocessTexture: " + assetPath);
				if (Path.GetExtension (assetPath) == ".png" && assetPath.IndexOf (autoPathMark) != -1) {
						string[] path;
						if (assetPath.IndexOf ("/") != -1)
								path = assetPath.Substring (assetPath.IndexOf (autoPathMark) + autoPathMark.Length + 1).Split (new string[]{"/"}, StringSplitOptions.RemoveEmptyEntries);
						else
								path = assetPath.Substring (assetPath.IndexOf (autoPathMark) + autoPathMark.Length + 1).Split (new string[]{"\\"}, StringSplitOptions.RemoveEmptyEntries);
						string spriteName = path [0].Replace (".png", "");

						string atlasPath = spriteLoadFrom + spriteName + ".txt";
						Utils.log ("Auto make sprite: " + assetPath + ", atlasPath=" + atlasPath);

						if (File.Exists (atlasPath)) {
								TextureImporter importer = assetImporter as TextureImporter;

								importer.spriteImportMode = SpriteImportMode.Multiple;
								importer.spritePixelsToUnits = 100;
								importer.spritePackingTag = spriteName;
								spriteSheetRow[] spriteSheet = spriteSheetConfigReader.getSpriteSheet (atlasPath);
								int count = spriteSheet.Length;

								Utils.log ("------------------------------------> Frame count: " + count);
								spriteSheetRow row;
								List<SpriteMetaData> spriteMetaData = new List<SpriteMetaData> ();
								for (int i=0; i<count; i++) {
										row = spriteSheet [i];
										string n = row.name;
										int x = row.x;
										int y = row.y;
										int w = row.w;
										int h = row.h;

										int height = row.height;

										//Utils.log ("==>>    x=" + x + ", y=" + y + ", w=" + w + ", h=" + h + ", height=" + height);
										SpriteMetaData metaData = new SpriteMetaData ();
										// According to Unity docs, Center = 0, Custom = 9
										metaData.alignment = 9;
										metaData.name = n;
										
										metaData.pivot = Vector2.zero;
										//metaData.pivot = new Vector2 ((row.ox + row.ow - row.sw / 2.0f) / (float)w, (row.oy + row.oh - row.sh / 2.0f) / (float)h);// Vector2 (0.5f, 0.5f);
										metaData.rect = new Rect (x, height - h - y + padding, w, h);
					
										spriteMetaData.Add (metaData);
								}

								importer.spritesheet = spriteMetaData.ToArray ();
								importer.name = spriteName;
						}
				}
		}
}

public struct spriteSheetRow
{
		public string name;
		public int x;
		public int y;
		public int w;
		public int h;
		public int ox;
		public int oy;
		public int ow;
		public int oh;
		public int height;//图集的高度
		public int sw;//当前帧的没有裁切的宽度
		public int sh;//当前帧的没有裁切的高度
}

public class spriteSheetConfigReader
{

		public static spriteSheetRow[] getSpriteSheet (string configFilePath)
		{
				//Get content of the config file, config file is suppose to in format of "name,x,y,width,height\r\nname,x,y,width,height\r\nname,x,y,width,height"
				string[] config_strs = FileUtils.getInstance ().ReadFile (configFilePath, "").Split (new string[] {
						"\r\n"
				}, StringSplitOptions.RemoveEmptyEntries);

				int len = config_strs.Length;
				spriteSheetRow[] arr = new spriteSheetRow[len];
				for (int i=0; i<len; i++) {
						//for debug message, you can delete it
						ConfigLoader.log_head = configFilePath + " > row " + i;

						string[] tmp = config_strs [i].Split (new string[]{","}, StringSplitOptions.RemoveEmptyEntries);
						spriteSheetRow row;
						row.name = tmp [0];
						row.x = Utils.parseInt (tmp [1]);
						row.y = Utils.parseInt (tmp [2]);
						row.w = Utils.parseInt (tmp [3]);
						row.h = Utils.parseInt (tmp [4]);

						row.ox = Utils.parseInt (tmp [5]);
						row.oy = Utils.parseInt (tmp [6]);
						row.ow = Utils.parseInt (tmp [7]);
						row.oh = Utils.parseInt (tmp [8]);

						row.height = Utils.parseInt (tmp [9]);
						row.sw = Utils.parseInt (tmp [10]);
						row.sh = Utils.parseInt (tmp [11]);

						arr [i] = row;

				}
				return arr;
		}
}


 

因为在导入过程中sprite没有生成,也没有生成后再调用的方法,所以只能再通过一个菜单来批量转换为prefab,把下面的脚本放到你的项目里面,在unity里面选中Asset/LAsset目录,点击菜单Assets/+> Build Prefabs From Selection...预制体就会被打包到Resources下(具体自己改路径吧)

using UnityEngine;  
using UnityEditor;  
using System.IO;
using System;
using System.Collections;
using System.Collections.Generic;

public class LExportPrefabs
{
		private static string[] state_type = new string[]{"stand","attack","skill"};

		[MenuItem("Assets/+> Build Prefabs From Selection...")]
		static void LExportResource ()
		{ 
				//List<string> pathList = new List<string> ();  
				UnityEngine.Object[] objs = Selection.GetFiltered (typeof(UnityEngine.Object), SelectionMode.DeepAssets);  
				foreach (UnityEngine.Object _obj in objs) {  
						string path = AssetDatabase.GetAssetPath (_obj);
						Utils.log (path);
						if (Path.GetExtension (path) == ".png" && path.IndexOf (LAssetPostprocessor.autoPathMark) != -1) {
								string filename = Path.GetFileName (path);
								string spriteName = filename.Replace (".png", "");
								//pathList.Add (path);
								Utils.log (path + " creating prefab for " + spriteName + "...");
								GameObject obj = new GameObject (spriteName);
								obj.AddComponent<SpriteRenderer> ();
								TurnModeRPGAnimator animator = obj.AddComponent<TurnModeRPGAnimator> ();

								List<Dictionary<int, int>> frameOrderOfState = new List<Dictionary<int, int>> ();
								frameOrderOfState.Add (new Dictionary<int, int> ());
								frameOrderOfState.Add (new Dictionary<int, int> ());
								frameOrderOfState.Add (new Dictionary<int, int> ());

								UnityEngine.Object[] arr = AssetDatabase.LoadAllAssetsAtPath (path);
								int len = arr.Length;

								//List<Sprite> sprites = new List<Sprite> ();
								Utils.log ("length: " + len);
								for (int i=0; i<len; i++)
										if (arr [i] is Sprite) {
												for (int j=0; j<3; j++)
														if (arr [i].name.IndexOf (state_type [j]) != -1) {
																frameOrderOfState [j].Add (Utils.parseInt (arr [i].name.Replace (state_type [j] + "_", "")), animator.sprites.Count);
																break;
														}
												animator.sprites.Add (arr [i] as Sprite);
										}
								int idx = 0;
								foreach (Dictionary<int, int> item in frameOrderOfState) {

										int[] arrFrames = new int[item.Count];
										for (int i=0; i<item.Count; i++)
												arrFrames [i] = item [i+1];

										if (idx == 0)
												animator.standFrames = arrFrames;
										else if (idx == 1)
												animator.attackFrames = arrFrames;
										else 
												animator.skillFrames = arrFrames;

										idx++;
								}
				animator.dics.Add(1,2);
				animator.dics.Add(2,317);
					PrefabUtility.CreatePrefab ("Assets/Resources/Pets/" + spriteName + ".prefab", obj);
								GameObject.DestroyImmediate (obj);
								Utils.log ("OK");
						}
						
				}  

		}  
}


 

预制体使用:

 

UnityEngine.GameObject _obj = Resources.Load ("Pets/bb_" + id) as GameObject;
				if (_obj != null) {
						Utils.log ("Resources loaded OK");
				} else
						Utils.log ("Resources failt to load");
				Instantiate (_obj, new Vector3 (id % 3, 0, 0), new Quaternion ());



 

我的QQ群:

PHPer&页游&Mobile&U3D 2D,群号:95303036
加群除了提问之外,请记得帮助别人,谢谢。

 

从gif到unity sprite——批量转换gif、批量导入texture packer图集为sprite、批量生成sprite预制体,布布扣,bubuko.com

从gif到unity sprite——批量转换gif、批量导入texture packer图集为sprite、批量生成sprite预制体

标签:des   blog   class   code   tar   ext   

原文地址:http://blog.csdn.net/leinchu/article/details/25041047

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!