• Editor
  • Illustrator -> Spine Character Recreation

Related Discussions
...

Hello Nate,

I have a question. We have our character in Illustrator CC. Nicely layered and grouped. In illustrator the character is visually as it should be. We then export this character to individual pieces (pngs) together with xml file that says where each individual png was located. I think about how to use this exported xml and recreate the same visual look in spine so that animators dont have to put all images together. (it takes quite a long time) We have this solution already for Illustrator -> Unity. So whatever we create in illustator we are then able to recreate in Unity by just one click. No need to positioning all pngs. All sits and fits pixel perfect.

So my question how can I procedurally or via script add images into spine scene and set their position and likely correct names according the xml (illustrator) file. Is this process possible?

Thank you very much.

We have pretty massive illustrator export script and I would like to make the same you have in Photoshop in Illustrator. So that we can export from our illusrator files json and pngs for you Spine and recreate our charachters. I will let you know how it goes. Can you please post here an example of that export import photoshop json file?

Sure:

{"skeleton":{"images":"images/"},
"bones":[{"name":"root"}],
"slots":[
   {"name":"rear_upper_arm","bone":"root","attachment":"rear_upper_arm"},
   {"name":"rear_bracer","bone":"root","attachment":"rear_bracer"},
   {"name":"rear_fist_closed","bone":"root","attachment":"rear_fist_closed"},
   {"name":"gun","bone":"root","attachment":"gun"},
   {"name":"rear_thigh","bone":"root","attachment":"rear_thigh"},
   {"name":"neck","bone":"root","attachment":"neck"},
   {"name":"rear_foot","bone":"root","attachment":"rear_foot"},
   {"name":"rear_shin","bone":"root","attachment":"rear_shin"},
   {"name":"torso","bone":"root","attachment":"torso"},
   {"name":"front_thigh","bone":"root","attachment":"front_thigh"},
   {"name":"front_foot","bone":"root","attachment":"front_foot"},
   {"name":"front_shin","bone":"root","attachment":"front_shin"},
   {"name":"head","bone":"root","attachment":"head"},
   {"name":"eye_indifferent","bone":"root","attachment":"eye_indifferent"},
   {"name":"mouth_smile","bone":"root","attachment":"mouth_smile"},
   {"name":"goggles","bone":"root","attachment":"goggles"},
   {"name":"front_upper_arm","bone":"root","attachment":"front_upper_arm"},
   {"name":"front_bracer","bone":"root","attachment":"front_bracer"},
   {"name":"front_fist_closed","bone":"root","attachment":"front_fist_closed"}
],
"skins":{
   "default":{
      "front_fist_closed":{"front_fist_closed":{"x":397.5,"y":522,"width":169,"height":182}},
      "front_bracer":{"front_bracer":{"x":343.5,"y":639.5,"width":135,"height":179}},
      "front_upper_arm":{"front_upper_arm":{"x":366,"y":743.5,"width":128,"height":213}},
      "goggles":{"goggles":{"x":484.5,"y":1089,"width":541,"height":352}},
      "mouth_smile":{"mouth_smile":{"x":522,"y":931.5,"width":206,"height":137}},
      "eye_indifferent":{"eye_indifferent":{"x":549.5,"y":1051.5,"width":205,"height":197}},
      "head":{"head":{"x":515.5,"y":1146,"width":561,"height":614}},
      "front_shin":{"front_shin":{"x":401,"y":298.5,"width":184,"height":387}},
      "front_foot":{"front_foot":{"x":451,"y":145,"width":272,"height":158}},
      "front_thigh":{"front_thigh":{"x":422,"y":479.5,"width":116,"height":243}},
      "torso":{"torso":{"x":395.5,"y":720,"width":215,"height":378}},
      "rear_shin":{"rear_shin":{"x":477,"y":293,"width":170,"height":376}},
      "rear_foot":{"rear_foot":{"x":533,"y":148,"width":246,"height":140}},
      "neck":{"neck":{"x":415,"y":863,"width":92,"height":102}},
      "rear_thigh":{"rear_thigh":{"x":456,"y":505.5,"width":150,"height":227}},
      "gun":{"gun":{"x":569.5,"y":500.5,"width":439,"height":425}},
      "rear_fist_closed":{"rear_fist_closed":{"x":454,"y":577,"width":164,"height":166}},
      "rear_bracer":{"rear_bracer":{"x":407.5,"y":667,"width":131,"height":162}},
      "rear_upper_arm":{"rear_upper_arm":{"x":408.5,"y":760,"width":113,"height":192}}
   }
},
"animations":{"animation":{}}
}

