[{"data":1,"prerenderedAt":3884},["ShallowReactive",2],{"tutorial-2021-01-unity-2d-animation-part-3":3},{"tutorial":4,"series":1924,"author":3875},{"id":5,"title":6,"author":7,"body":8,"category":1904,"cover":1905,"date":1908,"description":1909,"extension":1910,"meta":1911,"navigation":165,"path":1912,"seo":1913,"series":1914,"stem":1915,"tags":1916,"youtube":1920,"youtubeRange":1921,"__hash__":1922,"slug":1923},"posts\u002Fposts\u002F2021\u002F01\u002Funity-2d-animation-part-3.md","Scripting","nir",{"type":9,"value":10,"toc":1898},"minimark",[11,15,21,31,53,56,61,64,455,467,472,478,481,485,495,568,571,575,581,587,767,770,774,780,784,791,794,849,855,990,993,997,1006,1121,1150,1517,1527,1530,1845,1872,1876,1882,1891,1894],[12,13,14],"p",{},"To unleash Unity’s 2D Animation package’s full potential, we can interact with it through scripts. In this aerticle we will learn how to swap character sprites programmatically, inject a custom sprite into an existing character, replace all sprites as a grouped skin, and finally create a mixer for composing various characters.",[16,17,20],"article-download",{"href":18,"title":19},"https:\u002F\u002Fgithub.com\u002Fnotslot\u002Ftutorial-2d-anim-character","Download Unity Project & PSB File","\nFollow along! Download the character’s PSB and the result Unity project of this article.\n",[12,22,23,24,28],{},"In the previous articles, we learned how we could work manually with the 2D Animation package’s components. ",[25,26,27],"em",{},"To briefly recap:",[29,30],"br",{},[32,33,34,38,50],"ul",{},[35,36,37],"li",{},"A Sprite Library Asset contains all sprites and their variants, organized into categories and accessible by labels.",[35,39,40,41,45,46,49],{},"Not to confuse, but there is also a Sprite Library ",[42,43,44],"strong",{},"component",", which attaches the Sprite Library ",[42,47,48],{},"Asset"," to the character.",[35,51,52],{},"A Sprite Resolver allows us to switch sprites by selecting the active variant from the Library Asset.",[54,55],"article-assets",{},[57,58,60],"h2",{"id":59},"random-swap","Random Swap",[12,62,63],{},"In our first demo, we will start by randomly selecting a head sprite.",[65,66,72],"pre",{"className":67,"code":68,"filename":69,"language":70,"meta":71,"style":71},"language-csharp shiki shiki-themes github-light","using System.Linq;\nusing Unity.Collections;\nusing UnityEngine;\nusing UnityEngine.Experimental.U2D.Animation;\nusing UnityEngine.U2D;\n\npublic class Swapper : MonoBehaviour\n{\n\n  [SerializeField]\n  private SpriteLibrary spriteLibrary = default;\n\n  [SerializeField]\n  private SpriteResolver targetResolver = default;\n\n  [SerializeField]\n  private string targetCategory = default;\n\n\n  private SpriteLibraryAsset LibraryAsset => spriteLibrary.spriteLibraryAsset;\n\n\n  public void SelectRandom ()\n  {\n    string[] labels =\n      LibraryAsset.GetCategoryLabelNames(targetCategory).ToArray();\n    int index = Random.Range(0, labels.Length);\n    string label = labels[index];\n\n    targetResolver.SetCategoryAndLabel(targetCategory, label);\n  }\n\n}\n","Swapper.cs","csharp","",[73,74,75,98,113,123,147,160,167,185,191,196,208,228,233,242,259,264,273,290,295,300,317,322,327,342,348,363,381,408,421,426,438,444,449],"code",{"__ignoreMap":71},[76,77,80,84,88,92,95],"span",{"class":78,"line":79},"line",1,[76,81,83],{"class":82},"sD7c4","using",[76,85,87],{"class":86},"s7eDp"," System",[76,89,91],{"class":90},"sgsFI",".",[76,93,94],{"class":86},"Linq",[76,96,97],{"class":90},";\n",[76,99,101,103,106,108,111],{"class":78,"line":100},2,[76,102,83],{"class":82},[76,104,105],{"class":86}," Unity",[76,107,91],{"class":90},[76,109,110],{"class":86},"Collections",[76,112,97],{"class":90},[76,114,116,118,121],{"class":78,"line":115},3,[76,117,83],{"class":82},[76,119,120],{"class":86}," UnityEngine",[76,122,97],{"class":90},[76,124,126,128,130,132,135,137,140,142,145],{"class":78,"line":125},4,[76,127,83],{"class":82},[76,129,120],{"class":86},[76,131,91],{"class":90},[76,133,134],{"class":86},"Experimental",[76,136,91],{"class":90},[76,138,139],{"class":86},"U2D",[76,141,91],{"class":90},[76,143,144],{"class":86},"Animation",[76,146,97],{"class":90},[76,148,150,152,154,156,158],{"class":78,"line":149},5,[76,151,83],{"class":82},[76,153,120],{"class":86},[76,155,91],{"class":90},[76,157,139],{"class":86},[76,159,97],{"class":90},[76,161,163],{"class":78,"line":162},6,[76,164,166],{"emptyLinePlaceholder":165},true,"\n",[76,168,170,173,176,179,182],{"class":78,"line":169},7,[76,171,172],{"class":82},"public",[76,174,175],{"class":82}," class",[76,177,178],{"class":86}," Swapper",[76,180,181],{"class":90}," : ",[76,183,184],{"class":86},"MonoBehaviour\n",[76,186,188],{"class":78,"line":187},8,[76,189,190],{"class":90},"{\n",[76,192,194],{"class":78,"line":193},9,[76,195,166],{"emptyLinePlaceholder":165},[76,197,199,202,205],{"class":78,"line":198},10,[76,200,201],{"class":90},"  [",[76,203,204],{"class":86},"SerializeField",[76,206,207],{"class":90},"]\n",[76,209,211,214,217,220,223,226],{"class":78,"line":210},11,[76,212,213],{"class":82},"  private",[76,215,216],{"class":86}," SpriteLibrary",[76,218,219],{"class":86}," spriteLibrary",[76,221,222],{"class":82}," =",[76,224,225],{"class":82}," default",[76,227,97],{"class":90},[76,229,231],{"class":78,"line":230},12,[76,232,166],{"emptyLinePlaceholder":165},[76,234,236,238,240],{"class":78,"line":235},13,[76,237,201],{"class":90},[76,239,204],{"class":86},[76,241,207],{"class":90},[76,243,245,247,250,253,255,257],{"class":78,"line":244},14,[76,246,213],{"class":82},[76,248,249],{"class":86}," SpriteResolver",[76,251,252],{"class":86}," targetResolver",[76,254,222],{"class":82},[76,256,225],{"class":82},[76,258,97],{"class":90},[76,260,262],{"class":78,"line":261},15,[76,263,166],{"emptyLinePlaceholder":165},[76,265,267,269,271],{"class":78,"line":266},16,[76,268,201],{"class":90},[76,270,204],{"class":86},[76,272,207],{"class":90},[76,274,276,278,281,284,286,288],{"class":78,"line":275},17,[76,277,213],{"class":82},[76,279,280],{"class":82}," string",[76,282,283],{"class":86}," targetCategory",[76,285,222],{"class":82},[76,287,225],{"class":82},[76,289,97],{"class":90},[76,291,293],{"class":78,"line":292},18,[76,294,166],{"emptyLinePlaceholder":165},[76,296,298],{"class":78,"line":297},19,[76,299,166],{"emptyLinePlaceholder":165},[76,301,303,305,308,311,314],{"class":78,"line":302},20,[76,304,213],{"class":82},[76,306,307],{"class":86}," SpriteLibraryAsset",[76,309,310],{"class":86}," LibraryAsset",[76,312,313],{"class":82}," =>",[76,315,316],{"class":90}," spriteLibrary.spriteLibraryAsset;\n",[76,318,320],{"class":78,"line":319},21,[76,321,166],{"emptyLinePlaceholder":165},[76,323,325],{"class":78,"line":324},22,[76,326,166],{"emptyLinePlaceholder":165},[76,328,330,333,336,339],{"class":78,"line":329},23,[76,331,332],{"class":82},"  public",[76,334,335],{"class":82}," void",[76,337,338],{"class":86}," SelectRandom",[76,340,341],{"class":90}," ()\n",[76,343,345],{"class":78,"line":344},24,[76,346,347],{"class":90},"  {\n",[76,349,351,354,357,360],{"class":78,"line":350},25,[76,352,353],{"class":82},"    string",[76,355,356],{"class":90},"[] ",[76,358,359],{"class":86},"labels",[76,361,362],{"class":82}," =\n",[76,364,366,369,372,375,378],{"class":78,"line":365},26,[76,367,368],{"class":90},"      LibraryAsset.",[76,370,371],{"class":86},"GetCategoryLabelNames",[76,373,374],{"class":90},"(targetCategory).",[76,376,377],{"class":86},"ToArray",[76,379,380],{"class":90},"();\n",[76,382,384,387,390,392,395,398,401,405],{"class":78,"line":383},27,[76,385,386],{"class":82},"    int",[76,388,389],{"class":86}," index",[76,391,222],{"class":82},[76,393,394],{"class":90}," Random.",[76,396,397],{"class":86},"Range",[76,399,400],{"class":90},"(",[76,402,404],{"class":403},"sYu0t","0",[76,406,407],{"class":90},", labels.Length);\n",[76,409,411,413,416,418],{"class":78,"line":410},28,[76,412,353],{"class":82},[76,414,415],{"class":86}," label",[76,417,222],{"class":82},[76,419,420],{"class":90}," labels[index];\n",[76,422,424],{"class":78,"line":423},29,[76,425,166],{"emptyLinePlaceholder":165},[76,427,429,432,435],{"class":78,"line":428},30,[76,430,431],{"class":90},"    targetResolver.",[76,433,434],{"class":86},"SetCategoryAndLabel",[76,436,437],{"class":90},"(targetCategory, label);\n",[76,439,441],{"class":78,"line":440},31,[76,442,443],{"class":90},"  }\n",[76,445,447],{"class":78,"line":446},32,[76,448,166],{"emptyLinePlaceholder":165},[76,450,452],{"class":78,"line":451},33,[76,453,454],{"class":90},"}\n",[12,456,457,458,460,461,463,464,466],{},"The random swap method is straight forward:",[29,459],{},"\nI query for the available labels given the head category name. I convert them into an array for direct access to the elements.",[29,462],{},"\nI then select a random index and use it to retrieve a label name for the label collection. Finally, I call ",[25,465,434],{}," to set the chosen label as the active variant for the head category.",[468,469,471],"article-giphy",{"gif":470},"pRLvFqERhLGsKhJJVL","\nSprite Swapper.\n",[12,473,474,475,477],{},"In the editor, I’ve attached the component to the character. I assigned it the character’s Sprite Library, the head’s Sprite Resolver, and filled in the ‘Head’ category name.",[29,476],{},"\nAll that remains is to add a UI button and call the method on the character.",[479,480],"article-affiliate-group",{},[57,482,484],{"id":483},"custom-injection","Custom Injection",[12,486,487,488,490,491,494],{},"We’ll continue this demo by injecting a custom head sprite, which we haven’t define a label for beforehand.",[29,489],{},"\nIn the existing script, I added a new method ",[73,492,493],{},"InjectCustom",":",[65,496,498],{"className":67,"code":497,"filename":69,"language":70,"meta":71,"style":71},"public void InjectCustom (Sprite customSprite)\n{\n  const string customLabel = \"customHead\";\n  spriteLibrary.AddOverride(customSprite, targetCategory, customLabel);\n  targetResolver.SetCategoryAndLabel(targetCategory, customLabel);\n}\n",[73,499,500,521,525,543,554,564],{"__ignoreMap":71},[76,501,502,504,506,509,512,515,518],{"class":78,"line":79},[76,503,172],{"class":82},[76,505,335],{"class":82},[76,507,508],{"class":86}," InjectCustom",[76,510,511],{"class":90}," (",[76,513,514],{"class":86},"Sprite",[76,516,517],{"class":86}," customSprite",[76,519,520],{"class":90},")\n",[76,522,523],{"class":78,"line":100},[76,524,190],{"class":90},[76,526,527,530,532,535,537,541],{"class":78,"line":115},[76,528,529],{"class":82},"  const",[76,531,280],{"class":82},[76,533,534],{"class":86}," customLabel",[76,536,222],{"class":82},[76,538,540],{"class":539},"sYBdl"," \"customHead\"",[76,542,97],{"class":90},[76,544,545,548,551],{"class":78,"line":125},[76,546,547],{"class":90},"  spriteLibrary.",[76,549,550],{"class":86},"AddOverride",[76,552,553],{"class":90},"(customSprite, targetCategory, customLabel);\n",[76,555,556,559,561],{"class":78,"line":149},[76,557,558],{"class":90},"  targetResolver.",[76,560,434],{"class":86},[76,562,563],{"class":90},"(targetCategory, customLabel);\n",[76,565,566],{"class":78,"line":162},[76,567,454],{"class":90},[12,569,570],{},"I added a new button, which calls the new method we created, passing it a custom sprite. Now, when clicking the button, it should... yeah...",[468,572,574],{"gif":573},"HJOkMq28bY7yVK2lzj","\nUnsuccessful head sprite swapping.\n",[12,576,577,578,580],{},"Here is the thing, you see, when we rigged our character in the previous article, we created meta-data of the bones and how they are bound to the Sprite. A Sprite consist of a reference to the texture and, alongside it, the rigging meta-data.",[29,579],{},"\nWhen we injected the custom Sprite, it had the texture reference but was missing the rigging meta-data.",[12,582,583,584,586],{},"In the script, before injecting the Sprite, we should duplicate the rigging meta-data. I retrieve an existing head Sprite from the Sprite Library using the active label.",[29,585],{},"\nI then get the rigging meta-data from the existing head, both the bones and the bind poses. And finally, set the custom head’s bones and bind poses.",[65,588,590],{"className":67,"code":589,"filename":69,"language":70,"meta":71,"style":71},"public void InjectCustom (Sprite customSprite)\n{\n  \u002F\u002F Duplicate bones and poses\n  string referenceLabel = targetResolver.GetLabel();\n  Sprite referenceHead =\n    spriteLibrary.GetSprite(targetCategory, referenceLabel);\n  SpriteBone[] bones = referenceHead.GetBones();\n  NativeArray\u003CMatrix4x4> poses = referenceHead.GetBindPoses();\n  customSprite.SetBones(bones);\n  customSprite.SetBindPoses(poses);\n\n  \u002F\u002F Inject new sprite\n  const string customLabel = \"customHead\";\n  spriteLibrary.AddOverride(customSprite, targetCategory, customLabel);\n  targetResolver.SetCategoryAndLabel(targetCategory, customLabel);\n}\n",[73,591,592,608,612,618,636,646,657,677,703,714,724,728,733,747,755,763],{"__ignoreMap":71},[76,593,594,596,598,600,602,604,606],{"class":78,"line":79},[76,595,172],{"class":82},[76,597,335],{"class":82},[76,599,508],{"class":86},[76,601,511],{"class":90},[76,603,514],{"class":86},[76,605,517],{"class":86},[76,607,520],{"class":90},[76,609,610],{"class":78,"line":100},[76,611,190],{"class":90},[76,613,614],{"class":78,"line":115},[76,615,617],{"class":616},"sAwPA","  \u002F\u002F Duplicate bones and poses\n",[76,619,620,623,626,628,631,634],{"class":78,"line":125},[76,621,622],{"class":82},"  string",[76,624,625],{"class":86}," referenceLabel",[76,627,222],{"class":82},[76,629,630],{"class":90}," targetResolver.",[76,632,633],{"class":86},"GetLabel",[76,635,380],{"class":90},[76,637,638,641,644],{"class":78,"line":149},[76,639,640],{"class":86},"  Sprite",[76,642,643],{"class":86}," referenceHead",[76,645,362],{"class":82},[76,647,648,651,654],{"class":78,"line":162},[76,649,650],{"class":90},"    spriteLibrary.",[76,652,653],{"class":86},"GetSprite",[76,655,656],{"class":90},"(targetCategory, referenceLabel);\n",[76,658,659,662,664,667,669,672,675],{"class":78,"line":169},[76,660,661],{"class":86},"  SpriteBone",[76,663,356],{"class":90},[76,665,666],{"class":86},"bones",[76,668,222],{"class":82},[76,670,671],{"class":90}," referenceHead.",[76,673,674],{"class":86},"GetBones",[76,676,380],{"class":90},[76,678,679,682,685,688,691,694,696,698,701],{"class":78,"line":187},[76,680,681],{"class":86},"  NativeArray",[76,683,684],{"class":90},"\u003C",[76,686,687],{"class":86},"Matrix4x4",[76,689,690],{"class":90},"> ",[76,692,693],{"class":86},"poses",[76,695,222],{"class":82},[76,697,671],{"class":90},[76,699,700],{"class":86},"GetBindPoses",[76,702,380],{"class":90},[76,704,705,708,711],{"class":78,"line":193},[76,706,707],{"class":90},"  customSprite.",[76,709,710],{"class":86},"SetBones",[76,712,713],{"class":90},"(bones);\n",[76,715,716,718,721],{"class":78,"line":198},[76,717,707],{"class":90},[76,719,720],{"class":86},"SetBindPoses",[76,722,723],{"class":90},"(poses);\n",[76,725,726],{"class":78,"line":210},[76,727,166],{"emptyLinePlaceholder":165},[76,729,730],{"class":78,"line":230},[76,731,732],{"class":616},"  \u002F\u002F Inject new sprite\n",[76,734,735,737,739,741,743,745],{"class":78,"line":235},[76,736,529],{"class":82},[76,738,280],{"class":82},[76,740,534],{"class":86},[76,742,222],{"class":82},[76,744,540],{"class":539},[76,746,97],{"class":90},[76,748,749,751,753],{"class":78,"line":244},[76,750,547],{"class":90},[76,752,550],{"class":86},[76,754,553],{"class":90},[76,756,757,759,761],{"class":78,"line":261},[76,758,558],{"class":90},[76,760,434],{"class":86},[76,762,563],{"class":90},[76,764,765],{"class":78,"line":266},[76,766,454],{"class":90},[12,768,769],{},"We can now select a random head or inject a custom one. It’s worth noting that you can skip this rig duplication step by duplicating the bones manually; the previous article demos how to do it.",[57,771,773],{"id":772},"grouped-skins","Grouped Skins",[12,775,776,777,779],{},"Before creating a character mixer, let’s look into replacing all the characters’ Sprites as a grouped skin. ",[29,778],{},"\nThe recommended approach for this is to replace the Library Asset as a whole. We first need to create multiple libraries, each consisting of the same categories but different sprites.",[468,781,783],{"gif":782},"zz0NfqNO0ZuStShHVi","\nCharacter Skinner.\n",[12,785,786,787,790],{},"In a newly created ",[73,788,789],{},"MonoBehaviour",", I added a using statement at the top of the file. It’s required for all the scripts in the project, allowing us to interact with the 2D Animation package components.",[12,792,793],{},"For those using Unity 2021 and later, the components are no longer under the experimental namespace:",[65,795,797],{"className":67,"code":796,"language":70,"meta":71,"style":71},"\u002F\u002F Unity 2020\nusing UnityEngine.Experimental.U2D.Animation;\n\n\u002F\u002F Unity 2021+\nusing UnityEngine.U2D.Animation;\n",[73,798,799,804,824,828,833],{"__ignoreMap":71},[76,800,801],{"class":78,"line":79},[76,802,803],{"class":616},"\u002F\u002F Unity 2020\n",[76,805,806,808,810,812,814,816,818,820,822],{"class":78,"line":100},[76,807,83],{"class":82},[76,809,120],{"class":86},[76,811,91],{"class":90},[76,813,134],{"class":86},[76,815,91],{"class":90},[76,817,139],{"class":86},[76,819,91],{"class":90},[76,821,144],{"class":86},[76,823,97],{"class":90},[76,825,826],{"class":78,"line":115},[76,827,166],{"emptyLinePlaceholder":165},[76,829,830],{"class":78,"line":125},[76,831,832],{"class":616},"\u002F\u002F Unity 2021+\n",[76,834,835,837,839,841,843,845,847],{"class":78,"line":149},[76,836,83],{"class":82},[76,838,120],{"class":86},[76,840,91],{"class":90},[76,842,139],{"class":86},[76,844,91],{"class":90},[76,846,144],{"class":86},[76,848,97],{"class":90},[12,850,851,852,854],{},"I added a Sprite Library inspector field. And also created the only method we need for this script, containing a Library Asset parameter.",[29,853],{},"\nAll I do in this method is passing the new Library Asset to the Sprite Library component. Yep, that’s all...",[65,856,859],{"className":67,"code":857,"filename":858,"language":70,"meta":71,"style":71},"using UnityEngine;\nusing UnityEngine.Experimental.U2D.Animation;\n\npublic class Skinner : MonoBehaviour\n{\n\n  [SerializeField]\n  private SpriteLibrary spriteLibrary = default;\n\n\n  public void Replace (SpriteLibraryAsset libraryAsset)\n  {\n    spriteLibrary.spriteLibraryAsset = libraryAsset;\n  }\n\n}\n","Skinner.cs",[73,860,861,869,889,893,906,910,914,922,936,940,944,963,967,978,982,986],{"__ignoreMap":71},[76,862,863,865,867],{"class":78,"line":79},[76,864,83],{"class":82},[76,866,120],{"class":86},[76,868,97],{"class":90},[76,870,871,873,875,877,879,881,883,885,887],{"class":78,"line":100},[76,872,83],{"class":82},[76,874,120],{"class":86},[76,876,91],{"class":90},[76,878,134],{"class":86},[76,880,91],{"class":90},[76,882,139],{"class":86},[76,884,91],{"class":90},[76,886,144],{"class":86},[76,888,97],{"class":90},[76,890,891],{"class":78,"line":115},[76,892,166],{"emptyLinePlaceholder":165},[76,894,895,897,899,902,904],{"class":78,"line":125},[76,896,172],{"class":82},[76,898,175],{"class":82},[76,900,901],{"class":86}," Skinner",[76,903,181],{"class":90},[76,905,184],{"class":86},[76,907,908],{"class":78,"line":149},[76,909,190],{"class":90},[76,911,912],{"class":78,"line":162},[76,913,166],{"emptyLinePlaceholder":165},[76,915,916,918,920],{"class":78,"line":169},[76,917,201],{"class":90},[76,919,204],{"class":86},[76,921,207],{"class":90},[76,923,924,926,928,930,932,934],{"class":78,"line":187},[76,925,213],{"class":82},[76,927,216],{"class":86},[76,929,219],{"class":86},[76,931,222],{"class":82},[76,933,225],{"class":82},[76,935,97],{"class":90},[76,937,938],{"class":78,"line":193},[76,939,166],{"emptyLinePlaceholder":165},[76,941,942],{"class":78,"line":198},[76,943,166],{"emptyLinePlaceholder":165},[76,945,946,948,950,953,955,958,961],{"class":78,"line":210},[76,947,332],{"class":82},[76,949,335],{"class":82},[76,951,952],{"class":86}," Replace",[76,954,511],{"class":90},[76,956,957],{"class":86},"SpriteLibraryAsset",[76,959,960],{"class":86}," libraryAsset",[76,962,520],{"class":90},[76,964,965],{"class":78,"line":230},[76,966,347],{"class":90},[76,968,969,972,975],{"class":78,"line":235},[76,970,971],{"class":90},"    spriteLibrary.spriteLibraryAsset ",[76,973,974],{"class":82},"=",[76,976,977],{"class":90}," libraryAsset;\n",[76,979,980],{"class":78,"line":244},[76,981,443],{"class":90},[76,983,984],{"class":78,"line":261},[76,985,166],{"emptyLinePlaceholder":165},[76,987,988],{"class":78,"line":266},[76,989,454],{"class":90},[12,991,992],{},"While this workflow is mostly editor work, it’s great for downloading asset bundles with new skins over the network reusing existing animated characters.",[57,994,996],{"id":995},"character-mixer","Character Mixer",[12,998,999,1000,1002,1003,494],{},"In our final demo, we will create a mixer to mix-and-match sprites to create various characters.",[29,1001],{},"\nWe need a way to store all the available categories, so I created the serialized struct ",[73,1004,1005],{},"MixerCategory",[65,1007,1010],{"className":67,"code":1008,"filename":1009,"language":70,"meta":71,"style":71},"using System;\nusing UnityEngine.Experimental.U2D.Animation;\n\n[Serializable]\npublic struct MixerCategory\n{\n\n  public string name;\n\n  public string displayTitle;\n\n  public SpriteResolver resolver;\n\n}\n","MixerCategory.cs",[73,1011,1012,1020,1040,1044,1054,1064,1068,1072,1083,1087,1098,1102,1113,1117],{"__ignoreMap":71},[76,1013,1014,1016,1018],{"class":78,"line":79},[76,1015,83],{"class":82},[76,1017,87],{"class":86},[76,1019,97],{"class":90},[76,1021,1022,1024,1026,1028,1030,1032,1034,1036,1038],{"class":78,"line":100},[76,1023,83],{"class":82},[76,1025,120],{"class":86},[76,1027,91],{"class":90},[76,1029,134],{"class":86},[76,1031,91],{"class":90},[76,1033,139],{"class":86},[76,1035,91],{"class":90},[76,1037,144],{"class":86},[76,1039,97],{"class":90},[76,1041,1042],{"class":78,"line":115},[76,1043,166],{"emptyLinePlaceholder":165},[76,1045,1046,1049,1052],{"class":78,"line":125},[76,1047,1048],{"class":90},"[",[76,1050,1051],{"class":86},"Serializable",[76,1053,207],{"class":90},[76,1055,1056,1058,1061],{"class":78,"line":149},[76,1057,172],{"class":82},[76,1059,1060],{"class":82}," struct",[76,1062,1063],{"class":86}," MixerCategory\n",[76,1065,1066],{"class":78,"line":162},[76,1067,190],{"class":90},[76,1069,1070],{"class":78,"line":169},[76,1071,166],{"emptyLinePlaceholder":165},[76,1073,1074,1076,1078,1081],{"class":78,"line":187},[76,1075,332],{"class":82},[76,1077,280],{"class":82},[76,1079,1080],{"class":86}," name",[76,1082,97],{"class":90},[76,1084,1085],{"class":78,"line":193},[76,1086,166],{"emptyLinePlaceholder":165},[76,1088,1089,1091,1093,1096],{"class":78,"line":198},[76,1090,332],{"class":82},[76,1092,280],{"class":82},[76,1094,1095],{"class":86}," displayTitle",[76,1097,97],{"class":90},[76,1099,1100],{"class":78,"line":210},[76,1101,166],{"emptyLinePlaceholder":165},[76,1103,1104,1106,1108,1111],{"class":78,"line":230},[76,1105,332],{"class":82},[76,1107,249],{"class":86},[76,1109,1110],{"class":86}," resolver",[76,1112,97],{"class":90},[76,1114,1115],{"class":78,"line":235},[76,1116,166],{"emptyLinePlaceholder":165},[76,1118,1119],{"class":78,"line":244},[76,1120,454],{"class":90},[12,1122,1123,1124,1126,1127,1129,1130,1132,1133,1135,1136,1138,1139,1141,1142,1144,1145,1147,1148,91],{},"For the dropdown UI, I created another ",[73,1125,789],{}," consisting of two inspector fields: UI Text and UI Dropdown. We will use this script to control a Mixer Selector prefab.",[29,1128],{},"\nIt has a single method that accepts two parameters: the ",[73,1131,1005],{}," serialized struct we previously created and an array of labels.",[29,1134],{},"\nI start by setting the UI label to the title provided by the ",[73,1137,1005],{}," struct.",[29,1140],{},"\nNext up, I create an empty list of UI Dropdown Option Data. For each label passed to the method, I make a new Dropdown Option Data and add it to the list.",[29,1143],{},"\nI then assign the list to the UI Dropdown’s options property.",[29,1146],{},"\nLast, I hook up a listener for when the dropdown value changes. In such a case, we will receive the index of the selected item. I can then use the index to retrieve a label from the labels array. The label is then assigned as the active variant of the Sprite Resolver using ",[73,1149,434],{},[65,1151,1154],{"className":67,"code":1152,"filename":1153,"language":70,"meta":71,"style":71},"using System.Collections.Generic;\nusing UnityEngine;\nusing UnityEngine.UI;\n\npublic class MixerSelector : MonoBehaviour\n{\n\n  [SerializeField]\n  private Text titleLabel;\n\n  [SerializeField]\n  private Dropdown dropdown;\n\n\n  public void Init (MixerCategory category, string[] labels)\n  {\n    \u002F\u002F Set title\n    titleLabel.text = category.displayTitle;\n\n    \u002F\u002F Populate dropdown\n    List\u003CDropdown.OptionData> spriteLabels = new List\u003CDropdown.OptionData>();\n    foreach ( string label in labels )\n    {\n      Dropdown.OptionData data = new Dropdown.OptionData(label);\n      spriteLabels.Add(data);\n    }\n\n    dropdown.options = spriteLabels;\n\n    \u002F\u002F Handle change\n    dropdown.onValueChanged.AddListener(optionIndex =>\n    {\n      string label = labels[optionIndex];\n      category.resolver.SetCategoryAndLabel(category.name, label);\n    }); \n  }\n\n}\n","MixerSelector.cs",[73,1155,1156,1173,1181,1194,1198,1211,1215,1219,1227,1239,1243,1251,1263,1267,1271,1299,1303,1308,1318,1322,1327,1366,1384,1389,1414,1425,1430,1434,1444,1448,1453,1469,1473,1485,1496,1502,1507,1512],{"__ignoreMap":71},[76,1157,1158,1160,1162,1164,1166,1168,1171],{"class":78,"line":79},[76,1159,83],{"class":82},[76,1161,87],{"class":86},[76,1163,91],{"class":90},[76,1165,110],{"class":86},[76,1167,91],{"class":90},[76,1169,1170],{"class":86},"Generic",[76,1172,97],{"class":90},[76,1174,1175,1177,1179],{"class":78,"line":100},[76,1176,83],{"class":82},[76,1178,120],{"class":86},[76,1180,97],{"class":90},[76,1182,1183,1185,1187,1189,1192],{"class":78,"line":115},[76,1184,83],{"class":82},[76,1186,120],{"class":86},[76,1188,91],{"class":90},[76,1190,1191],{"class":86},"UI",[76,1193,97],{"class":90},[76,1195,1196],{"class":78,"line":125},[76,1197,166],{"emptyLinePlaceholder":165},[76,1199,1200,1202,1204,1207,1209],{"class":78,"line":149},[76,1201,172],{"class":82},[76,1203,175],{"class":82},[76,1205,1206],{"class":86}," MixerSelector",[76,1208,181],{"class":90},[76,1210,184],{"class":86},[76,1212,1213],{"class":78,"line":162},[76,1214,190],{"class":90},[76,1216,1217],{"class":78,"line":169},[76,1218,166],{"emptyLinePlaceholder":165},[76,1220,1221,1223,1225],{"class":78,"line":187},[76,1222,201],{"class":90},[76,1224,204],{"class":86},[76,1226,207],{"class":90},[76,1228,1229,1231,1234,1237],{"class":78,"line":193},[76,1230,213],{"class":82},[76,1232,1233],{"class":86}," Text",[76,1235,1236],{"class":86}," titleLabel",[76,1238,97],{"class":90},[76,1240,1241],{"class":78,"line":198},[76,1242,166],{"emptyLinePlaceholder":165},[76,1244,1245,1247,1249],{"class":78,"line":210},[76,1246,201],{"class":90},[76,1248,204],{"class":86},[76,1250,207],{"class":90},[76,1252,1253,1255,1258,1261],{"class":78,"line":230},[76,1254,213],{"class":82},[76,1256,1257],{"class":86}," Dropdown",[76,1259,1260],{"class":86}," dropdown",[76,1262,97],{"class":90},[76,1264,1265],{"class":78,"line":235},[76,1266,166],{"emptyLinePlaceholder":165},[76,1268,1269],{"class":78,"line":244},[76,1270,166],{"emptyLinePlaceholder":165},[76,1272,1273,1275,1277,1280,1282,1284,1287,1290,1293,1295,1297],{"class":78,"line":261},[76,1274,332],{"class":82},[76,1276,335],{"class":82},[76,1278,1279],{"class":86}," Init",[76,1281,511],{"class":90},[76,1283,1005],{"class":86},[76,1285,1286],{"class":86}," category",[76,1288,1289],{"class":90},", ",[76,1291,1292],{"class":82},"string",[76,1294,356],{"class":90},[76,1296,359],{"class":86},[76,1298,520],{"class":90},[76,1300,1301],{"class":78,"line":266},[76,1302,347],{"class":90},[76,1304,1305],{"class":78,"line":275},[76,1306,1307],{"class":616},"    \u002F\u002F Set title\n",[76,1309,1310,1313,1315],{"class":78,"line":292},[76,1311,1312],{"class":90},"    titleLabel.text ",[76,1314,974],{"class":82},[76,1316,1317],{"class":90}," category.displayTitle;\n",[76,1319,1320],{"class":78,"line":297},[76,1321,166],{"emptyLinePlaceholder":165},[76,1323,1324],{"class":78,"line":302},[76,1325,1326],{"class":616},"    \u002F\u002F Populate dropdown\n",[76,1328,1329,1332,1334,1337,1339,1342,1344,1347,1349,1352,1355,1357,1359,1361,1363],{"class":78,"line":319},[76,1330,1331],{"class":86},"    List",[76,1333,684],{"class":90},[76,1335,1336],{"class":86},"Dropdown",[76,1338,91],{"class":90},[76,1340,1341],{"class":86},"OptionData",[76,1343,690],{"class":90},[76,1345,1346],{"class":86},"spriteLabels",[76,1348,222],{"class":82},[76,1350,1351],{"class":82}," new",[76,1353,1354],{"class":86}," List",[76,1356,684],{"class":90},[76,1358,1336],{"class":86},[76,1360,91],{"class":90},[76,1362,1341],{"class":86},[76,1364,1365],{"class":90},">();\n",[76,1367,1368,1371,1374,1376,1378,1381],{"class":78,"line":324},[76,1369,1370],{"class":82},"    foreach",[76,1372,1373],{"class":90}," ( ",[76,1375,1292],{"class":82},[76,1377,415],{"class":86},[76,1379,1380],{"class":82}," in",[76,1382,1383],{"class":90}," labels )\n",[76,1385,1386],{"class":78,"line":329},[76,1387,1388],{"class":90},"    {\n",[76,1390,1391,1394,1396,1398,1401,1403,1405,1407,1409,1411],{"class":78,"line":344},[76,1392,1393],{"class":86},"      Dropdown",[76,1395,91],{"class":90},[76,1397,1341],{"class":86},[76,1399,1400],{"class":86}," data",[76,1402,222],{"class":82},[76,1404,1351],{"class":82},[76,1406,1257],{"class":86},[76,1408,91],{"class":90},[76,1410,1341],{"class":86},[76,1412,1413],{"class":90},"(label);\n",[76,1415,1416,1419,1422],{"class":78,"line":350},[76,1417,1418],{"class":90},"      spriteLabels.",[76,1420,1421],{"class":86},"Add",[76,1423,1424],{"class":90},"(data);\n",[76,1426,1427],{"class":78,"line":365},[76,1428,1429],{"class":90},"    }\n",[76,1431,1432],{"class":78,"line":383},[76,1433,166],{"emptyLinePlaceholder":165},[76,1435,1436,1439,1441],{"class":78,"line":410},[76,1437,1438],{"class":90},"    dropdown.options ",[76,1440,974],{"class":82},[76,1442,1443],{"class":90}," spriteLabels;\n",[76,1445,1446],{"class":78,"line":423},[76,1447,166],{"emptyLinePlaceholder":165},[76,1449,1450],{"class":78,"line":428},[76,1451,1452],{"class":616},"    \u002F\u002F Handle change\n",[76,1454,1455,1458,1461,1463,1466],{"class":78,"line":440},[76,1456,1457],{"class":90},"    dropdown.onValueChanged.",[76,1459,1460],{"class":86},"AddListener",[76,1462,400],{"class":90},[76,1464,1465],{"class":86},"optionIndex",[76,1467,1468],{"class":82}," =>\n",[76,1470,1471],{"class":78,"line":446},[76,1472,1388],{"class":90},[76,1474,1475,1478,1480,1482],{"class":78,"line":451},[76,1476,1477],{"class":82},"      string",[76,1479,415],{"class":86},[76,1481,222],{"class":82},[76,1483,1484],{"class":90}," labels[optionIndex];\n",[76,1486,1488,1491,1493],{"class":78,"line":1487},34,[76,1489,1490],{"class":90},"      category.resolver.",[76,1492,434],{"class":86},[76,1494,1495],{"class":90},"(category.name, label);\n",[76,1497,1499],{"class":78,"line":1498},35,[76,1500,1501],{"class":90},"    }); \n",[76,1503,1505],{"class":78,"line":1504},36,[76,1506,443],{"class":90},[76,1508,1510],{"class":78,"line":1509},37,[76,1511,166],{"emptyLinePlaceholder":165},[76,1513,1515],{"class":78,"line":1514},38,[76,1516,454],{"class":90},[12,1518,1519,1520,1523,1524,1526],{},"I created a UI Canvas prefab and attached the ",[73,1521,1522],{},"MixerSelector"," component we just created.",[29,1525],{},"\nI added a label and dropdown UI elements to the prefab and assigned them to the component.",[12,1528,1529],{},"Hang on there; we have one last script to create:",[65,1531,1534],{"className":67,"code":1532,"filename":1533,"language":70,"meta":71,"style":71},"using System.Linq;\nusing UnityEngine;\nusing UnityEngine.Experimental.U2D.Animation;\n\npublic class Mixer : MonoBehaviour\n{\n\n  [SerializeField]\n  private SpriteLibrary spriteLibrary = default;\n\n  [SerializeField]\n  private MixerSelector selectorTemplate = default;\n\n  [SerializeField]\n  private MixerCategory[] categories = default;\n\n\n  private SpriteLibraryAsset LibraryAsset => spriteLibrary.spriteLibraryAsset;\n\n\n  private void Start ()\n  {\n    foreach ( MixerCategory category in categories )\n      AddUISelector(category);\n  }\n\n\n  private void AddUISelector (MixerCategory category)\n  {\n    string[] labels = LibraryAsset.GetCategoryLabelNames(category.name)\n                                  .ToArray();\n    MixerSelector item = Instantiate(selectorTemplate, transform);\n    item.Init(category, labels);\n  }\n\n}\n","Mixer.cs",[73,1535,1536,1548,1556,1576,1580,1593,1597,1601,1609,1623,1627,1635,1650,1654,1662,1680,1684,1688,1700,1704,1708,1719,1723,1738,1746,1750,1754,1758,1775,1779,1797,1806,1822,1833,1837,1841],{"__ignoreMap":71},[76,1537,1538,1540,1542,1544,1546],{"class":78,"line":79},[76,1539,83],{"class":82},[76,1541,87],{"class":86},[76,1543,91],{"class":90},[76,1545,94],{"class":86},[76,1547,97],{"class":90},[76,1549,1550,1552,1554],{"class":78,"line":100},[76,1551,83],{"class":82},[76,1553,120],{"class":86},[76,1555,97],{"class":90},[76,1557,1558,1560,1562,1564,1566,1568,1570,1572,1574],{"class":78,"line":115},[76,1559,83],{"class":82},[76,1561,120],{"class":86},[76,1563,91],{"class":90},[76,1565,134],{"class":86},[76,1567,91],{"class":90},[76,1569,139],{"class":86},[76,1571,91],{"class":90},[76,1573,144],{"class":86},[76,1575,97],{"class":90},[76,1577,1578],{"class":78,"line":125},[76,1579,166],{"emptyLinePlaceholder":165},[76,1581,1582,1584,1586,1589,1591],{"class":78,"line":149},[76,1583,172],{"class":82},[76,1585,175],{"class":82},[76,1587,1588],{"class":86}," Mixer",[76,1590,181],{"class":90},[76,1592,184],{"class":86},[76,1594,1595],{"class":78,"line":162},[76,1596,190],{"class":90},[76,1598,1599],{"class":78,"line":169},[76,1600,166],{"emptyLinePlaceholder":165},[76,1602,1603,1605,1607],{"class":78,"line":187},[76,1604,201],{"class":90},[76,1606,204],{"class":86},[76,1608,207],{"class":90},[76,1610,1611,1613,1615,1617,1619,1621],{"class":78,"line":193},[76,1612,213],{"class":82},[76,1614,216],{"class":86},[76,1616,219],{"class":86},[76,1618,222],{"class":82},[76,1620,225],{"class":82},[76,1622,97],{"class":90},[76,1624,1625],{"class":78,"line":198},[76,1626,166],{"emptyLinePlaceholder":165},[76,1628,1629,1631,1633],{"class":78,"line":210},[76,1630,201],{"class":90},[76,1632,204],{"class":86},[76,1634,207],{"class":90},[76,1636,1637,1639,1641,1644,1646,1648],{"class":78,"line":230},[76,1638,213],{"class":82},[76,1640,1206],{"class":86},[76,1642,1643],{"class":86}," selectorTemplate",[76,1645,222],{"class":82},[76,1647,225],{"class":82},[76,1649,97],{"class":90},[76,1651,1652],{"class":78,"line":235},[76,1653,166],{"emptyLinePlaceholder":165},[76,1655,1656,1658,1660],{"class":78,"line":244},[76,1657,201],{"class":90},[76,1659,204],{"class":86},[76,1661,207],{"class":90},[76,1663,1664,1666,1669,1671,1674,1676,1678],{"class":78,"line":261},[76,1665,213],{"class":82},[76,1667,1668],{"class":86}," MixerCategory",[76,1670,356],{"class":90},[76,1672,1673],{"class":86},"categories",[76,1675,222],{"class":82},[76,1677,225],{"class":82},[76,1679,97],{"class":90},[76,1681,1682],{"class":78,"line":266},[76,1683,166],{"emptyLinePlaceholder":165},[76,1685,1686],{"class":78,"line":275},[76,1687,166],{"emptyLinePlaceholder":165},[76,1689,1690,1692,1694,1696,1698],{"class":78,"line":292},[76,1691,213],{"class":82},[76,1693,307],{"class":86},[76,1695,310],{"class":86},[76,1697,313],{"class":82},[76,1699,316],{"class":90},[76,1701,1702],{"class":78,"line":297},[76,1703,166],{"emptyLinePlaceholder":165},[76,1705,1706],{"class":78,"line":302},[76,1707,166],{"emptyLinePlaceholder":165},[76,1709,1710,1712,1714,1717],{"class":78,"line":319},[76,1711,213],{"class":82},[76,1713,335],{"class":82},[76,1715,1716],{"class":86}," Start",[76,1718,341],{"class":90},[76,1720,1721],{"class":78,"line":324},[76,1722,347],{"class":90},[76,1724,1725,1727,1729,1731,1733,1735],{"class":78,"line":329},[76,1726,1370],{"class":82},[76,1728,1373],{"class":90},[76,1730,1005],{"class":86},[76,1732,1286],{"class":86},[76,1734,1380],{"class":82},[76,1736,1737],{"class":90}," categories )\n",[76,1739,1740,1743],{"class":78,"line":344},[76,1741,1742],{"class":86},"      AddUISelector",[76,1744,1745],{"class":90},"(category);\n",[76,1747,1748],{"class":78,"line":350},[76,1749,443],{"class":90},[76,1751,1752],{"class":78,"line":365},[76,1753,166],{"emptyLinePlaceholder":165},[76,1755,1756],{"class":78,"line":383},[76,1757,166],{"emptyLinePlaceholder":165},[76,1759,1760,1762,1764,1767,1769,1771,1773],{"class":78,"line":410},[76,1761,213],{"class":82},[76,1763,335],{"class":82},[76,1765,1766],{"class":86}," AddUISelector",[76,1768,511],{"class":90},[76,1770,1005],{"class":86},[76,1772,1286],{"class":86},[76,1774,520],{"class":90},[76,1776,1777],{"class":78,"line":423},[76,1778,347],{"class":90},[76,1780,1781,1783,1785,1787,1789,1792,1794],{"class":78,"line":428},[76,1782,353],{"class":82},[76,1784,356],{"class":90},[76,1786,359],{"class":86},[76,1788,222],{"class":82},[76,1790,1791],{"class":90}," LibraryAsset.",[76,1793,371],{"class":86},[76,1795,1796],{"class":90},"(category.name)\n",[76,1798,1799,1802,1804],{"class":78,"line":440},[76,1800,1801],{"class":90},"                                  .",[76,1803,377],{"class":86},[76,1805,380],{"class":90},[76,1807,1808,1811,1814,1816,1819],{"class":78,"line":446},[76,1809,1810],{"class":86},"    MixerSelector",[76,1812,1813],{"class":86}," item",[76,1815,222],{"class":82},[76,1817,1818],{"class":86}," Instantiate",[76,1820,1821],{"class":90},"(selectorTemplate, transform);\n",[76,1823,1824,1827,1830],{"class":78,"line":451},[76,1825,1826],{"class":90},"    item.",[76,1828,1829],{"class":86},"Init",[76,1831,1832],{"class":90},"(category, labels);\n",[76,1834,1835],{"class":78,"line":1487},[76,1836,443],{"class":90},[76,1838,1839],{"class":78,"line":1498},[76,1840,166],{"emptyLinePlaceholder":165},[76,1842,1843],{"class":78,"line":1504},[76,1844,454],{"class":90},[12,1846,1847,1848,1850,1851,1853,1854,1856,1857,1859,1860,1862,1863,1865,1866,1868,1869,1871],{},"The last MonoBehaviour is the Mixer that manages this whole operation. It has three inspector fields: a Sprite Library, a MixerSelecter script we just created, and an array of ",[73,1849,1005],{}," structs we made before.",[29,1852],{},"\nI also create a method that accepts a ",[73,1855,1005],{}," for which I will create a ",[73,1858,1522],{}," instance.",[29,1861],{},"\nI start by retrieving an array of labels for the category; I get them by calling GetCategoryLabelNames on the Library Asset that I access through the Sprite Library.",[29,1864],{},"\nI then use the prefab reference to instantiate a new ",[73,1867,1522],{}," as a child of this script’s transform.",[29,1870],{},"\nI call the Init method we created and pass it the category struct and the options labels.",[468,1873,1875],{"gif":1874},"i7FzVVCqxq6U8UiHJx","\nCharacter Mixer.\n",[12,1877,1878,1879,1881],{},"Finally, when the ",[73,1880,789],{}," starts, I iterate the categories and create a selector for each of them.",[12,1883,1884,1885,1887,1888,1890],{},"To hook it all up, I created a UI Panel and attached to it the Mixer component. I assigned the character’s Sprite Library and the ",[73,1886,1522],{}," prefab we have created. I also filled in all the ",[73,1889,1005],{}," data for this character, including the category names, display titles, and the Sprite Resolvers from the character’s objects.",[12,1892,1893],{},"We can now create any sprite combination for our character!",[1895,1896,1897],"style",{},"html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}",{"title":71,"searchDepth":115,"depth":115,"links":1899},[1900,1901,1902,1903],{"id":59,"depth":100,"text":60},{"id":483,"depth":100,"text":484},{"id":772,"depth":100,"text":773},{"id":995,"depth":100,"text":996},"tutorial",{"480w":1906,"960w":1907},"\u002Fposts\u002F2021\u002F01-04\u002Funity-2d-animation-scripting-480w.jpg","\u002Fposts\u002F2021\u002F01-04\u002Funity-2d-animation-scripting-960w.jpg","2021-01-04","Creating scripts to control Unity’s 2D Animation package: Swapping, Skins, Character Mixer.","md",{},"\u002Fposts\u002F2021\u002F01\u002Funity-2d-animation-part-3",{"title":6,"description":1909},"2020-2d-animation-unity","posts\u002F2021\u002F01\u002Funity-2d-animation-part-3",[1917,73,1918,1919],"unity","animation","2d","zN9SCRrTVaA",null,"VNoVCEZnROzv60sIgtoO4BKtnPCsG-0HordVCp-BYaE","unity-2d-animation-part-3",{"id":1925,"title":1926,"description":1927,"extension":1928,"hideParts":1929,"meta":1930,"shortTitle":1921,"stem":1931,"__hash__":1932,"posts":1933},"tutorials\u002Ftutorials\u002F2020-2d-animation-unity.yaml","Unity 2D Animation","Getting started with the Unity’s 2D Animation package.\u003Cbr \u002F>All the steps untill we have a rigged character ready for animation.","yaml",false,{},"tutorials\u002F2020-2d-animation-unity","t81htfO4zTbC27f9fw_xp5mHZr2JFqwlKOu-WYEMwrM",[1934,2196,2322],{"id":1935,"title":1936,"author":1937,"body":1938,"category":1904,"cover":2183,"date":2186,"description":2187,"extension":1910,"meta":2188,"navigation":165,"path":2189,"seo":2190,"series":1914,"stem":2191,"tags":2192,"youtube":2193,"youtubeRange":1921,"__hash__":2194,"slug":2195},"posts\u002Fposts\u002F2020\u002F12\u002Funity-2d-animation-part-1.md","Bones & Rig","danielle",{"type":9,"value":1939,"toc":2177},[1940,1943,1947,1951,1964,1968,1971,1974,1980,1986,1989,1994,1997,1999,2003,2006,2010,2013,2016,2031,2043,2048,2051,2054,2060,2066,2072,2075,2080,2089,2092,2095,2101,2107,2113,2118,2120,2124,2133,2136,2155,2161,2165,2171,2174],[12,1941,1942],{},"This tutorial is about getting started with 2D Skeletal Animations in Unity. By the end of it, we will have a fully rigged character – ready and prepared for animation.",[16,1944,1946],{"href":1945,"title":19},"https:\u002F\u002Fgithub.com\u002Fnotslot\u002Ftutorial-2d-anim-character\u002Freleases\u002Fdownload\u002Fv1.0\u002FUnity.2D.Animation.Part.1.zip","\nFollow along! The download contains the character’s PSB and the result Unity project of this article.\n",[57,1948,1950],{"id":1949},"project-setting","Project Setting",[12,1952,1953,1954,1956,1957,1960,1961,91],{},"Before we can start rigging, we would need to add two packages to our unity project.",[29,1955],{},"\nGo to Window -> Package Manager and install the ",[25,1958,1959],{},"2D animation package"," and the ",[25,1962,1963],{},"2D PSD importer",[57,1965,1967],{"id":1966},"spritesheet-formats","Sprite–Sheet Formats",[12,1969,1970],{},"We can use two different formats for the character’s sprite: a PNG sprite–sheet or a PSB file.",[12,1972,1973],{},"When using the PNG format, we must separate the body parts and make sure no part covers another.",[12,1975,1976,1977,1979],{},"The second format we can use is the PSB file.",[29,1978],{},"\nThe PSB file is a large document format that supports all of the Photoshop features, including layers, effects, and filters. We create our character with the PSB file without separating the body parts as we would need if we worked with a PNG file. The PSB file contains each body part at a different layer.",[1981,1982,1985],"article-image",{"src":1983,"alt":1984},"\u002Fposts\u002F2020\u002F12-07\u002Funity-2d-animation-1.jpg","Unity 2D Animation – photoshop file","\nPhotoshop layers hieracrhy.\n",[12,1987,1988],{},"You can create this file using Adobe Photoshop, going to save as and selecting the PSB format. The process of creating bones is similar for both methods. In this tutorial, I will work with the PSB format.",[1981,1990,1993],{"src":1991,"alt":1992},"\u002Fposts\u002F2020\u002F12-07\u002Funity-2d-animation-2.jpg","Unity 2D Animation – spritesheet","\nGenerated sprite sheet inside Unity’s Sprite Editor.\n",[12,1995,1996],{},"Once we place our file in the project, you can see how it automatically separates the layers and creates a sprite sheet.",[54,1998],{},[57,2000,2002],{"id":2001},"rigging","Rigging",[12,2004,2005],{},"We open the Sprite Editor from the Inspector and change to the skinning editor. We can view the constructed character or view the sprite–sheet version by switching to the sprite-sheet mode.",[468,2007,2009],{"gif":2008},"4KXmqifPPnsYkLXAFi","\nAdding bones.\n",[12,2011,2012],{},"We draw bones over our character by selecting Create Bone and click to place a bone. By clicking once and moving our mouse, we can control the bone’s lengths and engle. A second click will complete the current bone and begin creating the next one. And with a right-click, we end the bones’ chain.",[12,2014,2015],{},"If we want to edit an existing bone’s position or length, we can either use the Edit Bone button or click on the bone’s anchor to move the bone as we like.",[12,2017,2018,2019,2022,2023,2026,2027,2030],{},"Regretting creating a bone? You can delete it by pressing ",[73,2020,2021],{},"Delete"," on Windows or ",[73,2024,2025],{},"Command"," + ",[73,2028,2029],{},"Backspace"," on Mac.",[12,2032,2033,2034,2036,2037,2039,2040,2042],{},"When creating a rigged character, it is important to pay attention to the bones hierarchy.",[29,2035],{},"\nA parent bone is the origin of the other connected bones. When we move it, it will drag the child bones with it.",[29,2038],{},"\nWith this character, we want the arms and head to follow as we move the torso bones, and for that, we will need to make the torso bone their parent.",[29,2041],{},"\nWith Unity, once we place a bone, the second one is automatically set as its child, but we can change that; clicking on a bone will mark it as the parent of the next bone we will create.",[1981,2044,2047],{"src":2045,"alt":2046},"\u002Fposts\u002F2020\u002F12-07\u002Funity-2d-animation-3.jpg","Unity 2D Animation – bones drawing","\nCharacter with bones.\n",[12,2049,2050],{},"This faint line represents their connection, and you can double-check your bone layout at any time.",[12,2052,2053],{},"Want to change a bone’s parent? We can do that at the Visibility tab. Here we can control our bone’s order, names, and depth. Choose the bone you want to change and drag it under any other bone.",[12,2055,2056,2057,2059],{},"I went ahead and fully rigged the character.",[29,2058],{},"\nFor some bones, I used the Split Bone option to split them into two. A great way to make sure two bones have the same angle.",[12,2061,2062,2063,2065],{},"Since the character’s body occludes an arm and a leg, I made sure to treat them with the bones they deserve.",[29,2064],{},"\nAt the Visibility window, you can see the bones’ names and hierarchy. I filled in different depth numbers. Higher numbers for bones near us, like the front arm and leg, and lower numbers for bones distant from us, like the back arm and leg.",[12,2067,2068,2069,2071],{},"Now it’s time to connect our bones to the sprite.",[29,2070],{},"\nFirst, we will need to add Geometry to the sprites. Geometry, also known as meshes, allows a polygon to be defined inside an image, creating vertices to manipulate bending and deform the sprite.",[12,2073,2074],{},"The simplest way to add Geometry is by the Auto Geometry option. We can go to each sprite and rearrange, add or reduce the vertices. Keep in mind that complex meshes can reduce performance; ideally, we would want to use as few vertices as possible.",[1981,2076,2079],{"src":2077,"alt":2078},"\u002Fposts\u002F2020\u002F12-07\u002Funity-2d-animation-5.jpg","Unity 2D Animation – generated geometry","\nCharacter’s generated geometry.\n",[12,2081,2082,2083,2085,2086,2088],{},"We are moving on to connecting bones.",[29,2084],{},"\nWith the Bone Influence option, we can select a sprite and add bones to influence it. Select a sprite in the Visibility window and attach to it a marked bone.",[29,2087],{},"\nOf course, one sprite can have as many bones as you like.",[12,2090,2091],{},"Though the same as before, the fewer the bones in one character, the better for your game’s performance. While Unity Jobs helps, we should always keep an eye on the performance.",[12,2093,2094],{},"To make the bones influence the sprite vertices, we need to add Weights. Weights allow transformed bones to deform the mesh automatically.",[12,2096,2097,2098,2100],{},"The easiest way is to use the Auto Weights option.",[29,2099],{},"\nWe can either generate Weights with or without associate bones. As we connected our bones in the previous step, uncheck it, and generate. We now have lovely gradients representing the weights’ division.",[12,2102,2103,2104,2106],{},"With the Weight Brush option, we can use a brush to adjust the weights.",[29,2105],{},"\nThe mode ‘Add And Subtract’ adds the influence of a new bone, while the mode ‘Grow and Shrink’ changes the weight balance between bones already influenced by the selected bone. The Smooth mode gently smoothes the gradient between bones’ weights.",[12,2108,2109,2110,2112],{},"Once finished adjusting, click Apply.",[29,2111],{},"\nDragging the character to the scene, we can see the bones we just created and the sprites.",[1981,2114,2117],{"src":2115,"alt":2116},"\u002Fposts\u002F2020\u002F12-07\u002Funity-2d-animation-4.jpg","Unity 2D Animation – Rigged character inside a Unity scene","\nRigged character inside a Unity scene.\n",[479,2119],{},[57,2121,2123],{"id":2122},"inverse-kinematics-ik","Inverse Kinematics (IK)",[12,2125,2126,2127,2129,2130,2132],{},"Our last step before starting to animate is to add IKs.",[29,2128],{},"\nWith IK, we can add inverse kinematics to our character, making the animation process much more comfortable.",[29,2131],{},"\nFor this type of character, the IK will work best on the legs and arms.",[12,2134,2135],{},"We start by selecting the character’s root object and adding an IK Manager component. With this component, we create and control our IK. Clicking ‘add to list’ presents 3 IK solver options, each using a different algorithm to calculate bones’ position.",[12,2137,2138,2139,2141,2142,2145,2146,2148,2149,2151,2152,2154],{},"For this character, we will use the Limb IK solver – a standard two bone Solver that is ideal for posing joints such as arms and legs.",[29,2140],{},"\nSelecting this IK solver will create a new game object. I renamed it to ",[25,2143,2144],{},"Hand-F-IK",", as I want it to control the Front arm bones. We drag the Front hand bone to the Effector field. ",[29,2147],{},"\nThe Effector is the bone that the rest of the bones be calculated based on its position.",[29,2150],{},"\nClicking on Create Target will create our IK.",[29,2153],{},"\nThe Target is what we use to animate the IK – the Solver will try to reposition the Effector where the Target is.",[12,2156,2157,2158,2160],{},"The arm bends in the wrong direction. We can change that by checking the Flip checkbox. Since the hand bone is used as an Effector, we can’t rotate it as long as the Constrain Rotation box is checked. Once unchecked, we can adjust the hand rotation to match the arm’s movement.",[29,2159],{},"\nWe repeat the same process for the other arm and legs.",[468,2162,2164],{"gif":2163},"f5HkNTrU1dQV7prbbj","\nAnimating a rigged 2D character inside Unity.\n",[12,2166,2167,2168,2170],{},"By attaching an animator controller with a new animation, we are now ready to animate! ",[29,2169],{},"\nDon’t forget to enable keyframe recording before starting animating.",[2172,2173],"hr",{},[12,2175,2176],{},"In the next part, we will add a new skin to the character, making a swappable rig that uses the same bones and animation keyframes.",{"title":71,"searchDepth":115,"depth":115,"links":2178},[2179,2180,2181,2182],{"id":1949,"depth":100,"text":1950},{"id":1966,"depth":100,"text":1967},{"id":2001,"depth":100,"text":2002},{"id":2122,"depth":100,"text":2123},{"480w":2184,"960w":2185},"\u002Fposts\u002F2020\u002F12-07\u002Funity-2d-animation-rig-bones-480w.jpg","\u002Fposts\u002F2020\u002F12-07\u002Funity-2d-animation-rig-bones-960w.jpg","2020-12-07","We will create a 2D Skeletal Animation with complete bones & rig.",{},"\u002Fposts\u002F2020\u002F12\u002Funity-2d-animation-part-1",{"title":1936,"description":2187},"posts\u002F2020\u002F12\u002Funity-2d-animation-part-1",[1917,1918,1919],"k4LkNtp9_wU","AlyTdwMDZDAy-Y4KMKRZ1rTDVWjFIGEYaCzEZ05bDPo","unity-2d-animation-part-1",{"id":2197,"title":2198,"author":1937,"body":2199,"category":1904,"cover":2309,"date":2312,"description":2313,"extension":1910,"meta":2314,"navigation":165,"path":2315,"seo":2316,"series":1914,"stem":2317,"tags":2318,"youtube":2319,"youtubeRange":1921,"__hash__":2320,"slug":2321},"posts\u002Fposts\u002F2020\u002F12\u002Funity-2d-animation-part-2.md","Skin Swapping",{"type":9,"value":2200,"toc":2305},[2201,2207,2210,2213,2217,2226,2231,2234,2237,2240,2242,2246,2258,2263,2266,2269,2272,2274,2283,2289,2294,2300,2302],[12,2202,2203,2204,2206],{},"Skeletal Rigs offer many advantages, but swappable rigs, also known as skins, is probably one of its best.",[29,2205],{},"\nWith skins, we can apply the same rig and animations on different characters. Either for creating a new character, or changing the looks of an exiting one.",[12,2208,2209],{},"By the end of this tutorial, we will have various characters reusing the existing bones and meshes we created in the previous part.",[16,2211,1946],{"href":2212,"title":19},"https:\u002F\u002Fgithub.com\u002Fnotslot\u002Ftutorial-2d-anim-character\u002Freleases\u002Fdownload\u002Fv1.0\u002FUnity.2D.Animation.Part.2.zip",[57,2214,2216],{"id":2215},"psb-and-rigging","PSB and Rigging",[12,2218,2219,2220,2222,2223,2225],{},"To create our sprite-sheet, I recommend using the PSB format to automates processes that otherwise we had to do manually.",[29,2221],{},"\nFor example, when using a PSB file, we can place all swappable sprites under the same file, creating a pool of accessible sprites.",[29,2224],{},"\nWe place the same body parts from different skins under one group. As I will explain ahead, the groups will have a crucial role as soon as we convert them into Categories.",[1981,2227,2230],{"src":2228,"alt":2229},"\u002Fposts\u002F2020\u002F12-14\u002Funity-2d-animation-6.jpg","Unity 2D Animation – phtoshop file with skins","\nPhotoshop hierarchy for multiple character variants.\n",[12,2232,2233],{},"After placing the file in our project, we go to the Skinning Editor and use the rig we created in the previous video. We can easily duplicate rigs from one sprite-sheet to another using the Copy and Paste options.",[12,2235,2236],{},"The bones won’t influence our new sprites until we explicitly connect them. Going to the Sprite tab at the Visibility window, we can select the new sprites and attach them to their bones.",[12,2238,2239],{},"We must also add the Geometry and Weights manually. Use the Auto Geometry option and make sure to tick the Weights checkbox.",[54,2241],{},[57,2243,2245],{"id":2244},"categories-and-labels","Categories and Labels",[12,2247,2248,2249,2251,2252,2254,2255,2257],{},"We want Unity to recognize the different skins, and for that, we need to create Categories and Labels at the Visibility window.",[29,2250],{},"\nA Category is a placeholder for a sprite. We can choose which Label, and therefore Sprite, is active for a Category in a given moment.",[29,2253],{},"\nBy placing our layers under groups in our PSB file, we can easily convert them into Categories and Labels.",[29,2256],{},"\nSelect all groups, right-click on Category and use the ‘Convert Group to Category.’",[1981,2259,2262],{"src":2260,"alt":2261},"\u002Fposts\u002F2020\u002F12-14\u002Funity-2d-animation-7.jpg","Unity 2D Animation – cateogires and labels","\nSprite Editor – listing of categories and labels.\n",[12,2264,2265],{},"You can see how it added a Lable section next to the sprites. We need to define a Label for any sprite we intend to use. This way, we could swap them by code during runtime.",[12,2267,2268],{},"Once we finish, click apply and add our character to the scene. Add an IK to the limbs, as we did in the previous video.",[12,2270,2271],{},"Using the PSB file to create the Categories and Labels generates components for the character automatically.",[479,2273],{},[12,2275,2276,2277,2279,2280,91],{},"At the character’s root, we have the Sprite Library component – which contains the Categories and Labels of the character.",[29,2278],{},"\nIf you use a PNG instead of PSB, you should manually create a Sprite Library Asset from the menu ",[25,2281,2282],{},"Assets > Create > 2D > Sprite Library Asset",[12,2284,2285,2286,2288],{},"At the character’s sprites, we have the Sprite Resolver component.",[29,2287],{},"\nThis component pulls information from the Sprite Library Asset and visually represents to us our Labels. Here we can select the desired Lable to render.\nWe can also switch the displayed Sprite on each frame at run time with frame-by-frame animation.",[1981,2290,2293],{"src":2291,"alt":2292},"\u002Fposts\u002F2020\u002F12-14\u002Funity-2d-animation-8.jpg","Unity 2D Animation – sprite resolver","\nSprite Resolver component.\n",[12,2295,2296,2297,2299],{},"I created a prefab with the base skin and made variants from it for each skin.",[29,2298],{},"\nAnd here it is! Three characters with different skins, using the same rig and animations.",[2172,2301],{},[12,2303,2304],{},"In the next part, we will create scripts to swap sprites, inject custom sprites, replace skins as a whole, and finally create a mixer to create various characters.",{"title":71,"searchDepth":115,"depth":115,"links":2306},[2307,2308],{"id":2215,"depth":100,"text":2216},{"id":2244,"depth":100,"text":2245},{"480w":2310,"960w":2311},"\u002Fposts\u002F2020\u002F12-14\u002Funity-2d-animation-skin-swap-480w.jpg","\u002Fposts\u002F2020\u002F12-14\u002Funity-2d-animation-skin-swap-960w.jpg","2020-12-14","We will create a swapabbles skins retaining the same rig & animations.",{},"\u002Fposts\u002F2020\u002F12\u002Funity-2d-animation-part-2",{"title":2198,"description":2313},"posts\u002F2020\u002F12\u002Funity-2d-animation-part-2",[1917,1918,1919],"hoKKFQ2PWMw","VpSBOenggXSKGTplCn0n2XYbExXUEC_T-YC-fGpIT6U","unity-2d-animation-part-2",{"id":5,"title":6,"author":7,"body":2323,"category":1904,"cover":3871,"date":1908,"description":1909,"extension":1910,"meta":3872,"navigation":165,"path":1912,"seo":3873,"series":1914,"stem":1915,"tags":3874,"youtube":1920,"youtubeRange":1921,"__hash__":1922,"slug":1923},{"type":9,"value":2324,"toc":3865},[2325,2327,2329,2335,2347,2349,2351,2353,2635,2643,2645,2649,2651,2653,2659,2717,2719,2721,2725,2729,2881,2883,2885,2889,2891,2895,2897,2949,2953,3079,3081,3083,3089,3195,3215,3529,3535,3537,3831,3849,3851,3855,3861,3863],[12,2326,14],{},[16,2328,20],{"href":18,"title":19},[12,2330,23,2331,2333],{},[25,2332,27],{},[29,2334],{},[32,2336,2337,2339,2345],{},[35,2338,37],{},[35,2340,40,2341,45,2343,49],{},[42,2342,44],{},[42,2344,48],{},[35,2346,52],{},[54,2348],{},[57,2350,60],{"id":59},[12,2352,63],{},[65,2354,2355],{"className":67,"code":68,"filename":69,"language":70,"meta":71,"style":71},[73,2356,2357,2369,2381,2389,2409,2421,2425,2437,2441,2445,2453,2467,2471,2479,2493,2497,2505,2519,2523,2527,2539,2543,2547,2557,2561,2571,2583,2601,2611,2615,2623,2627,2631],{"__ignoreMap":71},[76,2358,2359,2361,2363,2365,2367],{"class":78,"line":79},[76,2360,83],{"class":82},[76,2362,87],{"class":86},[76,2364,91],{"class":90},[76,2366,94],{"class":86},[76,2368,97],{"class":90},[76,2370,2371,2373,2375,2377,2379],{"class":78,"line":100},[76,2372,83],{"class":82},[76,2374,105],{"class":86},[76,2376,91],{"class":90},[76,2378,110],{"class":86},[76,2380,97],{"class":90},[76,2382,2383,2385,2387],{"class":78,"line":115},[76,2384,83],{"class":82},[76,2386,120],{"class":86},[76,2388,97],{"class":90},[76,2390,2391,2393,2395,2397,2399,2401,2403,2405,2407],{"class":78,"line":125},[76,2392,83],{"class":82},[76,2394,120],{"class":86},[76,2396,91],{"class":90},[76,2398,134],{"class":86},[76,2400,91],{"class":90},[76,2402,139],{"class":86},[76,2404,91],{"class":90},[76,2406,144],{"class":86},[76,2408,97],{"class":90},[76,2410,2411,2413,2415,2417,2419],{"class":78,"line":149},[76,2412,83],{"class":82},[76,2414,120],{"class":86},[76,2416,91],{"class":90},[76,2418,139],{"class":86},[76,2420,97],{"class":90},[76,2422,2423],{"class":78,"line":162},[76,2424,166],{"emptyLinePlaceholder":165},[76,2426,2427,2429,2431,2433,2435],{"class":78,"line":169},[76,2428,172],{"class":82},[76,2430,175],{"class":82},[76,2432,178],{"class":86},[76,2434,181],{"class":90},[76,2436,184],{"class":86},[76,2438,2439],{"class":78,"line":187},[76,2440,190],{"class":90},[76,2442,2443],{"class":78,"line":193},[76,2444,166],{"emptyLinePlaceholder":165},[76,2446,2447,2449,2451],{"class":78,"line":198},[76,2448,201],{"class":90},[76,2450,204],{"class":86},[76,2452,207],{"class":90},[76,2454,2455,2457,2459,2461,2463,2465],{"class":78,"line":210},[76,2456,213],{"class":82},[76,2458,216],{"class":86},[76,2460,219],{"class":86},[76,2462,222],{"class":82},[76,2464,225],{"class":82},[76,2466,97],{"class":90},[76,2468,2469],{"class":78,"line":230},[76,2470,166],{"emptyLinePlaceholder":165},[76,2472,2473,2475,2477],{"class":78,"line":235},[76,2474,201],{"class":90},[76,2476,204],{"class":86},[76,2478,207],{"class":90},[76,2480,2481,2483,2485,2487,2489,2491],{"class":78,"line":244},[76,2482,213],{"class":82},[76,2484,249],{"class":86},[76,2486,252],{"class":86},[76,2488,222],{"class":82},[76,2490,225],{"class":82},[76,2492,97],{"class":90},[76,2494,2495],{"class":78,"line":261},[76,2496,166],{"emptyLinePlaceholder":165},[76,2498,2499,2501,2503],{"class":78,"line":266},[76,2500,201],{"class":90},[76,2502,204],{"class":86},[76,2504,207],{"class":90},[76,2506,2507,2509,2511,2513,2515,2517],{"class":78,"line":275},[76,2508,213],{"class":82},[76,2510,280],{"class":82},[76,2512,283],{"class":86},[76,2514,222],{"class":82},[76,2516,225],{"class":82},[76,2518,97],{"class":90},[76,2520,2521],{"class":78,"line":292},[76,2522,166],{"emptyLinePlaceholder":165},[76,2524,2525],{"class":78,"line":297},[76,2526,166],{"emptyLinePlaceholder":165},[76,2528,2529,2531,2533,2535,2537],{"class":78,"line":302},[76,2530,213],{"class":82},[76,2532,307],{"class":86},[76,2534,310],{"class":86},[76,2536,313],{"class":82},[76,2538,316],{"class":90},[76,2540,2541],{"class":78,"line":319},[76,2542,166],{"emptyLinePlaceholder":165},[76,2544,2545],{"class":78,"line":324},[76,2546,166],{"emptyLinePlaceholder":165},[76,2548,2549,2551,2553,2555],{"class":78,"line":329},[76,2550,332],{"class":82},[76,2552,335],{"class":82},[76,2554,338],{"class":86},[76,2556,341],{"class":90},[76,2558,2559],{"class":78,"line":344},[76,2560,347],{"class":90},[76,2562,2563,2565,2567,2569],{"class":78,"line":350},[76,2564,353],{"class":82},[76,2566,356],{"class":90},[76,2568,359],{"class":86},[76,2570,362],{"class":82},[76,2572,2573,2575,2577,2579,2581],{"class":78,"line":365},[76,2574,368],{"class":90},[76,2576,371],{"class":86},[76,2578,374],{"class":90},[76,2580,377],{"class":86},[76,2582,380],{"class":90},[76,2584,2585,2587,2589,2591,2593,2595,2597,2599],{"class":78,"line":383},[76,2586,386],{"class":82},[76,2588,389],{"class":86},[76,2590,222],{"class":82},[76,2592,394],{"class":90},[76,2594,397],{"class":86},[76,2596,400],{"class":90},[76,2598,404],{"class":403},[76,2600,407],{"class":90},[76,2602,2603,2605,2607,2609],{"class":78,"line":410},[76,2604,353],{"class":82},[76,2606,415],{"class":86},[76,2608,222],{"class":82},[76,2610,420],{"class":90},[76,2612,2613],{"class":78,"line":423},[76,2614,166],{"emptyLinePlaceholder":165},[76,2616,2617,2619,2621],{"class":78,"line":428},[76,2618,431],{"class":90},[76,2620,434],{"class":86},[76,2622,437],{"class":90},[76,2624,2625],{"class":78,"line":440},[76,2626,443],{"class":90},[76,2628,2629],{"class":78,"line":446},[76,2630,166],{"emptyLinePlaceholder":165},[76,2632,2633],{"class":78,"line":451},[76,2634,454],{"class":90},[12,2636,457,2637,460,2639,463,2641,466],{},[29,2638],{},[29,2640],{},[25,2642,434],{},[468,2644,471],{"gif":470},[12,2646,474,2647,477],{},[29,2648],{},[479,2650],{},[57,2652,484],{"id":483},[12,2654,487,2655,490,2657,494],{},[29,2656],{},[73,2658,493],{},[65,2660,2661],{"className":67,"code":497,"filename":69,"language":70,"meta":71,"style":71},[73,2662,2663,2679,2683,2697,2705,2713],{"__ignoreMap":71},[76,2664,2665,2667,2669,2671,2673,2675,2677],{"class":78,"line":79},[76,2666,172],{"class":82},[76,2668,335],{"class":82},[76,2670,508],{"class":86},[76,2672,511],{"class":90},[76,2674,514],{"class":86},[76,2676,517],{"class":86},[76,2678,520],{"class":90},[76,2680,2681],{"class":78,"line":100},[76,2682,190],{"class":90},[76,2684,2685,2687,2689,2691,2693,2695],{"class":78,"line":115},[76,2686,529],{"class":82},[76,2688,280],{"class":82},[76,2690,534],{"class":86},[76,2692,222],{"class":82},[76,2694,540],{"class":539},[76,2696,97],{"class":90},[76,2698,2699,2701,2703],{"class":78,"line":125},[76,2700,547],{"class":90},[76,2702,550],{"class":86},[76,2704,553],{"class":90},[76,2706,2707,2709,2711],{"class":78,"line":149},[76,2708,558],{"class":90},[76,2710,434],{"class":86},[76,2712,563],{"class":90},[76,2714,2715],{"class":78,"line":162},[76,2716,454],{"class":90},[12,2718,570],{},[468,2720,574],{"gif":573},[12,2722,577,2723,580],{},[29,2724],{},[12,2726,583,2727,586],{},[29,2728],{},[65,2730,2731],{"className":67,"code":589,"filename":69,"language":70,"meta":71,"style":71},[73,2732,2733,2749,2753,2757,2771,2779,2787,2803,2823,2831,2839,2843,2847,2861,2869,2877],{"__ignoreMap":71},[76,2734,2735,2737,2739,2741,2743,2745,2747],{"class":78,"line":79},[76,2736,172],{"class":82},[76,2738,335],{"class":82},[76,2740,508],{"class":86},[76,2742,511],{"class":90},[76,2744,514],{"class":86},[76,2746,517],{"class":86},[76,2748,520],{"class":90},[76,2750,2751],{"class":78,"line":100},[76,2752,190],{"class":90},[76,2754,2755],{"class":78,"line":115},[76,2756,617],{"class":616},[76,2758,2759,2761,2763,2765,2767,2769],{"class":78,"line":125},[76,2760,622],{"class":82},[76,2762,625],{"class":86},[76,2764,222],{"class":82},[76,2766,630],{"class":90},[76,2768,633],{"class":86},[76,2770,380],{"class":90},[76,2772,2773,2775,2777],{"class":78,"line":149},[76,2774,640],{"class":86},[76,2776,643],{"class":86},[76,2778,362],{"class":82},[76,2780,2781,2783,2785],{"class":78,"line":162},[76,2782,650],{"class":90},[76,2784,653],{"class":86},[76,2786,656],{"class":90},[76,2788,2789,2791,2793,2795,2797,2799,2801],{"class":78,"line":169},[76,2790,661],{"class":86},[76,2792,356],{"class":90},[76,2794,666],{"class":86},[76,2796,222],{"class":82},[76,2798,671],{"class":90},[76,2800,674],{"class":86},[76,2802,380],{"class":90},[76,2804,2805,2807,2809,2811,2813,2815,2817,2819,2821],{"class":78,"line":187},[76,2806,681],{"class":86},[76,2808,684],{"class":90},[76,2810,687],{"class":86},[76,2812,690],{"class":90},[76,2814,693],{"class":86},[76,2816,222],{"class":82},[76,2818,671],{"class":90},[76,2820,700],{"class":86},[76,2822,380],{"class":90},[76,2824,2825,2827,2829],{"class":78,"line":193},[76,2826,707],{"class":90},[76,2828,710],{"class":86},[76,2830,713],{"class":90},[76,2832,2833,2835,2837],{"class":78,"line":198},[76,2834,707],{"class":90},[76,2836,720],{"class":86},[76,2838,723],{"class":90},[76,2840,2841],{"class":78,"line":210},[76,2842,166],{"emptyLinePlaceholder":165},[76,2844,2845],{"class":78,"line":230},[76,2846,732],{"class":616},[76,2848,2849,2851,2853,2855,2857,2859],{"class":78,"line":235},[76,2850,529],{"class":82},[76,2852,280],{"class":82},[76,2854,534],{"class":86},[76,2856,222],{"class":82},[76,2858,540],{"class":539},[76,2860,97],{"class":90},[76,2862,2863,2865,2867],{"class":78,"line":244},[76,2864,547],{"class":90},[76,2866,550],{"class":86},[76,2868,553],{"class":90},[76,2870,2871,2873,2875],{"class":78,"line":261},[76,2872,558],{"class":90},[76,2874,434],{"class":86},[76,2876,563],{"class":90},[76,2878,2879],{"class":78,"line":266},[76,2880,454],{"class":90},[12,2882,769],{},[57,2884,773],{"id":772},[12,2886,776,2887,779],{},[29,2888],{},[468,2890,783],{"gif":782},[12,2892,786,2893,790],{},[73,2894,789],{},[12,2896,793],{},[65,2898,2899],{"className":67,"code":796,"language":70,"meta":71,"style":71},[73,2900,2901,2905,2925,2929,2933],{"__ignoreMap":71},[76,2902,2903],{"class":78,"line":79},[76,2904,803],{"class":616},[76,2906,2907,2909,2911,2913,2915,2917,2919,2921,2923],{"class":78,"line":100},[76,2908,83],{"class":82},[76,2910,120],{"class":86},[76,2912,91],{"class":90},[76,2914,134],{"class":86},[76,2916,91],{"class":90},[76,2918,139],{"class":86},[76,2920,91],{"class":90},[76,2922,144],{"class":86},[76,2924,97],{"class":90},[76,2926,2927],{"class":78,"line":115},[76,2928,166],{"emptyLinePlaceholder":165},[76,2930,2931],{"class":78,"line":125},[76,2932,832],{"class":616},[76,2934,2935,2937,2939,2941,2943,2945,2947],{"class":78,"line":149},[76,2936,83],{"class":82},[76,2938,120],{"class":86},[76,2940,91],{"class":90},[76,2942,139],{"class":86},[76,2944,91],{"class":90},[76,2946,144],{"class":86},[76,2948,97],{"class":90},[12,2950,851,2951,854],{},[29,2952],{},[65,2954,2955],{"className":67,"code":857,"filename":858,"language":70,"meta":71,"style":71},[73,2956,2957,2965,2985,2989,3001,3005,3009,3017,3031,3035,3039,3055,3059,3067,3071,3075],{"__ignoreMap":71},[76,2958,2959,2961,2963],{"class":78,"line":79},[76,2960,83],{"class":82},[76,2962,120],{"class":86},[76,2964,97],{"class":90},[76,2966,2967,2969,2971,2973,2975,2977,2979,2981,2983],{"class":78,"line":100},[76,2968,83],{"class":82},[76,2970,120],{"class":86},[76,2972,91],{"class":90},[76,2974,134],{"class":86},[76,2976,91],{"class":90},[76,2978,139],{"class":86},[76,2980,91],{"class":90},[76,2982,144],{"class":86},[76,2984,97],{"class":90},[76,2986,2987],{"class":78,"line":115},[76,2988,166],{"emptyLinePlaceholder":165},[76,2990,2991,2993,2995,2997,2999],{"class":78,"line":125},[76,2992,172],{"class":82},[76,2994,175],{"class":82},[76,2996,901],{"class":86},[76,2998,181],{"class":90},[76,3000,184],{"class":86},[76,3002,3003],{"class":78,"line":149},[76,3004,190],{"class":90},[76,3006,3007],{"class":78,"line":162},[76,3008,166],{"emptyLinePlaceholder":165},[76,3010,3011,3013,3015],{"class":78,"line":169},[76,3012,201],{"class":90},[76,3014,204],{"class":86},[76,3016,207],{"class":90},[76,3018,3019,3021,3023,3025,3027,3029],{"class":78,"line":187},[76,3020,213],{"class":82},[76,3022,216],{"class":86},[76,3024,219],{"class":86},[76,3026,222],{"class":82},[76,3028,225],{"class":82},[76,3030,97],{"class":90},[76,3032,3033],{"class":78,"line":193},[76,3034,166],{"emptyLinePlaceholder":165},[76,3036,3037],{"class":78,"line":198},[76,3038,166],{"emptyLinePlaceholder":165},[76,3040,3041,3043,3045,3047,3049,3051,3053],{"class":78,"line":210},[76,3042,332],{"class":82},[76,3044,335],{"class":82},[76,3046,952],{"class":86},[76,3048,511],{"class":90},[76,3050,957],{"class":86},[76,3052,960],{"class":86},[76,3054,520],{"class":90},[76,3056,3057],{"class":78,"line":230},[76,3058,347],{"class":90},[76,3060,3061,3063,3065],{"class":78,"line":235},[76,3062,971],{"class":90},[76,3064,974],{"class":82},[76,3066,977],{"class":90},[76,3068,3069],{"class":78,"line":244},[76,3070,443],{"class":90},[76,3072,3073],{"class":78,"line":261},[76,3074,166],{"emptyLinePlaceholder":165},[76,3076,3077],{"class":78,"line":266},[76,3078,454],{"class":90},[12,3080,992],{},[57,3082,996],{"id":995},[12,3084,999,3085,1002,3087,494],{},[29,3086],{},[73,3088,1005],{},[65,3090,3091],{"className":67,"code":1008,"filename":1009,"language":70,"meta":71,"style":71},[73,3092,3093,3101,3121,3125,3133,3141,3145,3149,3159,3163,3173,3177,3187,3191],{"__ignoreMap":71},[76,3094,3095,3097,3099],{"class":78,"line":79},[76,3096,83],{"class":82},[76,3098,87],{"class":86},[76,3100,97],{"class":90},[76,3102,3103,3105,3107,3109,3111,3113,3115,3117,3119],{"class":78,"line":100},[76,3104,83],{"class":82},[76,3106,120],{"class":86},[76,3108,91],{"class":90},[76,3110,134],{"class":86},[76,3112,91],{"class":90},[76,3114,139],{"class":86},[76,3116,91],{"class":90},[76,3118,144],{"class":86},[76,3120,97],{"class":90},[76,3122,3123],{"class":78,"line":115},[76,3124,166],{"emptyLinePlaceholder":165},[76,3126,3127,3129,3131],{"class":78,"line":125},[76,3128,1048],{"class":90},[76,3130,1051],{"class":86},[76,3132,207],{"class":90},[76,3134,3135,3137,3139],{"class":78,"line":149},[76,3136,172],{"class":82},[76,3138,1060],{"class":82},[76,3140,1063],{"class":86},[76,3142,3143],{"class":78,"line":162},[76,3144,190],{"class":90},[76,3146,3147],{"class":78,"line":169},[76,3148,166],{"emptyLinePlaceholder":165},[76,3150,3151,3153,3155,3157],{"class":78,"line":187},[76,3152,332],{"class":82},[76,3154,280],{"class":82},[76,3156,1080],{"class":86},[76,3158,97],{"class":90},[76,3160,3161],{"class":78,"line":193},[76,3162,166],{"emptyLinePlaceholder":165},[76,3164,3165,3167,3169,3171],{"class":78,"line":198},[76,3166,332],{"class":82},[76,3168,280],{"class":82},[76,3170,1095],{"class":86},[76,3172,97],{"class":90},[76,3174,3175],{"class":78,"line":210},[76,3176,166],{"emptyLinePlaceholder":165},[76,3178,3179,3181,3183,3185],{"class":78,"line":230},[76,3180,332],{"class":82},[76,3182,249],{"class":86},[76,3184,1110],{"class":86},[76,3186,97],{"class":90},[76,3188,3189],{"class":78,"line":235},[76,3190,166],{"emptyLinePlaceholder":165},[76,3192,3193],{"class":78,"line":244},[76,3194,454],{"class":90},[12,3196,1123,3197,1126,3199,1129,3201,1132,3203,1135,3205,1138,3207,1141,3209,1144,3211,1147,3213,91],{},[73,3198,789],{},[29,3200],{},[73,3202,1005],{},[29,3204],{},[73,3206,1005],{},[29,3208],{},[29,3210],{},[29,3212],{},[73,3214,434],{},[65,3216,3217],{"className":67,"code":1152,"filename":1153,"language":70,"meta":71,"style":71},[73,3218,3219,3235,3243,3255,3259,3271,3275,3279,3287,3297,3301,3309,3319,3323,3327,3351,3355,3359,3367,3371,3375,3407,3421,3425,3447,3455,3459,3463,3471,3475,3479,3491,3495,3505,3513,3517,3521,3525],{"__ignoreMap":71},[76,3220,3221,3223,3225,3227,3229,3231,3233],{"class":78,"line":79},[76,3222,83],{"class":82},[76,3224,87],{"class":86},[76,3226,91],{"class":90},[76,3228,110],{"class":86},[76,3230,91],{"class":90},[76,3232,1170],{"class":86},[76,3234,97],{"class":90},[76,3236,3237,3239,3241],{"class":78,"line":100},[76,3238,83],{"class":82},[76,3240,120],{"class":86},[76,3242,97],{"class":90},[76,3244,3245,3247,3249,3251,3253],{"class":78,"line":115},[76,3246,83],{"class":82},[76,3248,120],{"class":86},[76,3250,91],{"class":90},[76,3252,1191],{"class":86},[76,3254,97],{"class":90},[76,3256,3257],{"class":78,"line":125},[76,3258,166],{"emptyLinePlaceholder":165},[76,3260,3261,3263,3265,3267,3269],{"class":78,"line":149},[76,3262,172],{"class":82},[76,3264,175],{"class":82},[76,3266,1206],{"class":86},[76,3268,181],{"class":90},[76,3270,184],{"class":86},[76,3272,3273],{"class":78,"line":162},[76,3274,190],{"class":90},[76,3276,3277],{"class":78,"line":169},[76,3278,166],{"emptyLinePlaceholder":165},[76,3280,3281,3283,3285],{"class":78,"line":187},[76,3282,201],{"class":90},[76,3284,204],{"class":86},[76,3286,207],{"class":90},[76,3288,3289,3291,3293,3295],{"class":78,"line":193},[76,3290,213],{"class":82},[76,3292,1233],{"class":86},[76,3294,1236],{"class":86},[76,3296,97],{"class":90},[76,3298,3299],{"class":78,"line":198},[76,3300,166],{"emptyLinePlaceholder":165},[76,3302,3303,3305,3307],{"class":78,"line":210},[76,3304,201],{"class":90},[76,3306,204],{"class":86},[76,3308,207],{"class":90},[76,3310,3311,3313,3315,3317],{"class":78,"line":230},[76,3312,213],{"class":82},[76,3314,1257],{"class":86},[76,3316,1260],{"class":86},[76,3318,97],{"class":90},[76,3320,3321],{"class":78,"line":235},[76,3322,166],{"emptyLinePlaceholder":165},[76,3324,3325],{"class":78,"line":244},[76,3326,166],{"emptyLinePlaceholder":165},[76,3328,3329,3331,3333,3335,3337,3339,3341,3343,3345,3347,3349],{"class":78,"line":261},[76,3330,332],{"class":82},[76,3332,335],{"class":82},[76,3334,1279],{"class":86},[76,3336,511],{"class":90},[76,3338,1005],{"class":86},[76,3340,1286],{"class":86},[76,3342,1289],{"class":90},[76,3344,1292],{"class":82},[76,3346,356],{"class":90},[76,3348,359],{"class":86},[76,3350,520],{"class":90},[76,3352,3353],{"class":78,"line":266},[76,3354,347],{"class":90},[76,3356,3357],{"class":78,"line":275},[76,3358,1307],{"class":616},[76,3360,3361,3363,3365],{"class":78,"line":292},[76,3362,1312],{"class":90},[76,3364,974],{"class":82},[76,3366,1317],{"class":90},[76,3368,3369],{"class":78,"line":297},[76,3370,166],{"emptyLinePlaceholder":165},[76,3372,3373],{"class":78,"line":302},[76,3374,1326],{"class":616},[76,3376,3377,3379,3381,3383,3385,3387,3389,3391,3393,3395,3397,3399,3401,3403,3405],{"class":78,"line":319},[76,3378,1331],{"class":86},[76,3380,684],{"class":90},[76,3382,1336],{"class":86},[76,3384,91],{"class":90},[76,3386,1341],{"class":86},[76,3388,690],{"class":90},[76,3390,1346],{"class":86},[76,3392,222],{"class":82},[76,3394,1351],{"class":82},[76,3396,1354],{"class":86},[76,3398,684],{"class":90},[76,3400,1336],{"class":86},[76,3402,91],{"class":90},[76,3404,1341],{"class":86},[76,3406,1365],{"class":90},[76,3408,3409,3411,3413,3415,3417,3419],{"class":78,"line":324},[76,3410,1370],{"class":82},[76,3412,1373],{"class":90},[76,3414,1292],{"class":82},[76,3416,415],{"class":86},[76,3418,1380],{"class":82},[76,3420,1383],{"class":90},[76,3422,3423],{"class":78,"line":329},[76,3424,1388],{"class":90},[76,3426,3427,3429,3431,3433,3435,3437,3439,3441,3443,3445],{"class":78,"line":344},[76,3428,1393],{"class":86},[76,3430,91],{"class":90},[76,3432,1341],{"class":86},[76,3434,1400],{"class":86},[76,3436,222],{"class":82},[76,3438,1351],{"class":82},[76,3440,1257],{"class":86},[76,3442,91],{"class":90},[76,3444,1341],{"class":86},[76,3446,1413],{"class":90},[76,3448,3449,3451,3453],{"class":78,"line":350},[76,3450,1418],{"class":90},[76,3452,1421],{"class":86},[76,3454,1424],{"class":90},[76,3456,3457],{"class":78,"line":365},[76,3458,1429],{"class":90},[76,3460,3461],{"class":78,"line":383},[76,3462,166],{"emptyLinePlaceholder":165},[76,3464,3465,3467,3469],{"class":78,"line":410},[76,3466,1438],{"class":90},[76,3468,974],{"class":82},[76,3470,1443],{"class":90},[76,3472,3473],{"class":78,"line":423},[76,3474,166],{"emptyLinePlaceholder":165},[76,3476,3477],{"class":78,"line":428},[76,3478,1452],{"class":616},[76,3480,3481,3483,3485,3487,3489],{"class":78,"line":440},[76,3482,1457],{"class":90},[76,3484,1460],{"class":86},[76,3486,400],{"class":90},[76,3488,1465],{"class":86},[76,3490,1468],{"class":82},[76,3492,3493],{"class":78,"line":446},[76,3494,1388],{"class":90},[76,3496,3497,3499,3501,3503],{"class":78,"line":451},[76,3498,1477],{"class":82},[76,3500,415],{"class":86},[76,3502,222],{"class":82},[76,3504,1484],{"class":90},[76,3506,3507,3509,3511],{"class":78,"line":1487},[76,3508,1490],{"class":90},[76,3510,434],{"class":86},[76,3512,1495],{"class":90},[76,3514,3515],{"class":78,"line":1498},[76,3516,1501],{"class":90},[76,3518,3519],{"class":78,"line":1504},[76,3520,443],{"class":90},[76,3522,3523],{"class":78,"line":1509},[76,3524,166],{"emptyLinePlaceholder":165},[76,3526,3527],{"class":78,"line":1514},[76,3528,454],{"class":90},[12,3530,1519,3531,1523,3533,1526],{},[73,3532,1522],{},[29,3534],{},[12,3536,1529],{},[65,3538,3539],{"className":67,"code":1532,"filename":1533,"language":70,"meta":71,"style":71},[73,3540,3541,3553,3561,3581,3585,3597,3601,3605,3613,3627,3631,3639,3653,3657,3665,3681,3685,3689,3701,3705,3709,3719,3723,3737,3743,3747,3751,3755,3771,3775,3791,3799,3811,3819,3823,3827],{"__ignoreMap":71},[76,3542,3543,3545,3547,3549,3551],{"class":78,"line":79},[76,3544,83],{"class":82},[76,3546,87],{"class":86},[76,3548,91],{"class":90},[76,3550,94],{"class":86},[76,3552,97],{"class":90},[76,3554,3555,3557,3559],{"class":78,"line":100},[76,3556,83],{"class":82},[76,3558,120],{"class":86},[76,3560,97],{"class":90},[76,3562,3563,3565,3567,3569,3571,3573,3575,3577,3579],{"class":78,"line":115},[76,3564,83],{"class":82},[76,3566,120],{"class":86},[76,3568,91],{"class":90},[76,3570,134],{"class":86},[76,3572,91],{"class":90},[76,3574,139],{"class":86},[76,3576,91],{"class":90},[76,3578,144],{"class":86},[76,3580,97],{"class":90},[76,3582,3583],{"class":78,"line":125},[76,3584,166],{"emptyLinePlaceholder":165},[76,3586,3587,3589,3591,3593,3595],{"class":78,"line":149},[76,3588,172],{"class":82},[76,3590,175],{"class":82},[76,3592,1588],{"class":86},[76,3594,181],{"class":90},[76,3596,184],{"class":86},[76,3598,3599],{"class":78,"line":162},[76,3600,190],{"class":90},[76,3602,3603],{"class":78,"line":169},[76,3604,166],{"emptyLinePlaceholder":165},[76,3606,3607,3609,3611],{"class":78,"line":187},[76,3608,201],{"class":90},[76,3610,204],{"class":86},[76,3612,207],{"class":90},[76,3614,3615,3617,3619,3621,3623,3625],{"class":78,"line":193},[76,3616,213],{"class":82},[76,3618,216],{"class":86},[76,3620,219],{"class":86},[76,3622,222],{"class":82},[76,3624,225],{"class":82},[76,3626,97],{"class":90},[76,3628,3629],{"class":78,"line":198},[76,3630,166],{"emptyLinePlaceholder":165},[76,3632,3633,3635,3637],{"class":78,"line":210},[76,3634,201],{"class":90},[76,3636,204],{"class":86},[76,3638,207],{"class":90},[76,3640,3641,3643,3645,3647,3649,3651],{"class":78,"line":230},[76,3642,213],{"class":82},[76,3644,1206],{"class":86},[76,3646,1643],{"class":86},[76,3648,222],{"class":82},[76,3650,225],{"class":82},[76,3652,97],{"class":90},[76,3654,3655],{"class":78,"line":235},[76,3656,166],{"emptyLinePlaceholder":165},[76,3658,3659,3661,3663],{"class":78,"line":244},[76,3660,201],{"class":90},[76,3662,204],{"class":86},[76,3664,207],{"class":90},[76,3666,3667,3669,3671,3673,3675,3677,3679],{"class":78,"line":261},[76,3668,213],{"class":82},[76,3670,1668],{"class":86},[76,3672,356],{"class":90},[76,3674,1673],{"class":86},[76,3676,222],{"class":82},[76,3678,225],{"class":82},[76,3680,97],{"class":90},[76,3682,3683],{"class":78,"line":266},[76,3684,166],{"emptyLinePlaceholder":165},[76,3686,3687],{"class":78,"line":275},[76,3688,166],{"emptyLinePlaceholder":165},[76,3690,3691,3693,3695,3697,3699],{"class":78,"line":292},[76,3692,213],{"class":82},[76,3694,307],{"class":86},[76,3696,310],{"class":86},[76,3698,313],{"class":82},[76,3700,316],{"class":90},[76,3702,3703],{"class":78,"line":297},[76,3704,166],{"emptyLinePlaceholder":165},[76,3706,3707],{"class":78,"line":302},[76,3708,166],{"emptyLinePlaceholder":165},[76,3710,3711,3713,3715,3717],{"class":78,"line":319},[76,3712,213],{"class":82},[76,3714,335],{"class":82},[76,3716,1716],{"class":86},[76,3718,341],{"class":90},[76,3720,3721],{"class":78,"line":324},[76,3722,347],{"class":90},[76,3724,3725,3727,3729,3731,3733,3735],{"class":78,"line":329},[76,3726,1370],{"class":82},[76,3728,1373],{"class":90},[76,3730,1005],{"class":86},[76,3732,1286],{"class":86},[76,3734,1380],{"class":82},[76,3736,1737],{"class":90},[76,3738,3739,3741],{"class":78,"line":344},[76,3740,1742],{"class":86},[76,3742,1745],{"class":90},[76,3744,3745],{"class":78,"line":350},[76,3746,443],{"class":90},[76,3748,3749],{"class":78,"line":365},[76,3750,166],{"emptyLinePlaceholder":165},[76,3752,3753],{"class":78,"line":383},[76,3754,166],{"emptyLinePlaceholder":165},[76,3756,3757,3759,3761,3763,3765,3767,3769],{"class":78,"line":410},[76,3758,213],{"class":82},[76,3760,335],{"class":82},[76,3762,1766],{"class":86},[76,3764,511],{"class":90},[76,3766,1005],{"class":86},[76,3768,1286],{"class":86},[76,3770,520],{"class":90},[76,3772,3773],{"class":78,"line":423},[76,3774,347],{"class":90},[76,3776,3777,3779,3781,3783,3785,3787,3789],{"class":78,"line":428},[76,3778,353],{"class":82},[76,3780,356],{"class":90},[76,3782,359],{"class":86},[76,3784,222],{"class":82},[76,3786,1791],{"class":90},[76,3788,371],{"class":86},[76,3790,1796],{"class":90},[76,3792,3793,3795,3797],{"class":78,"line":440},[76,3794,1801],{"class":90},[76,3796,377],{"class":86},[76,3798,380],{"class":90},[76,3800,3801,3803,3805,3807,3809],{"class":78,"line":446},[76,3802,1810],{"class":86},[76,3804,1813],{"class":86},[76,3806,222],{"class":82},[76,3808,1818],{"class":86},[76,3810,1821],{"class":90},[76,3812,3813,3815,3817],{"class":78,"line":451},[76,3814,1826],{"class":90},[76,3816,1829],{"class":86},[76,3818,1832],{"class":90},[76,3820,3821],{"class":78,"line":1487},[76,3822,443],{"class":90},[76,3824,3825],{"class":78,"line":1498},[76,3826,166],{"emptyLinePlaceholder":165},[76,3828,3829],{"class":78,"line":1504},[76,3830,454],{"class":90},[12,3832,1847,3833,1850,3835,1853,3837,1856,3839,1859,3841,1862,3843,1865,3845,1868,3847,1871],{},[73,3834,1005],{},[29,3836],{},[73,3838,1005],{},[73,3840,1522],{},[29,3842],{},[29,3844],{},[73,3846,1522],{},[29,3848],{},[468,3850,1875],{"gif":1874},[12,3852,1878,3853,1881],{},[73,3854,789],{},[12,3856,1884,3857,1887,3859,1890],{},[73,3858,1522],{},[73,3860,1005],{},[12,3862,1893],{},[1895,3864,1897],{},{"title":71,"searchDepth":115,"depth":115,"links":3866},[3867,3868,3869,3870],{"id":59,"depth":100,"text":60},{"id":483,"depth":100,"text":484},{"id":772,"depth":100,"text":773},{"id":995,"depth":100,"text":996},{"480w":1906,"960w":1907},{},{"title":6,"description":1909},[1917,73,1918,1919],{"id":3876,"authorPage":165,"extension":1928,"meta":3877,"name":3878,"social":3879,"stem":3882,"__hash__":3883},"team\u002Fteam\u002Fnir.yaml",{},"Nir Lahad",{"twitter":3880,"linkedin":3881},"Nirlah","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fnir-lahad-b994675b","team\u002Fnir","XR6GHUplaX0xSjFx9OIVhSL2dd4CVyDFtBi3TRUSr5c",1790297819562]