SkinSystem.lua 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. --[[
  2. 所有的skinDatas, extSkinDatas格式如下
  3. skinDatas =
  4. {
  5. [Enum.SkinSlotType.HeadTop] = {hasValue = boolean, prefabGo = GameObject, pos = Vector3, rot = Quaternion, scale = Vector3, customBindBone = String},
  6. [Enum.SkinSlotType.HeadMiddle] = {hasValue = boolean, prefabGo = GameObject, pos = Vector3, rot = Quaternion, scale = Vector3, customBindBone = String},
  7. [Enum.SkinSlotType.HeadBottom] = {hasValue = boolean, prefabGo = GameObject, pos = Vector3, rot = Quaternion, scale = Vector3, customBindBone = String},
  8. [Enum.SkinSlotType.Cloth] = {hasValue = boolean, prefabGo = GameObject, pos = Vector3, rot = Quaternion, scale = Vector3, customBindBone = String},
  9. [Enum.SkinSlotType.LeftHand] = {hasValue = boolean, prefabGo = GameObject, pos = Vector3, rot = Quaternion, scale = Vector3, customBindBone = String},
  10. [Enum.SkinSlotType.RightHand] = {hasValue = boolean, prefabGo = GameObject, pos = Vector3, rot = Quaternion, scale = Vector3, customBindBone = String},
  11. [Enum.SkinSlotType.BodyBack] = {hasValue = boolean, prefabGo = GameObject, pos = Vector3, rot = Quaternion, scale = Vector3, customBindBone = String},
  12. [Enum.SkinSlotType.HairStyle] = {hasValue = boolean, prefabGo = GameObject, pos = Vector3, rot = Quaternion, scale = Vector3, customBindBone = String},
  13. [Enum.SkinSlotType.Pupil] = {hasValue = boolean, prefabGo = GameObject, pos = Vector3, rot = Quaternion, scale = Vector3, customBindBone = String},
  14. [Enum.SkinSlotType.HairColor] = {hasValue = boolean, uvOffset = Vector2},
  15. [Enum.SkinSlotType.Face] = {hasValue = boolean, prefabGo = GameObject, pos = Vector3, rot = Quaternion, scale = Vector3},
  16. }
  17. hasValue 为 是否位置上设置了值,false则表示该位置上未放置东西
  18. prefabGo 为 prefab资源
  19. pos 为挂载点的相对坐标
  20. rot 为挂载点的相对旋转
  21. scale 为挂载点的相对缩放
  22. customBindBone 为自定义绑定骨骼,可为nil, 不为nil是会覆盖默认绑定骨骼节点
  23. 有的skins, extSkins格式如下
  24. skins =
  25. {
  26. [Enum.SkinSlotType.HeadTop] = {rendererInfos = {{renderer = Renderer, shareMaterials = Array(Materials)}}, materialMap = {[instanceId] = Material}},
  27. [Enum.SkinSlotType.HeadMiddle] = {rendererInfos = {{renderer = Renderer, shareMaterials = Array(Materials)}}, materialMap = {[instanceId] = Material}},
  28. [Enum.SkinSlotType.HeadBottom] = {rendererInfos = {{renderer = Renderer, shareMaterials = Array(Materials)}}, materialMap = {[instanceId] = Material}},
  29. [Enum.SkinSlotType.Cloth] = {rendererInfos = {{renderer = Renderer, shareMaterials = Array(Materials)}}, materialMap = {[instanceId] = Material}},
  30. [Enum.SkinSlotType.LeftHand] = {rendererInfos = {{renderer = Renderer, shareMaterials = Array(Materials)}}, materialMap = {[instanceId] = Material}},
  31. [Enum.SkinSlotType.RightHand] = {rendererInfos = {{renderer = Renderer, shareMaterials = Array(Materials)}}, materialMap = {[instanceId] = Material}},
  32. [Enum.SkinSlotType.BodyBack] = {rendererInfos = {{renderer = Renderer, shareMaterials = Array(Materials)}}, materialMap = {[instanceId] = Material}},
  33. [Enum.SkinSlotType.HairStyle] = {rendererInfos = {{renderer = Renderer, shareMaterials = Array(Materials)}}, materialMap = {[instanceId] = Material}},
  34. [Enum.SkinSlotType.Pupil] = {rendererInfos = {{renderer = Renderer, shareMaterials = Array(Materials)}}, materialMap = {[instanceId] = Material}},
  35. [Enum.SkinSlotType.HairColor] = {[HairColor] = Vector2},
  36. [Enum.SkinSlotType.Face] = {rendererInfos = {{renderer = Renderer, shareMaterials = Array(Materials)}}, materialMap = {[instanceId] = Material}},
  37. }
  38. rendererInfos 为 该位置上所有的渲染Renderer信息
  39. shareMaterials 为 该位置上渲染Renderer的默认材质球
  40. materialMap 为 该位置上所有的渲染Renderer改变的材质信息
  41. ]]
  42. local SkinSystem = class("SkinSystem")
  43. local Object = UnityEngine.Object
  44. local Material = UnityEngine.Material
  45. local Renderer = UnityEngine.Renderer
  46. local SkinnedMeshRenderer = UnityEngine.SkinnedMeshRenderer
  47. -- local MeshRenderer = UnityEngine.MeshRenderer
  48. local RendererType = typeof(Renderer)
  49. local SkinnedMeshRendererType = typeof(SkinnedMeshRenderer)
  50. -- local MeshRendererType = typeof(MeshRenderer)
  51. local GetMatUVOffset = function(material)
  52. return material.mainTextureOffset
  53. end
  54. local SetMatUVOffset = function(material, uvOffset)
  55. material.mainTextureOffset = uvOffset
  56. end
  57. -- local GetMatAlpha = function(material)
  58. -- local color = material.color
  59. -- return color.a
  60. -- end
  61. -- local SetMatAlpha = function(material, alpha)
  62. -- local color = material.color
  63. -- color.alpha = alpha
  64. -- material.color = color
  65. -- end
  66. function SkinSystem:ctor()
  67. self.rootTrans = nil
  68. self.boneMap = {}
  69. self.skins = {}
  70. self.extSkins = {}
  71. end
  72. function SkinSystem:Dispose()
  73. self:Clear()
  74. self.rootTrans = nil
  75. self.boneMap = nil
  76. self.skins = nil
  77. self.extSkins = nil
  78. end
  79. function SkinSystem:Clear()
  80. for skinSlot,_ in pairs(self.skins) do
  81. self:_RemoveSkin(skinSlot, self.skins)
  82. end
  83. for skinSlot,_ in pairs(self.extSkins) do
  84. self:_RemoveSkin(skinSlot, self.extSkins)
  85. end
  86. for key,_ in pairs(self.boneMap) do
  87. self.boneMap[key] = nil
  88. end
  89. self.rootTrans = nil
  90. end
  91. function SkinSystem:Init(ownerTrans, skinDatas, extSkinDatas, isCombine)
  92. assert(ownerTrans, "ownerTrans is nil")
  93. self:Clear()
  94. self.rootTrans = ownerTrans
  95. self:_BuildBoneMap()
  96. self:SetSkins(skinDatas, extSkinDatas, isCombine)
  97. end
  98. function SkinSystem:SetBaseBone(ownerTrans)
  99. assert(ownerTrans, "ownerTrans is nil")
  100. if self.rootTrans == ownerTrans then return end
  101. self.rootTrans = ownerTrans
  102. self:_BuildBoneMap()
  103. self:_RebineSkins()
  104. end
  105. function SkinSystem:SetSkins(skinDatas, extSkinDatas, isCombine)
  106. local changed = false
  107. local skins = self.skins
  108. local extSkins = self.extSkins
  109. local skinData, hasValue
  110. for _, skinSlotType in pairs(Enum.SkinSlotType) do
  111. if skinDatas then
  112. skinData = skinDatas[skinSlotType]
  113. if skinData then
  114. hasValue = skinData.hasValue
  115. if hasValue then
  116. changed = self:_AddSkin(skinSlotType, skinData, skins) or changed
  117. else
  118. changed = self:_RemoveSkin(skinSlotType, skins) or changed
  119. end
  120. end
  121. end
  122. if extSkinDatas then
  123. skinData = extSkinDatas[skinSlotType]
  124. if skinData then
  125. hasValue = skinData.hasValue
  126. if hasValue then
  127. changed = self:_SetSkinActive(skinSlotType, false) or changed
  128. changed = self:_AddSkin(skinSlotType, skinData, extSkins) or changed
  129. else
  130. changed = self:_SetSkinActive(skinSlotType, true) or changed
  131. changed = self:_RemoveSkin(skinSlotType, extSkins) or changed
  132. end
  133. end
  134. end
  135. end
  136. if changed and isCombine then self:_CombineSkin() end
  137. end
  138. function SkinSystem:_AddSkin(skinSlotType, skinInfo, skins)
  139. local changed = false
  140. if skinSlotType == Enum.SkinSlotType.HairColor then
  141. local uvOffset = skinInfo.uvOffset
  142. -- 改变头发材质的颜色值
  143. skins[skinSlotType] = { uvOffset = uvOffset }
  144. -- 如果头发模型在,需要修改材质
  145. local hairData = skins[Enum.SkinSlotType.Hair]
  146. if hairData then
  147. -- 修改头发颜色
  148. changed = self:_ChangeHairColor(hairData, uvOffset) or changed
  149. end
  150. else
  151. -- 删除当前位置上已有的表现
  152. changed = self:_RemoveSkin(skinSlotType, skins) or changed
  153. if not skinInfo then return changed end
  154. -- 预制体的改变
  155. local rendererInfos = self:_AddPrefab(skinSlotType, skinInfo)
  156. if not rendererInfos or #rendererInfos <= 0 then
  157. return changed
  158. end
  159. changed = true
  160. local data = { rendererInfos = rendererInfos }
  161. if skinSlotType == Enum.SkinSlotType.Hair then
  162. local hairColorData = skins[Enum.SkinSlotType.HairColor]
  163. if hairColorData and hairColorData.uvOffset then
  164. -- 修改头发颜色
  165. local uvOffset = hairColorData.uvOffset
  166. changed = self:_ChangeHairColor(data, uvOffset) or changed
  167. end
  168. end
  169. skins[skinSlotType] = data
  170. end
  171. return changed
  172. end
  173. function SkinSystem:_RemoveSkin(skinSlotType, skins)
  174. local changed = false
  175. if skinSlotType == Enum.SkinSlotType.HairColor then
  176. -- 删除头发材质的颜色值
  177. -- 头发模型在,需要恢复默认材质
  178. local hairData = skins[Enum.SkinSlotType.Hair]
  179. if hairData then
  180. -- 恢复默认头发颜色
  181. changed = self:_ChangeHairColor(hairData, nil) or changed
  182. end
  183. else
  184. -- 改变表现
  185. local skinInfo = skins[skinSlotType]
  186. if skinInfo then
  187. self:_ClearChangeMaterial(skinInfo)
  188. local rendererInfos = skinInfo.rendererInfos
  189. if rendererInfos then
  190. for i = #rendererInfos, 1, -1 do
  191. local rendererInfo = rendererInfos[i]
  192. if rendererInfo and not tolua.isnull(rendererInfo.renderer) and not tolua.isnull(rendererInfo.renderer.gameObject) then
  193. -- TODO: 由于Destroy并不是立即删除,所以Animator中的BlendShape动画重定向时还会被定位到,导致动画表现错误
  194. -- 所以把当前对象移除Animator可索引区域
  195. rendererInfo.renderer.transform:SetParent(nil)
  196. Object.Destroy(rendererInfo.renderer.gameObject)
  197. end
  198. rendererInfo.sharedMaterials = nil
  199. rendererInfos[i].renderer = nil
  200. rendererInfos[i] = nil
  201. end
  202. end
  203. skinInfo.color = nil
  204. skinInfo.rendererInfos = nil
  205. end
  206. end
  207. skins[skinSlotType] = nil
  208. return changed
  209. end
  210. function SkinSystem:_SetSkinActive(skinSlotType, active)
  211. local changed = false
  212. if skinSlotType ~= Enum.SkinSlotType.HairColor then
  213. -- 改变表现
  214. local skinInfo = self.skins[skinSlotType]
  215. if skinInfo then
  216. local rendererInfos = skinInfo.rendererInfos
  217. if rendererInfos then
  218. for i = #rendererInfos, 1, -1 do
  219. local rendererInfo = rendererInfos[i]
  220. if rendererInfo and not tolua.isnull(rendererInfo.renderer) then
  221. local activeSelf = rendererInfo.renderer.gameObject.activeSelf
  222. if activeSelf ~= active then
  223. rendererInfo.renderer.gameObject:SetActive(active)
  224. changed = true
  225. end
  226. end
  227. end
  228. end
  229. end
  230. end
  231. return changed
  232. end
  233. function SkinSystem:_ChangeHairColor(hairData, uvOffset)
  234. return self:_ChangeMaterial(hairData, 'HairColor', uvOffset, SetMatUVOffset, GetMatUVOffset)
  235. end
  236. function SkinSystem:_ClearChangeMaterial(data)
  237. data.changes = nil
  238. self:_ResetMaterial(data)
  239. end
  240. function SkinSystem:_ChangeMaterial(data, key, value, changeFun, getDefaultValFun)
  241. local status = self:_SetChangeDataValue(data, key, value)
  242. -- 和当前值一致,不需要做修改
  243. if status == 0 then
  244. return false
  245. end
  246. -- 所有修改都取消了,重置材质球到默认材质球
  247. if status == 2 then
  248. return self:_ResetMaterial(data)
  249. end
  250. local rendererInfos = data.rendererInfos
  251. local materialMap = data.materialMap
  252. if materialMap == nil then
  253. materialMap = {}
  254. data.materialMap = materialMap
  255. -- 统计出需要改变的材质球
  256. for i = 1, #rendererInfos do
  257. local rendererInfo = rendererInfos[i]
  258. local sharedMaterials = rendererInfo.sharedMaterials
  259. local length = sharedMaterials.Length
  260. local newMaterials = System.Array.CreateInstance(typeof(Material), length)
  261. for j = 0, length - 1 do
  262. local sharedMaterial = sharedMaterials[j]
  263. if sharedMaterial then
  264. local instanceId = sharedMaterial:GetInstanceID()
  265. if materialMap[instanceId] then
  266. newMaterials[j] = materialMap[instanceId][1]
  267. else
  268. -- 创建新材质球,并修改值
  269. local newMaterial = Material(sharedMaterial)
  270. materialMap[instanceId] = { newMaterial, sharedMaterial }
  271. newMaterials[j] = newMaterial
  272. if status == 3 then -- 修改材质球到这个值
  273. changeFun(newMaterial, value)
  274. end
  275. end
  276. end
  277. end
  278. rendererInfo.renderer.sharedMaterials = newMaterials
  279. end
  280. else
  281. for _, materials in pairs(materialMap) do
  282. if status == 1 then -- 当修改需要重置回默认值
  283. local defaultValue = getDefaultValFun(materials[2])
  284. changeFun(materials[1], defaultValue)
  285. elseif status == 3 then -- 修改材质球到这个值
  286. changeFun(materials[1], value)
  287. end
  288. end
  289. end
  290. return true
  291. end
  292. --- 还原被修改的材质球
  293. function SkinSystem:_ResetMaterial(data)
  294. local rendererInfos = data.rendererInfos
  295. local materialMap = data.materialMap
  296. -- 没有改变过材质球,不需要修改
  297. if not materialMap then return false end
  298. -- 还原默认材质
  299. for i = 1, #rendererInfos do
  300. local rendererInfo = rendererInfos[i]
  301. if not tolua.isnull(rendererInfo.renderer) then
  302. rendererInfo.renderer.sharedMaterials = rendererInfo.sharedMaterials
  303. end
  304. end
  305. -- 删除变化的材质球
  306. for instanceId, material in pairs(materialMap) do
  307. if not tolua.isnull(material) then
  308. Object.Destroy(material)
  309. end
  310. materialMap[instanceId] = nil
  311. end
  312. data.materialMap = nil
  313. return true
  314. end
  315. --- 设置变化值
  316. ---@return integer 0:和当前值一致;1:Key的变化重置回默认值;2:所有变化都重置回默认值;3:更新key的变化
  317. function SkinSystem:_SetChangeDataValue(data, key, value)
  318. local changes = data.changes
  319. if changes == nil then
  320. if not value then
  321. return 0
  322. end
  323. changes = {}
  324. data.changes = changes
  325. end
  326. local oldValue = changes[key]
  327. if oldValue == value then
  328. return 0
  329. end
  330. if not value then
  331. changes[key] = nil
  332. local isChanged = CommonUtil.TableIsEmpty(changes)
  333. if isChanged then
  334. return 1
  335. else
  336. data.changes = nil
  337. return 2
  338. end
  339. end
  340. changes[key] = value
  341. return 3
  342. end
  343. function SkinSystem:_AddPrefab(skinSlotType, slotContent)
  344. local prefabGo = slotContent.prefabGo
  345. if tolua.isnull(prefabGo) then return nil end
  346. local pos = slotContent.pos
  347. local rot = slotContent.rot
  348. local scale = slotContent.scale
  349. local customBindBone = slotContent.customBindBone
  350. -- 后续需要加上不同部位只能有一种类型Renderer的判断
  351. -- if skinSlotType == Enum.SkinSlotType.HeadTop
  352. -- or skinSlotType == Enum.SkinSlotType.HeadMiddle
  353. -- or skinSlotType == Enum.SkinSlotType.HeadBottom
  354. -- or skinSlotType == Enum.SkinSlotType.Weapon
  355. -- or skinSlotType == Enum.SkinSlotType.BodyBack then
  356. -- else
  357. -- end
  358. local prefabTrans = prefabGo.transform
  359. local go = Object.Instantiate(prefabGo)
  360. go.name = prefabGo.name
  361. local trans = go.transform
  362. local boneTrans = self:_SetBindBone(prefabTrans, trans, skinSlotType, pos, rot, scale, customBindBone)
  363. local renderers = go:GetComponentsInChildren(RendererType)
  364. local length = renderers.Length
  365. local rendererInfos = nil
  366. local needDestroy = true
  367. if length > 0 then
  368. local layer = self.rootTrans.gameObject.layer
  369. rendererInfos = {}
  370. for i = 0, length - 1 do
  371. local renderer = renderers[i]
  372. renderer.gameObject.layer = layer
  373. local rendererTrans = renderer.transform
  374. if rendererTrans == trans then
  375. needDestroy = false
  376. end
  377. local classType = renderer:GetType()
  378. if classType == SkinnedMeshRendererType then
  379. self:_SMRRebindBone(renderer)
  380. rendererTrans.parent = self.rootTrans
  381. else
  382. rendererTrans.parent = boneTrans
  383. end
  384. local rendererInfo = { renderer = renderer, sharedMaterials = renderer.sharedMaterials}
  385. rendererInfos[#rendererInfos + 1] = rendererInfo
  386. end
  387. end
  388. if needDestroy then
  389. trans.parent = nil
  390. Object.Destroy(go)
  391. end
  392. return rendererInfos
  393. end
  394. function SkinSystem:_SetBindBone(srcTrans, trans, skinSlotType, pos, rot, scale, customBindBone)
  395. local boneTrans = nil
  396. if customBindBone and customBindBone ~= '' and self.boneMap[customBindBone] then
  397. boneTrans = self.boneMap[customBindBone]
  398. end
  399. if tolua.isnull(boneTrans) then
  400. local parentName = Enum.SkinSlotBindBone[skinSlotType]
  401. boneTrans = self.boneMap[parentName]
  402. end
  403. if tolua.isnull(boneTrans) then
  404. local parentTrans = srcTrans.parent
  405. if parentTrans then
  406. boneTrans = self.boneMap[parentTrans.name]
  407. end
  408. end
  409. if tolua.isnull(boneTrans) then
  410. boneTrans = self.rootTrans
  411. end
  412. trans.parent = boneTrans
  413. trans.localPosition = pos or srcTrans.localPosition
  414. trans.localRotation = rot or srcTrans.localRotation
  415. trans.localScale = scale or srcTrans.localScale
  416. return boneTrans
  417. end
  418. function SkinSystem:_RebineSkin(slotInfo)
  419. if not slotInfo then return end
  420. local rendererInfos = slotInfo.rendererInfos
  421. if not rendererInfos then return end
  422. for i = 1, #rendererInfos do
  423. local renderer = rendererInfos[i].renderer
  424. local rendererTrans = renderer.transform
  425. local classType = renderer:GetType()
  426. if classType == typeof(SkinnedMeshRenderer) then
  427. self:_SMRRebindBone(renderer)
  428. rendererTrans.parent = self.rootTrans
  429. rendererTrans.localPosition = Vector3.zero
  430. rendererTrans.localRotation = Quaternion.identity
  431. rendererTrans.localScale = Vector3.one
  432. else
  433. local localPosition = rendererTrans.localPosition
  434. local localRotation = rendererTrans.localRotation
  435. local localScale = rendererTrans.localScale
  436. local parentTrans = rendererTrans.parent
  437. local parentName = parentTrans and parentTrans.name or ""
  438. local boneTrans = self.boneMap[parentName]
  439. rendererTrans.parent = boneTrans or self.rootTrans
  440. rendererTrans.localPosition = localPosition
  441. rendererTrans.localRotation = localRotation
  442. rendererTrans.localScale = localScale
  443. end
  444. end
  445. end
  446. --- 基本骨骼发生变化后,需要重新绑定表现
  447. function SkinSystem:_RebineSkins()
  448. local skins = self.skins
  449. local extSkins = self.extSkins
  450. for _, skinSlotType in pairs(Enum.SkinSlotType) do
  451. if skinSlotType == Enum.SkinSlotType.HairColor then
  452. -- 骨骼发生变化,对材质球是无影响的
  453. else
  454. if skins then
  455. self:_RebineSkin(skins[skinSlotType])
  456. end
  457. if extSkins then
  458. self:_RebineSkin(extSkins[skinSlotType])
  459. end
  460. end
  461. end
  462. end
  463. -- 重定向SkinnedMeshRenderer的骨骼绑定
  464. function SkinSystem:_SMRRebindBone(smr)
  465. local rootBone = smr.rootBone
  466. local name = rootBone.name
  467. if self.boneMap[name] then
  468. smr.rootBone = self.boneMap[name]
  469. else
  470. -- 暂时未做骨骼新增,看未来需求
  471. smr.rootBone = nil
  472. LogError(smr.gameObject.name .. "'s rootBone : ".. tostring(name) .. " is not find, Check It!!!!!!")
  473. end
  474. local bones = smr.bones
  475. for i = 0, bones.Length - 1 do
  476. name = bones[i].name
  477. if self.boneMap[name] then
  478. bones[i] = self.boneMap[name]
  479. else
  480. -- 暂时未做骨骼新增,看未来需求
  481. LogError(smr.gameObject.name .. "'s Bone : ".. tostring(name) .. " is not find, Check It!!!!!!")
  482. end
  483. end
  484. smr.bones = bones
  485. end
  486. -- 构建骨骼Map,方便后续骨骼查找
  487. function SkinSystem:_BuildBoneMap()
  488. if not self.rootTrans then
  489. LogError("BaseModel is Null, not generate Bone Map")
  490. return self.boneMap
  491. end
  492. local rootBone = self.rootTrans:Find("Bip001")
  493. if not rootBone then
  494. LogError("BaseModel is not find \"Bip001\", not generate Bone Map")
  495. return self.boneMap
  496. end
  497. self:_GenerateBoneMap(rootBone)
  498. end
  499. function SkinSystem:_GenerateBoneMap(transform)
  500. if not transform then return end
  501. local name = transform.name
  502. if self.boneMap[name] then
  503. LogError("Has Some Name Bone" .. name .. ", Check It!!!!!!")
  504. end
  505. self.boneMap[name] = transform
  506. for i = 0, transform.childCount - 1 do
  507. self:_GenerateBoneMap(transform:GetChild(i))
  508. end
  509. end
  510. function SkinSystem:_CombineSkin()
  511. end
  512. return SkinSystem