I'm not sure it is worth the effort to write a more complex Illustrator script. Instead, in Illustrator go to File -> Export -> PSD, then open the PSD with Photoshop and run the Photoshop LayersToPNG script.

Your massive Illustrator script can be separate from this. This is just to get your layers into Spine.

Yes it is the worth the effort. Since we have lots of spine projects and to do it manually through photoshop would be an extra work. Anyway I do export xml from my illustrator export so make this spine json is easy. How do I then tell spine to use this json file to recreate the character? Via import data?

Yeah use Import Data, find the JSON file and set a name for the skeleton.

Ok... thank you... this will speed up our character creation a lot. :-) We work in Illustrator since we export all kind of resolutions for all kind of devices. And we have also workflow how to scale spine animations and reatlas them. Actually only 3 clicks and we are able to produce whole game in different resolution. (especially we aim to have this solution for 4k upcoming market so that we just do these 3 clicks and are ready to publish)

Keep in mind that you can create your skeleton at the largest scale and then at export under Spine Texture Packer Settings set 3 different scales. At runtime you can then set the skeleton scale and which texture to use based on resolution.

Yes but that means scaling of the graphics down for smaller resolution devices and also it means 3 textures in one build. Our solution is one texture and almost pixel perfect. That's why we use for all our graphics illustrator. Check in attachment what we are able to produce in illustrator. No photoshop at all.


And anyway, Shiu, your proposed solution won't work for 4k displays. Try to imagine 4k textures on android devices. The app would have over hundred mega.

You would not need to use the 4k version on Android 🙂 If you export multiple sizes you will end up with different size texture atlases and can pick which ones you want to use for each platform.

Helo Nate and Shiu,

So far I was able to import our illustrator export. I have several questions.

We generate from illustrator sometimes quite deep image directory structures. It depends how complex our character or scene are. We put these image directory structure into images directory on the same level where the spine file resides. So far I was able to import our dennis character without problem. As you can see in slots there is that "simple" directory path to image like dennis/nose etc. (images/dennis/nose.png)

So far all is imported correctly. So my questions:

1) is this directory path to an image also valid in skin definition?

"dennis/nose":{"dennis/nose":{"x":2484.75176617693,"y":-1459.81322950865, "width":50,"height":50}},

2) When we import this json into spine. All the images under each generated slots are as default turned off. I need to go over them in your hierarchy tree and turn them on. How can I define as default to have them on?

3) I don't have information from illustrator how big is the exported image so I put into skin definition just default 50px. Is it ok? Seems like this width and height does not have effect on whatever wen importing the file.

"dennis/nose":{"dennis/nose":{"x":2484.75176617693,"y":-1459.81322950865, "width":50,"height":50}},

{"skeleton":{"images":"images/"},
"bones":[{"name":"root"}],
"slots":[
      {"name":"dennis/nose","bone":"root","atachment":"dennis/nose"},
      {"name":"dennis/face","bone":"root","atachment":"dennis/face"},
      {"name":"dennis/shin_left","bone":"root","atachment":"dennis/shin_left"},
      {"name":"dennis/tigh_left","bone":"root","atachment":"dennis/tigh_left"},
      {"name":"dennis/tigh_right","bone":"root","atachment":"dennis/tigh_right"},
      {"name":"dennis/shin_right","bone":"root","atachment":"dennis/shin_right"},
      {"name":"dennis/upper_arm_right","bone":"root","atachment":"dennis/upper_arm_right"},
      {"name":"dennis/fore_arm_right","bone":"root","atachment":"dennis/fore_arm_right"},
      {"name":"dennis/hand_right","bone":"root","atachment":"dennis/hand_right"},
      {"name":"dennis/belt","bone":"root","atachment":"dennis/belt"},
      {"name":"dennis/body","bone":"root","atachment":"dennis/body"},
      {"name":"dennis/pelvis","bone":"root","atachment":"dennis/pelvis"},
      {"name":"dennis/hair_2","bone":"root","atachment":"dennis/hair_2"},
      {"name":"dennis/hair_1","bone":"root","atachment":"dennis/hair_1"},
      {"name":"dennis/hair","bone":"root","atachment":"dennis/hair"},
      {"name":"dennis/stick","bone":"root","atachment":"dennis/stick"},
      {"name":"dennis/hand_left_1","bone":"root","atachment":"dennis/hand_left_1"},
      {"name":"dennis/hand_left_2","bone":"root","atachment":"dennis/hand_left_2"},
      {"name":"dennis/head","bone":"root","atachment":"dennis/head"},
      {"name":"dennis/neck","bone":"root","atachment":"dennis/neck"},
      {"name":"dennis/shoe_right","bone":"root","atachment":"dennis/shoe_right"},
      {"name":"dennis/shoe_left","bone":"root","atachment":"dennis/shoe_left"},
      {"name":"dennis/lower_arm_left","bone":"root","atachment":"dennis/lower_arm_left"},
      {"name":"dennis/upper_arm_left","bone":"root","atachment":"dennis/upper_arm_left"},
      {"name":"dennis/flap","bone":"root","atachment":"dennis/flap"}
],
"skins":{
   "default":{
      "dennis/nose":{"dennis/nose":{"x":2484.75176617693,"y":-1459.81322950865, "width":50,"height":50}},
      "dennis/face":{"dennis/face":{"x":2234.99816714726,"y":-1442.83041325158, "width":50,"height":50}},
      "dennis/shin_left":{"dennis/shin_left":{"x":2562.52614362161,"y":-2295.70602553291, "width":50,"height":50}},
      "dennis/tigh_left":{"dennis/tigh_left":{"x":2482.57085347238,"y":-2082.08207714063, "width":50,"height":50}},
      "dennis/tigh_right":{"dennis/tigh_right":{"x":2284.63690621134,"y":-2106.47621449853, "width":50,"height":50}},
      "dennis/shin_right":{"dennis/shin_right":{"x":2302.95396094285,"y":-2333.10306602281, "width":50,"height":50}},
      "dennis/upper_arm_right":{"dennis/upper_arm_right":{"x":2176.65893610508,"y":-1679.3119892868, "width":50,"height":50}},
      "dennis/fore_arm_right":{"dennis/fore_arm_right":{"x":2110.47143974742,"y":-1809.22510628168, "width":50,"height":50}},
      "dennis/hand_right":{"dennis/hand_right":{"x":2224.25545434279,"y":-1865.53158501358, "width":50,"height":50}},
      "dennis/belt":{"dennis/belt":{"x":2350.06316799073,"y":-1878.2915137287, "width":50,"height":50}},
      "dennis/body":{"dennis/body":{"x":2366.07383257801,"y":-1733.70186388577, "width":50,"height":50}},
      "dennis/pelvis":{"dennis/pelvis":{"x":2371.36092948914,"y":-1978.74259062685, "width":50,"height":50}},
      "dennis/hair_2":{"dennis/hair_2":{"x":2347.44042074815,"y":-1113.44832201495, "width":50,"height":50}},
      "dennis/hair_1":{"dennis/hair_1":{"x":2498.01985267431,"y":-1126.81025515863, "width":50,"height":50}},
      "dennis/hair":{"dennis/hair":{"x":2408.57408580624,"y":-1276.74257496786, "width":50,"height":50}},
      "dennis/stick":{"dennis/stick":{"x":2907.36185470331,"y":-1445.66408853348, "width":50,"height":50}},
      "dennis/hand_left_1":{"dennis/hand_left_1":{"x":2814.05676100199,"y":-1375.24728855201, "width":50,"height":50}},
      "dennis/hand_left_2":{"dennis/hand_left_2":{"x":2730.6449429806,"y":-1449.18609611832, "width":50,"height":50}},
      "dennis/head":{"dennis/head":{"x":2428.97612773529,"y":-1453.03645827561, "width":50,"height":50}},
      "dennis/neck":{"dennis/neck":{"x":2369.41959364516,"y":-1572.81466112767, "width":50,"height":50}},
      "dennis/shoe_right":{"dennis/shoe_right":{"x":2290.38306029282,"y":-2464.3094207495, "width":50,"height":50}},
      "dennis/shoe_left":{"dennis/shoe_left":{"x":2645.82913325314,"y":-2451.42153782552, "width":50,"height":50}},
      "dennis/lower_arm_left":{"dennis/lower_arm_left":{"x":2653.78801279418,"y":-1585.99189028719, "width":50,"height":50}},
      "dennis/upper_arm_left":{"dennis/upper_arm_left":{"x":2498.01984768004,"y":-1657.05784949197, "width":50,"height":50}},
      "dennis/flap":{"dennis/flap":{"x":2202.72526960891,"y":-1958.12555362514, "width":50,"height":50}}
   }
},
"animations":{"animation":{}}
}

Glad you got it mostly working relatively quickly. :happy:

1) Any string can be used for the attachment names in a skin.
2) Set the attachment field on the slot. You've spelled it atachment. 🙂
3) Looks like something using an unscaled value.
4) The size is normally used at runtime. For the editor, it is only used if the image file cannot be read (to show the size of the "missing" images). It needs to be there, but you can just use 0.

Have you see the docs?
http://esotericsoftware.com/spine-json-format/

Also note that the Photoshop script can use groups to output skins (the Use groups as skins checkbox). You'll probably want to play with that yourself, compare a Photoshop group setup to the output JSON, etc.
http://esotericsoftware.com/spine-images#Photoshop

Mission completed. All is working seamlessly. :-) Our illustrator export and import to spine can be in whatever resolution for initial spine character setup and animations. Then when we need it in lower resolution or higher resolution we just regenerate our graphics and reatlas spine atlases. All the sizes and animation proportions thanks to Spine Unity Runtime stay the same. I'M VERY HAPPY. :-) Thank you guys.

Shiu :

We regenerate the whole graphics for individual devices so we end with exactly what we need for specific target devices. No need to clicking and choosing what texture we need to use or whatever. To generate our games in 4k is matter of 3 clicks. And if we decide to have it in 1k it is again matter of 3 click for regenerating all the graphics from our illustrator files. (not only spine graphics but also all other backgrounds)

Great! 🙂

Shiu is saying you can use Spine to pack your 4k images into an atlas sized at 4k and also additional atlases down scaled to (for example) 1080, 720, 480 and 320. The result is 5 atlases. This would be instead of exporting 5 sets of images from Illustrator at different resolutions, then packing them individually to get the 5 atlases. Maybe Illustrator does a better job than down scaling, but if not then the results are the same.

4 dana kasnije

I know about your technique. And i fully understand. But in our solution we don't have 5 atlases. We have only one. The actual one we need. I regenerate the graphics with same names and paths directly into unity. Set their pixelsPerUnity accordingly so that they stay the same size and reatlasing those needed into your atlas by TexturePacker. Sure there is small overhead for CPU to generate these every time we decide to release a game for new platform or device target but we are completely free for future 4k and higher resolutions. We can generate from illustrator whatever resolution we need in top notch quality.


Hello Nate, this command line does not work on windows 8.1. Spine only opens and that's all. Nothing happens.

C:\Program Files (x86)\Spine\Spine.com


input "C:\Users\Marek\Desktop\SPINE\cat_1_spine_cat\cat_1_spine_cat.spine"


output "C:\Users\Marek\Desktop\Illustrator\Assets\SPINE\cat_1_spine_cat\"


export "C:\Users\Marek\Desktop\SPINE\cat_1_spine_cat\export.json"

Can you show your spine.log (or the output of that command)? You might try downloading and reinstalling Spine, there have been some launcher updates.

Hello Nate, I tried to install new launcher and the result is the same. See attachment for console output. Where is spine log located? (running Spine in Windows 8.1 parallels, java 8 installed)

One more question. How do you now which packing settings you should use if there is no json export file in this line? We need to reatlas our projects with specific resolutions but how do your spine knows what settings to use for packing these sprites?

Spine -i /path/to/images/ -o C:/path/to/output/


pack atlasName

foriero wrote

Hello Nate, I tried to install new launcher and the result is the same. See attachment for console output. Where is spine log located? (running Spine in Windows 8.1 parallels, java 8 installed)

One more question. How do you now which packing settings you should use if there is no json export file in this line? We need to reatlas our projects with specific resolutions but how do your spine knows what settings to use for packing these sprites?

Spine -i /path/to/images/ -o C:/path/to/output/


pack atlasName

spine.log can be found by clicking the button on the settings dialog (F12).

Not sure why Spine run for you instead of doing the export. My guess is your command line arguments are wrong. You didn't include them in the screenshot and the one you pasted is from the help.

You don't need to specify texture packer settings since they can be customized with one or more pack.json files (see the texture packer docs). You can specify 5 different resolutions in the dialog and any number in the JSON.

Still, I've updated 2.1.04 so the command line texture packer argument can now take a texture atlas name as before OR a pack settings JSON file. This might be useful if for some reason you want to pack the same images with different settings, not just with different scales. Or maybe you just don't want pack.json in your images directory (though they enable per directory packer settings for images in the same atlas).

I'll release 2.1.04 and the updated launcher tomorrow since I shouldn't be doing releases at 6am. 🙂

Hello Nate, thank you for the last release. One question : How do I tell spine what is the atlas name? Should I add it into pack.json? (atlasName = name)

-i /path/to/images/ -o C:/path/to/output/ -p /path/to/pack.json