Unity3D仿星露谷物语开发60之定制角色其他部位
1、目标
上一篇中定制了角色的衬衫、手臂。
本篇中将定制角色其他部位的图形,包括:裤子、发型、皮肤、帽子等。
2、定制裤子
(1)修改ApplyCharacterCustomisation.cs脚本
我们需要设置一个输入框选择裤子的颜色。
// Select Trouser Color[SerializeField] private Color inputTrouserColor = Color.blue;
Color字段序列化之后,点击就会在编辑器中弹出一个颜色选择器。
目前角色的裤子颜色,基本上都是白色和灰色的,我们要做的是取那个被选中的颜色,在这些裤子上层绘制新的颜色。
添加新的处理方法:
添加如下方法:
private void ProcessTrousers(){// Get trouser pixels to recolorColor[] farmerTrouserPixels = farmerBaseTexture.GetPixels(288, 0, 96, farmerBaseTexture.height);// Change trouser colorsTintPixelColors(farmerTrouserPixels, inputTrouserColor);// Set changed trouser pixelsfarmerBaseCustomised.SetPixels(288, 0, 96, farmerBaseTexture.height, farmerTrouserPixels);// Apply texture changesfarmerBaseCustomised.Apply();}private void TintPixelColors(Color[] basePixelArray, Color tintColor){// Loop through pixels to tintfor(int i = 0; i < basePixelArray.Length; i++){basePixelArray[i].r = basePixelArray[i].r * tintColor.r;basePixelArray[i].g = basePixelArray[i].g * tintColor.g;basePixelArray[i].b = basePixelArray[i].b * tintColor.b;}}
为了得到新的像素,我们将基础像素和色调颜色相乘。
在MergeCustomisations方法中,将farmerBaseTexture修改为farmerBaseCustomised。
(2)游戏效果
运行游戏后,查看以下文件,可以看到精灵表中裤子都换成了蓝色。
选择黄色裤子后,可以看到角色的裤子更新了。
3、定制发型
(1)修改ApplyCharacterCustomisation.cs脚本
添加1个输入:
在下面可以看到所有的发型信息:
这些发型没有颜色,只是白色和灰色的阴影。这里面有2种(列)发型,每种发型有3个方向的发型。
添加1个输出:
添加输入项:
添加发型的维度信息:
添加处理发型的方法:
添加处理方法:
private void ProcessHair(){// Create Selected Hair TextureAddHairToTexture(inputHairStyleNo);// Get hair pixels to recolorColor[] farmerSelectedHairPixels = hairCustomised.GetPixels();// Tint hair pixelsTintPixelColors(farmerSelectedHairPixels, inputHairColor);hairCustomised.SetPixels(farmerSelectedHairPixels);hairCustomised.Apply();}private void AddHairToTexture(int hairStyleNo){// Calculate coordinates for hair pixelsint y = (hairStyleNo / hairStylesInSpriteWidth) * hairTextureHeight;int x = (hairStyleNo % hairStylesInSpriteWidth) * hairTextureWidth;// Get hair pixelsColor[] hairPixels = hairBaseTexture.GetPixels(x, y, hairTextureWidth, hairTextureHeight);// Apply selected hair pixels to texturehairCustomised.SetPixels(hairPixels);hairCustomised.Apply();}
(2)配置Player对象
配置CharacterCustomiser对象。
程序会从assets -> Sprites -> Output Textures中读取数据(真实有用,而不仅仅为了展示效果)
反选hat避免遮挡发型。
(3)游戏效果
运行游戏,可以看到红色的新发型。
4、定制肤色
(1)修改ApplyCharacterCustomisation.cs脚本
定义要替换的皮肤颜色:
// Target skin colours for color replacementprivate Color32 skinTargetColor1 = new Color32(145, 117, 90, 255); // darkestprivate Color32 skinTargetColor2 = new Color32(204, 155, 108, 255); // next darkestprivate Color32 skinTargetColor3 = new Color32(207, 166, 128, 255); // next darkestprivate Color32 skinTargetColor4 = new Color32(238, 195, 154, 255); // lightest
这4个颜色对应脸部、手掌上的颜色如下:
后面会用新定义的颜色来代替上面这些颜色。
增加新的函数如下:
private void ProcessSkin(){// Get skin pixels to recolorColor[] farmerPixelsToRecolor = farmerBaseCustomised.GetPixels(0, 0, 288, farmerBaseTexture.height);// Populate Skin Color Swap ListPopulateSkinColorSwapList(inputSkinType);// Change skin colorsChangePixelColors(farmerPixelsToRecolor, colorSwapList);// Set recoloured pixelsfarmerBaseCustomised.SetPixels(0, 0, 288, farmerBaseTexture.height, farmerPixelsToRecolor);// Apply texture changesfarmerBaseCustomised.Apply();}private void PopulateSkinColorSwapList(int skinType){// Clear color swap listcolorSwapList.Clear();// Skin replacement colors//Switch on skin typeswitch(skinType){case 0:colorSwapList.Add(new colorSwap(skinTargetColor1, skinTargetColor1));colorSwapList.Add(new colorSwap(skinTargetColor2, skinTargetColor2));colorSwapList.Add(new colorSwap(skinTargetColor3, skinTargetColor3));colorSwapList.Add(new colorSwap(skinTargetColor4, skinTargetColor4));break;case 1:colorSwapList.Add(new colorSwap(skinTargetColor1, new Color32(187, 157, 128, 255)));colorSwapList.Add(new colorSwap(skinTargetColor2, new Color32(231, 187, 144, 255)));colorSwapList.Add(new colorSwap(skinTargetColor3, new Color32(221, 186, 154, 255)));colorSwapList.Add(new colorSwap(skinTargetColor4, new Color32(213, 189, 167, 255)));break;case 2:colorSwapList.Add(new colorSwap(skinTargetColor1, new Color32(105, 69, 2, 255)));colorSwapList.Add(new colorSwap(skinTargetColor2, new Color32(128, 87, 12, 255)));colorSwapList.Add(new colorSwap(skinTargetColor3, new Color32(145, 103, 26, 255)));colorSwapList.Add(new colorSwap(skinTargetColor4, new Color32(161, 114, 25, 255)));break;case 3:colorSwapList.Add(new colorSwap(skinTargetColor1, new Color32(151, 132, 0, 255)));colorSwapList.Add(new colorSwap(skinTargetColor2, new Color32(187, 166, 15, 255)));colorSwapList.Add(new colorSwap(skinTargetColor3, new Color32(209, 188, 39, 255)));colorSwapList.Add(new colorSwap(skinTargetColor4, new Color32(211, 199, 112, 255)));break;default:colorSwapList.Add(new colorSwap(skinTargetColor1, skinTargetColor1));colorSwapList.Add(new colorSwap(skinTargetColor2, skinTargetColor2));colorSwapList.Add(new colorSwap(skinTargetColor3, skinTargetColor3));colorSwapList.Add(new colorSwap(skinTargetColor4, skinTargetColor4));break;}}
(2)游戏效果
理论上脸部要发生颜色变化,实际上脸部颜色没有发生变化,尝试了修改skinTargetColor1~4也无果。
5、定制帽子
目前角色使用到的帽子的精灵图(output目录下)位于:
输入的帽子的精灵图位于:
目前只有一种帽子,此时构造2个选择:0没有帽子,1有帽子。
编写ApplyCharacterCustomisation.cs脚本:
private void ProcessHat(){// Create Selected Hat TextureAddHatToTexture(inputHatStyleNo);}private void AddHatToTexture(int hatStyleNo){// Calculate coordinates for hat pixelsint y = (hatStyleNo / hatStylesInSpriteWidth) * hatTextureHeight;int x = (hatStyleNo % hatStylesInSpriteWidth) * hatTextureWidth;// Get hat pixelsColor[] hatPixels = hatsBaseTexture.GetPixels(x, y, hatTextureWidth, hatTextureHeight);// Apply selected hat pixels to texturehatsCustomised.SetPixels(hatPixels);hatsCustomised.Apply();}
配置CharacterCustomiser的信息:
运行游戏:
Select Hat Style=0时没有帽子:
Select Hat Style=1时有帽子:
6、定制角色装饰
目标:用户选择不同的装饰(0没有,1眼镜,2胡子)。
下面可以看到装饰信息:
第一个位置是空的,下一个位置为眼镜,再下一个位置是胡子。并且只有正面和侧面的图片。
private void ProcessAdornments(){// Initialise body adornments offset arraybodyAdornmentsOffsetArray = new Vector2Int[bodyColumns, bodyRows];// Populate body adornments offset arrayPopulateBodyAdornmentsOffsetArray();// Create Selected Adornments TextureAddAdornmentsToTexture(inputAdornmentsStyleNo);// Create new adornments base texturefarmerBaseAdornmentsUpdated = new Texture2D(farmerBaseTexture.width, farmerBaseTexture.height);farmerBaseAdornmentsUpdated.filterMode = FilterMode.Point;// Set adornments base texture to transparentSetTextureToTransparent(farmerBaseAdornmentsUpdated);ApplyAdornmentsTextureToBase();}private void AddAdornmentsToTexture(int adornmentsStyleNo){// Create adornment textureselectedAdornment = new Texture2D(adornmentsTextureWidth, adornmentsTextureHeight);selectedAdornment.filterMode = FilterMode.Point;// Calculate coordinates for adornments pixelsint y = (adornmentsStyleNo / adornmentsStylesInSpriteWidth) * adornmentsTextureHeight;int x = (adornmentsStyleNo % adornmentsStylesInSpriteWidth) * adornmentsTextureWidth;// Get adornments pixelsColor[] adornmentsPixels = adornmentsBaseTexture.GetPixels(x, y, adornmentsTextureWidth, adornmentsTextureHeight);// Apply selected adornments pixels to textureselectedAdornment.SetPixels(adornmentsPixels);selectedAdornment.Apply(); }private void ApplyAdornmentsTextureToBase(){Color[] frontAdornmentsPixels;Color[] rightAdornmentsPixels;frontAdornmentsPixels = selectedAdornment.GetPixels(0, adornmentsSpriteHeight * 1, adornmentsSpriteWidth, adornmentsSpriteHeight);rightAdornmentsPixels = selectedAdornment.GetPixels(0, adornmentsSpriteHeight * 0, adornmentsSpriteWidth, adornmentsSpriteHeight);// Loop through base texture and apply adornments pixelsfor(int x = 0; x < bodyColumns; x++){for(int y = 0; y < bodyRows; y++){int pixelX = x * farmerSpriteWidth;int pixelY = y * farmerSpriteHeight;if (bodyAdornmentsOffsetArray[x, y] != null){pixelX += bodyAdornmentsOffsetArray[x, y].x;pixelY += bodyAdornmentsOffsetArray[x, y].y;}// Switch on facing directionswitch(bodyFacingArray[x, y]){case Facing.none:break;case Facing.front:// Populate front adornments pixelsfarmerBaseAdornmentsUpdated.SetPixels(pixelX, pixelY, adornmentsSpriteWidth, adornmentsSpriteHeight, frontAdornmentsPixels);break;case Facing.right:// Populate right adornments pixelsfarmerBaseAdornmentsUpdated.SetPixels(pixelX, pixelY, adornmentsSpriteWidth, adornmentsSpriteHeight, rightAdornmentsPixels);break;default:break;}}}// Apply adornments texture pixelsfarmerBaseAdornmentsUpdated.Apply();}
ApplyCharacterCustomisation.cs的完整代码如下:
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;[System.Serializable]
public class colorSwap
{public Color fromColor;public Color toColor;public colorSwap(Color fromColor, Color toColor){this.fromColor = fromColor;this.toColor = toColor;}
}public class ApplyCharacterCustomisation : MonoBehaviour
{// Input Textures[Header("Base Textures")][SerializeField] private Texture2D maleFarmerBaseTexture = null;[SerializeField] private Texture2D femaleFarmerBaseTexture = null;[SerializeField] private Texture2D shirtsBaseTexture = null;[SerializeField] private Texture2D hairBaseTexture = null;[SerializeField] private Texture2D hatsBaseTexture = null;[SerializeField] private Texture2D adornmentsBaseTexture = null;private Texture2D farmerBaseTexture;// Created Textures[Header("OutputBase Texture To Be Used For Animation")][SerializeField] private Texture2D farmerBaseCustomised = null;[SerializeField] private Texture2D hairCustomised = null;[SerializeField] private Texture2D hatsCustomised = null;private Texture2D farmerBaseShirtsUpdated;private Texture2D selectedShirt;private Texture2D farmerBaseAdornmentsUpdated;private Texture2D selectedAdornment;// Select Shirt style[Header("Select Shirt Style")][Range(0, 1)] // 红色衬衫或者绿色衬衫[SerializeField] private int inputShirtStyleNo = 0;// Select Hair Style[Header("Select Hair Style")][Range(0, 2)][SerializeField] private int inputHairStyleNo = 0;// Select Hat Style[Header("Select Hat Style")][Range(0, 1)][SerializeField] private int inputHatStyleNo = 0;// Select Adornments Style[Header("Select Adornments Style")][Range(0, 2)][SerializeField] private int inputAdornmentsStyleNo = 0;// Select Skin Type[Header("Select Skin Type")][Range(0, 3)][SerializeField] private int inputSkinType = 0;// Select Hair Color[SerializeField] private Color inputHairColor = Color.black;// Selecct Sex[Header("Select Sex:0=Male, 1=female")][Range(0, 1)][SerializeField] private int inputSex = 0;// Select Trouser Color[SerializeField] private Color inputTrouserColor = Color.blue;private Facing[,] bodyFacingArray;private Vector2Int[,] bodyShirtOffsetArray;private Vector2Int[,] bodyAdornmentsOffsetArray;// 定义精灵表的维度信息private int bodyRows = 21;private int bodyColumns = 6;private int farmerSpriteWidth = 16;private int farmerSpriteHeight = 32;private int shirtTextureWidth = 9;private int shirtTextureHeight = 36;private int shirtSpriteWidth = 9;private int shirtSpriteHeight = 9;private int shirtStylesInSpriteWidth = 16; // 纹理可以容纳衬衫的件数private int hairTextureWidth = 16;private int hairTextureHeight = 96;private int hairStylesInSpriteWidth = 8; // 发型的最多数量private int hatTextureWidth = 20;private int hatTextureHeight = 80; // output中的hat的texture就是20*80大小private int hatStylesInSpriteWidth = 12; // 帽子的最多数量private int adornmentsTextureWidth = 16;private int adornmentsTextureHeight = 32;private int adornmentsStylesInSpriteWidth = 8;private int adornmentsSpriteWidth = 16;private int adornmentsSpriteHeight = 16;// 颜色交换列表private List<colorSwap> colorSwapList;// Target arm colours for color replacementprivate Color32 armTargetColor1 = new Color32(77, 13, 13, 255); // darkestprivate Color32 armTargetColor2 = new Color32(138, 41, 41, 255); // next darkestprivate Color32 armTargetColor3 = new Color32(172, 50, 50, 255); // lightest// Target skin colours for color replacementprivate Color32 skinTargetColor1 = new Color32(145, 117, 90, 255); // darkestprivate Color32 skinTargetColor2 = new Color32(204, 155, 108, 255); // next darkestprivate Color32 skinTargetColor3 = new Color32(207, 166, 128, 255); // next darkestprivate Color32 skinTargetColor4 = new Color32(238, 195, 154, 255); // lightestprivate void Awake(){// Initialise color swap listcolorSwapList = new List<colorSwap>();// Process CustomisationProcessCustomisation();}private void ProcessCustomisation(){ProcessGender();ProcessShirt();ProcessArms();ProcessTrousers();ProcessHair();ProcessSkin();ProcessHat();ProcessAdornments();MergeCustomisations();}private void ProcessGender(){// Set base spritesheet by genderif(inputSex == 0){farmerBaseTexture = maleFarmerBaseTexture;}else if(inputSex == 1){farmerBaseTexture = femaleFarmerBaseTexture;}// Get base pixelsColor[] farmerBasePixels = farmerBaseTexture.GetPixels();// Set changed base pixelsfarmerBaseCustomised.SetPixels(farmerBasePixels);farmerBaseCustomised.Apply();}private void ProcessShirt(){// Initialise body facing shirt arraybodyFacingArray = new Facing[bodyColumns, bodyRows];// Populate body facing shirt arrayPopulateBodyFacingArray();// Initialise body shirt offset arraybodyShirtOffsetArray = new Vector2Int[bodyColumns, bodyRows];// Populate body shirt offset arrayPopulateBodyShirtOffsetArray();// Create Selected Shirt TextureAddShirtToTexture(inputShirtStyleNo);// Apply shirt texture to baseApplyShirtTextureToBase();}private void ProcessArms(){// Get arm pixels to recolorColor[] farmerPixelsToRecolor = farmerBaseTexture.GetPixels(0, 0, 288, farmerBaseTexture.height);// Populate arm color swap listPopulateArmColorSwapList();// Change arm colorsChangePixelColors(farmerPixelsToRecolor, colorSwapList);// Set recolored pixelsfarmerBaseCustomised.SetPixels(0, 0, 288, farmerBaseTexture.height, farmerPixelsToRecolor);// Apply texture changesfarmerBaseCustomised.Apply();}private void ProcessTrousers(){// Get trouser pixels to recolorColor[] farmerTrouserPixels = farmerBaseTexture.GetPixels(288, 0, 96, farmerBaseTexture.height);// Change trouser colorsTintPixelColors(farmerTrouserPixels, inputTrouserColor);// Set changed trouser pixelsfarmerBaseCustomised.SetPixels(288, 0, 96, farmerBaseTexture.height, farmerTrouserPixels);// Apply texture changesfarmerBaseCustomised.Apply();}private void ProcessHair(){// Create Selected Hair TextureAddHairToTexture(inputHairStyleNo);// Get hair pixels to recolorColor[] farmerSelectedHairPixels = hairCustomised.GetPixels();// Tint hair pixelsTintPixelColors(farmerSelectedHairPixels, inputHairColor);hairCustomised.SetPixels(farmerSelectedHairPixels);hairCustomised.Apply();}private void ProcessSkin(){// Get skin pixels to recolorColor[] farmerPixelsToRecolor = farmerBaseCustomised.GetPixels(0, 0, 288, farmerBaseTexture.height);// Populate Skin Color Swap ListPopulateSkinColorSwapList(inputSkinType);// Change skin colorsChangePixelColors(farmerPixelsToRecolor, colorSwapList);// Set recoloured pixelsfarmerBaseCustomised.SetPixels(0, 0, 288, farmerBaseTexture.height, farmerPixelsToRecolor);// Apply texture changesfarmerBaseCustomised.Apply();}private void ProcessHat(){// Create Selected Hat TextureAddHatToTexture(inputHatStyleNo);}private void ProcessAdornments(){// Initialise body adornments offset arraybodyAdornmentsOffsetArray = new Vector2Int[bodyColumns, bodyRows];// Populate body adornments offset arrayPopulateBodyAdornmentsOffsetArray();// Create Selected Adornments TextureAddAdornmentsToTexture(inputAdornmentsStyleNo);// Create new adornments base texturefarmerBaseAdornmentsUpdated = new Texture2D(farmerBaseTexture.width, farmerBaseTexture.height);farmerBaseAdornmentsUpdated.filterMode = FilterMode.Point;// Set adornments base texture to transparentSetTextureToTransparent(farmerBaseAdornmentsUpdated);ApplyAdornmentsTextureToBase();}private void AddAdornmentsToTexture(int adornmentsStyleNo){// Create adornment textureselectedAdornment = new Texture2D(adornmentsTextureWidth, adornmentsTextureHeight);selectedAdornment.filterMode = FilterMode.Point;// Calculate coordinates for adornments pixelsint y = (adornmentsStyleNo / adornmentsStylesInSpriteWidth) * adornmentsTextureHeight;int x = (adornmentsStyleNo % adornmentsStylesInSpriteWidth) * adornmentsTextureWidth;// Get adornments pixelsColor[] adornmentsPixels = adornmentsBaseTexture.GetPixels(x, y, adornmentsTextureWidth, adornmentsTextureHeight);// Apply selected adornments pixels to textureselectedAdornment.SetPixels(adornmentsPixels);selectedAdornment.Apply(); }private void ApplyAdornmentsTextureToBase(){Color[] frontAdornmentsPixels;Color[] rightAdornmentsPixels;frontAdornmentsPixels = selectedAdornment.GetPixels(0, adornmentsSpriteHeight * 1, adornmentsSpriteWidth, adornmentsSpriteHeight);rightAdornmentsPixels = selectedAdornment.GetPixels(0, adornmentsSpriteHeight * 0, adornmentsSpriteWidth, adornmentsSpriteHeight);// Loop through base texture and apply adornments pixelsfor(int x = 0; x < bodyColumns; x++){for(int y = 0; y < bodyRows; y++){int pixelX = x * farmerSpriteWidth;int pixelY = y * farmerSpriteHeight;if (bodyAdornmentsOffsetArray[x, y] != null){pixelX += bodyAdornmentsOffsetArray[x, y].x;pixelY += bodyAdornmentsOffsetArray[x, y].y;}// Switch on facing directionswitch(bodyFacingArray[x, y]){case Facing.none:break;case Facing.front:// Populate front adornments pixelsfarmerBaseAdornmentsUpdated.SetPixels(pixelX, pixelY, adornmentsSpriteWidth, adornmentsSpriteHeight, frontAdornmentsPixels);break;case Facing.right:// Populate right adornments pixelsfarmerBaseAdornmentsUpdated.SetPixels(pixelX, pixelY, adornmentsSpriteWidth, adornmentsSpriteHeight, rightAdornmentsPixels);break;default:break;}}}// Apply adornments texture pixelsfarmerBaseAdornmentsUpdated.Apply();}private void AddHatToTexture(int hatStyleNo){// Calculate coordinates for hat pixelsint y = (hatStyleNo / hatStylesInSpriteWidth) * hatTextureHeight;int x = (hatStyleNo % hatStylesInSpriteWidth) * hatTextureWidth;// Get hat pixelsColor[] hatPixels = hatsBaseTexture.GetPixels(x, y, hatTextureWidth, hatTextureHeight);// Apply selected hat pixels to texturehatsCustomised.SetPixels(hatPixels);hatsCustomised.Apply();}private void PopulateSkinColorSwapList(int skinType){// Clear color swap listcolorSwapList.Clear();// Skin replacement colors//Switch on skin typeswitch(skinType){case 0:colorSwapList.Add(new colorSwap(skinTargetColor1, skinTargetColor1));colorSwapList.Add(new colorSwap(skinTargetColor2, skinTargetColor2));colorSwapList.Add(new colorSwap(skinTargetColor3, skinTargetColor3));colorSwapList.Add(new colorSwap(skinTargetColor4, skinTargetColor4));break;case 1:colorSwapList.Add(new colorSwap(skinTargetColor1, new Color32(187, 157, 128, 255)));colorSwapList.Add(new colorSwap(skinTargetColor2, new Color32(231, 187, 144, 255)));colorSwapList.Add(new colorSwap(skinTargetColor3, new Color32(221, 186, 154, 255)));colorSwapList.Add(new colorSwap(skinTargetColor4, new Color32(213, 189, 167, 255)));break;case 2:colorSwapList.Add(new colorSwap(skinTargetColor1, new Color32(105, 69, 2, 255)));colorSwapList.Add(new colorSwap(skinTargetColor2, new Color32(128, 87, 12, 255)));colorSwapList.Add(new colorSwap(skinTargetColor3, new Color32(145, 103, 26, 255)));colorSwapList.Add(new colorSwap(skinTargetColor4, new Color32(161, 114, 25, 255)));break;case 3:colorSwapList.Add(new colorSwap(skinTargetColor1, new Color32(151, 132, 0, 255)));colorSwapList.Add(new colorSwap(skinTargetColor2, new Color32(187, 166, 15, 255)));colorSwapList.Add(new colorSwap(skinTargetColor3, new Color32(209, 188, 39, 255)));colorSwapList.Add(new colorSwap(skinTargetColor4, new Color32(211, 199, 112, 255)));break;default:colorSwapList.Add(new colorSwap(skinTargetColor1, skinTargetColor1));colorSwapList.Add(new colorSwap(skinTargetColor2, skinTargetColor2));colorSwapList.Add(new colorSwap(skinTargetColor3, skinTargetColor3));colorSwapList.Add(new colorSwap(skinTargetColor4, skinTargetColor4));break;}}private void AddHairToTexture(int hairStyleNo){// Calculate coordinates for hair pixelsint y = (hairStyleNo / hairStylesInSpriteWidth) * hairTextureHeight;int x = (hairStyleNo % hairStylesInSpriteWidth) * hairTextureWidth;// Get hair pixelsColor[] hairPixels = hairBaseTexture.GetPixels(x, y, hairTextureWidth, hairTextureHeight);// Apply selected hair pixels to texturehairCustomised.SetPixels(hairPixels);hairCustomised.Apply();}private void TintPixelColors(Color[] basePixelArray, Color tintColor){// Loop through pixels to tintfor(int i = 0; i < basePixelArray.Length; i++){basePixelArray[i].r = basePixelArray[i].r * tintColor.r;basePixelArray[i].g = basePixelArray[i].g * tintColor.g;basePixelArray[i].b = basePixelArray[i].b * tintColor.b;}}private void MergeCustomisations(){// Farmer Shirt pixelsColor[] farmerShirtPixels = farmerBaseShirtsUpdated.GetPixels(0, 0, bodyColumns * farmerSpriteWidth, farmerBaseTexture.height);// Farmer Trouser PixelsColor[] farmerTrouserPixelsSelection = farmerBaseCustomised.GetPixels(288, 0, 96, farmerBaseTexture.height);// Farmer Adornments PixelsColor[] farmerAdornmentsPixels = farmerBaseAdornmentsUpdated.GetPixels(0, 0, bodyColumns * farmerSpriteWidth, farmerBaseTexture.height);// Farmer Body PixelsColor[] farmerBodyPixels = farmerBaseCustomised.GetPixels(0, 0, bodyColumns * farmerSpriteWidth, farmerBaseTexture.height);MergeColorArray(farmerBodyPixels, farmerTrouserPixelsSelection);MergeColorArray(farmerBodyPixels, farmerShirtPixels);MergeColorArray(farmerBodyPixels, farmerAdornmentsPixels);// Paste merged pixelsfarmerBaseCustomised.SetPixels(0, 0, bodyColumns * farmerSpriteWidth, farmerBaseTexture.height, farmerBodyPixels);// Apply texture changesfarmerBaseCustomised.Apply();}private void MergeColorArray(Color[] baseArray, Color[] mergeArray){for(int i = 0; i < baseArray.Length; i++){if (mergeArray[i].a > 0){// Merge array has colorif (mergeArray[i].a >= 1){// Fully replacebaseArray[i] = mergeArray[i];}else{// Interpolate colorsfloat alpha = mergeArray[i].a;baseArray[i].r += (mergeArray[i].r - baseArray[i].r) * alpha;baseArray[i].g += (mergeArray[i].g - baseArray[i].g) * alpha;baseArray[i].b += (mergeArray[i].b - baseArray[i].b) * alpha;baseArray[i].a += mergeArray[i].a;}}}}private void PopulateArmColorSwapList(){// Clear color swap listcolorSwapList.Clear();// Arms replacement colorscolorSwapList.Add(new colorSwap(armTargetColor1, selectedShirt.GetPixel(0, 7)));colorSwapList.Add(new colorSwap(armTargetColor2, selectedShirt.GetPixel(0, 6)));colorSwapList.Add(new colorSwap(armTargetColor3, selectedShirt.GetPixel(0, 5)));}private void ChangePixelColors(Color[] baseArray, List<colorSwap> colorSwapList){for(int i = 0; i < baseArray.Length; i++){// Loop through color swap listif(colorSwapList.Count > 0){for(int j = 0; j < colorSwapList.Count; j++){if (isSameColor(baseArray[i], colorSwapList[j].fromColor)){baseArray[i] = colorSwapList[j].toColor;}}}}}private bool isSameColor(Color color1, Color color2){if ((color1.r == color2.r) && (color1.g == color2.g) && (color1.b == color2.b) && (color1.a == color2.a)){return true;}else{return false;}}private void AddShirtToTexture(int shirtStyleNo){// Create shirt textureselectedShirt = new Texture2D(shirtTextureWidth, shirtTextureHeight);selectedShirt.filterMode = FilterMode.Point;// Calculate coordinates for shirt pixelsint y = (shirtStyleNo / shirtStylesInSpriteWidth) * shirtTextureHeight;int x = (shirtStyleNo % shirtStylesInSpriteWidth) * shirtTextureWidth;// Get shirts pixelsColor[] shirtPixels = shirtsBaseTexture.GetPixels(x, y, shirtTextureWidth, shirtTextureHeight);// Apply selected shirt pixels to textureselectedShirt.SetPixels(shirtPixels);selectedShirt.Apply();}private void ApplyShirtTextureToBase(){// Create new shirt base texturefarmerBaseShirtsUpdated = new Texture2D(farmerBaseTexture.width, farmerBaseTexture.height);farmerBaseShirtsUpdated.filterMode = FilterMode.Point;// Set shirt base texture to transparentSetTextureToTransparent(farmerBaseShirtsUpdated);Color[] frontShirtPixels;Color[] backShirtPixels;Color[] rightShirtPixels;frontShirtPixels = selectedShirt.GetPixels(0, shirtSpriteHeight * 3, shirtSpriteWidth, shirtSpriteHeight);backShirtPixels = selectedShirt.GetPixels(0, shirtSpriteHeight * 0, shirtSpriteWidth, shirtSpriteHeight);rightShirtPixels = selectedShirt.GetPixels(0, shirtSpriteHeight * 2, shirtSpriteWidth, shirtSpriteHeight);// Loop through base texture and apply shirt pixelsfor(int x = 0; x < bodyColumns; x++){for(int y = 0; y < bodyRows; y++){int pixelX = x * farmerSpriteWidth;int pixelY = y * farmerSpriteHeight;if (bodyShirtOffsetArray[x, y] != null){if (bodyShirtOffsetArray[x, y].x == 99 && bodyShirtOffsetArray[x, y].y == 99) // do not populate with shirtcontinue;pixelX += bodyShirtOffsetArray[x, y].x;pixelY += bodyShirtOffsetArray[x, y].y;}// Switch on facing directionswitch(bodyFacingArray[x, y]){case Facing.none:break;case Facing.front:// populate front shirt pixelsfarmerBaseShirtsUpdated.SetPixels(pixelX, pixelY, shirtSpriteWidth, shirtSpriteHeight, frontShirtPixels);break;case Facing.back:// populate back shirt pixelsfarmerBaseShirtsUpdated.SetPixels(pixelX, pixelY, shirtSpriteWidth, shirtSpriteHeight, backShirtPixels);break;case Facing.right:// populate right shirt pixelsfarmerBaseShirtsUpdated.SetPixels(pixelX, pixelY, shirtSpriteWidth, shirtSpriteHeight, rightShirtPixels);break;default:break;}}}// Apply shirt texture pixelsfarmerBaseShirtsUpdated.Apply();}private void SetTextureToTransparent(Texture2D texture2D){// fill texture with transparencyColor[] fill = new Color[texture2D.height * texture2D.width];for(int i = 0; i < fill.Length; i++){fill[i] = Color.clear;}texture2D.SetPixels(fill);}private void PopulateBodyFacingArray(){bodyFacingArray[0, 0] = Facing.none;bodyFacingArray[1, 0] = Facing.none;bodyFacingArray[2, 0] = Facing.none;bodyFacingArray[3, 0] = Facing.none;bodyFacingArray[4, 0] = Facing.none;bodyFacingArray[5, 0] = Facing.none;bodyFacingArray[0, 1] = Facing.none;bodyFacingArray[1, 1] = Facing.none;bodyFacingArray[2, 1] = Facing.none;bodyFacingArray[3, 1] = Facing.none;bodyFacingArray[4, 1] = Facing.none;bodyFacingArray[5, 1] = Facing.none;bodyFacingArray[0, 2] = Facing.none;bodyFacingArray[1, 2] = Facing.none;bodyFacingArray[2, 2] = Facing.none;bodyFacingArray[3, 2] = Facing.none;bodyFacingArray[4, 2] = Facing.none;bodyFacingArray[5, 2] = Facing.none;bodyFacingArray[0, 3] = Facing.none;bodyFacingArray[1, 3] = Facing.none;bodyFacingArray[2, 3] = Facing.none;bodyFacingArray[3, 3] = Facing.none;bodyFacingArray[4, 3] = Facing.none;bodyFacingArray[5, 3] = Facing.none;bodyFacingArray[0, 4] = Facing.none;bodyFacingArray[1, 4] = Facing.none;bodyFacingArray[2, 4] = Facing.none;bodyFacingArray[3, 4] = Facing.none;bodyFacingArray[4, 4] = Facing.none;bodyFacingArray[5, 4] = Facing.none;bodyFacingArray[0, 5] = Facing.none;bodyFacingArray[1, 5] = Facing.none;bodyFacingArray[2, 5] = Facing.none;bodyFacingArray[3, 5] = Facing.none;bodyFacingArray[4, 5] = Facing.none;bodyFacingArray[5, 5] = Facing.none;bodyFacingArray[0, 6] = Facing.none;bodyFacingArray[1, 6] = Facing.none;bodyFacingArray[2, 6] = Facing.none;bodyFacingArray[3, 6] = Facing.none;bodyFacingArray[4, 6] = Facing.none;bodyFacingArray[5, 6] = Facing.none;bodyFacingArray[0, 7] = Facing.none;bodyFacingArray[1, 7] = Facing.none;bodyFacingArray[2, 7] = Facing.none;bodyFacingArray[3, 7] = Facing.none;bodyFacingArray[4, 7] = Facing.none;bodyFacingArray[5, 7] = Facing.none;bodyFacingArray[0, 8] = Facing.none;bodyFacingArray[1, 8] = Facing.none;bodyFacingArray[2, 8] = Facing.none;bodyFacingArray[3, 8] = Facing.none;bodyFacingArray[4, 8] = Facing.none;bodyFacingArray[5, 8] = Facing.none;bodyFacingArray[0, 9] = Facing.none;bodyFacingArray[1, 9] = Facing.none;bodyFacingArray[2, 9] = Facing.none;bodyFacingArray[3, 9] = Facing.none;bodyFacingArray[4, 9] = Facing.none;bodyFacingArray[5, 9] = Facing.none;bodyFacingArray[0, 10] = Facing.back;bodyFacingArray[1, 10] = Facing.back;bodyFacingArray[2, 10] = Facing.right;bodyFacingArray[3, 10] = Facing.right;bodyFacingArray[4, 10] = Facing.right;bodyFacingArray[5, 10] = Facing.right;bodyFacingArray[0, 11] = Facing.front;bodyFacingArray[1, 11] = Facing.front;bodyFacingArray[2, 11] = Facing.front;bodyFacingArray[3, 11] = Facing.front;bodyFacingArray[4, 11] = Facing.back;bodyFacingArray[5, 11] = Facing.back;bodyFacingArray[0, 12] = Facing.back;bodyFacingArray[1, 12] = Facing.back;bodyFacingArray[2, 12] = Facing.right;bodyFacingArray[3, 12] = Facing.right;bodyFacingArray[4, 12] = Facing.right;bodyFacingArray[5, 12] = Facing.right;bodyFacingArray[0, 13] = Facing.front;bodyFacingArray[1, 13] = Facing.front;bodyFacingArray[2, 13] = Facing.front;bodyFacingArray[3, 13] = Facing.front;bodyFacingArray[4, 13] = Facing.back;bodyFacingArray[5, 13] = Facing.back;bodyFacingArray[0, 14] = Facing.back;bodyFacingArray[1, 14] = Facing.back;bodyFacingArray[2, 14] = Facing.right;bodyFacingArray[3, 14] = Facing.right;bodyFacingArray[4, 14] = Facing.right;bodyFacingArray[5, 14] = Facing.right;bodyFacingArray[0, 15] = Facing.front;bodyFacingArray[1, 15] = Facing.front;bodyFacingArray[2, 15] = Facing.front;bodyFacingArray[3, 15] = Facing.front;bodyFacingArray[4, 15] = Facing.back;bodyFacingArray[5, 15] = Facing.back;bodyFacingArray[0, 16] = Facing.back;bodyFacingArray[1, 16] = Facing.back;bodyFacingArray[2, 16] = Facing.right;bodyFacingArray[3, 16] = Facing.right;bodyFacingArray[4, 16] = Facing.right;bodyFacingArray[5, 16] = Facing.right;bodyFacingArray[0, 17] = Facing.front;bodyFacingArray[1, 17] = Facing.front;bodyFacingArray[2, 17] = Facing.front;bodyFacingArray[3, 17] = Facing.front;bodyFacingArray[4, 17] = Facing.back;bodyFacingArray[5, 17] = Facing.back;bodyFacingArray[0, 18] = Facing.back;bodyFacingArray[1, 18] = Facing.back;bodyFacingArray[2, 18] = Facing.back;bodyFacingArray[3, 18] = Facing.right;bodyFacingArray[4, 18] = Facing.right;bodyFacingArray[5, 18] = Facing.right;bodyFacingArray[0, 19] = Facing.right;bodyFacingArray[1, 19] = Facing.right;bodyFacingArray[2, 19] = Facing.right;bodyFacingArray[3, 19] = Facing.front;bodyFacingArray[4, 19] = Facing.front;bodyFacingArray[5, 19] = Facing.front;bodyFacingArray[0, 20] = Facing.front;bodyFacingArray[1, 20] = Facing.front;bodyFacingArray[2, 20] = Facing.front;bodyFacingArray[3, 20] = Facing.back;bodyFacingArray[4, 20] = Facing.back;bodyFacingArray[5, 20] = Facing.back;}private void PopulateBodyShirtOffsetArray(){bodyShirtOffsetArray[0, 0] = new Vector2Int(99, 99);bodyShirtOffsetArray[1, 0] = new Vector2Int(99, 99);bodyShirtOffsetArray[2, 0] = new Vector2Int(99, 99);bodyShirtOffsetArray[3, 0] = new Vector2Int(99, 99);bodyShirtOffsetArray[4, 0] = new Vector2Int(99, 99);bodyShirtOffsetArray[5, 0] = new Vector2Int(99, 99);bodyShirtOffsetArray[0, 1] = new Vector2Int(99, 99);bodyShirtOffsetArray[1, 1] = new Vector2Int(99, 99);bodyShirtOffsetArray[2, 1] = new Vector2Int(99, 99);bodyShirtOffsetArray[3, 1] = new Vector2Int(99, 99);bodyShirtOffsetArray[4, 1] = new Vector2Int(99, 99);bodyShirtOffsetArray[5, 1] = new Vector2Int(99, 99);bodyShirtOffsetArray[0, 2] = new Vector2Int(99, 99);bodyShirtOffsetArray[1, 2] = new Vector2Int(99, 99);bodyShirtOffsetArray[2, 2] = new Vector2Int(99, 99);bodyShirtOffsetArray[3, 2] = new Vector2Int(99, 99);bodyShirtOffsetArray[4, 2] = new Vector2Int(99, 99);bodyShirtOffsetArray[5, 2] = new Vector2Int(99, 99);bodyShirtOffsetArray[0, 3] = new Vector2Int(99, 99);bodyShirtOffsetArray[1, 3] = new Vector2Int(99, 99);bodyShirtOffsetArray[2, 3] = new Vector2Int(99, 99);bodyShirtOffsetArray[3, 3] = new Vector2Int(99, 99);bodyShirtOffsetArray[4, 3] = new Vector2Int(99, 99);bodyShirtOffsetArray[5, 3] = new Vector2Int(99, 99);bodyShirtOffsetArray[0, 4] = new Vector2Int(99, 99);bodyShirtOffsetArray[1, 4] = new Vector2Int(99, 99);bodyShirtOffsetArray[2, 4] = new Vector2Int(99, 99);bodyShirtOffsetArray[3, 4] = new Vector2Int(99, 99);bodyShirtOffsetArray[4, 4] = new Vector2Int(99, 99);bodyShirtOffsetArray[5, 4] = new Vector2Int(99, 99);bodyShirtOffsetArray[0, 5] = new Vector2Int(99, 99);bodyShirtOffsetArray[1, 5] = new Vector2Int(99, 99);bodyShirtOffsetArray[2, 5] = new Vector2Int(99, 99);bodyShirtOffsetArray[3, 5] = new Vector2Int(99, 99);bodyShirtOffsetArray[4, 5] = new Vector2Int(99, 99);bodyShirtOffsetArray[5, 5] = new Vector2Int(99, 99);bodyShirtOffsetArray[0, 6] = new Vector2Int(99, 99);bodyShirtOffsetArray[1, 6] = new Vector2Int(99, 99);bodyShirtOffsetArray[2, 6] = new Vector2Int(99, 99);bodyShirtOffsetArray[3, 6] = new Vector2Int(99, 99);bodyShirtOffsetArray[4, 6] = new Vector2Int(99, 99);bodyShirtOffsetArray[5, 6] = new Vector2Int(99, 99);bodyShirtOffsetArray[0, 7] = new Vector2Int(99, 99);bodyShirtOffsetArray[1, 7] = new Vector2Int(99, 99);bodyShirtOffsetArray[2, 7] = new Vector2Int(99, 99);bodyShirtOffsetArray[3, 7] = new Vector2Int(99, 99);bodyShirtOffsetArray[4, 7] = new Vector2Int(99, 99);bodyShirtOffsetArray[5, 7] = new Vector2Int(99, 99);bodyShirtOffsetArray[0, 8] = new Vector2Int(99, 99);bodyShirtOffsetArray[1, 8] = new Vector2Int(99, 99);bodyShirtOffsetArray[2, 8] = new Vector2Int(99, 99);bodyShirtOffsetArray[3, 8] = new Vector2Int(99, 99);bodyShirtOffsetArray[4, 8] = new Vector2Int(99, 99);bodyShirtOffsetArray[5, 8] = new Vector2Int(99, 99);bodyShirtOffsetArray[0, 9] = new Vector2Int(99, 99);bodyShirtOffsetArray[1, 9] = new Vector2Int(99, 99);bodyShirtOffsetArray[2, 9] = new Vector2Int(99, 99);bodyShirtOffsetArray[3, 9] = new Vector2Int(99, 99);bodyShirtOffsetArray[4, 9] = new Vector2Int(99, 99);bodyShirtOffsetArray[5, 9] = new Vector2Int(99, 99);bodyShirtOffsetArray[0, 10] = new Vector2Int(4, 11);bodyShirtOffsetArray[1, 10] = new Vector2Int(4, 10);bodyShirtOffsetArray[2, 10] = new Vector2Int(4, 11);bodyShirtOffsetArray[3, 10] = new Vector2Int(4, 12);bodyShirtOffsetArray[4, 10] = new Vector2Int(4, 11);bodyShirtOffsetArray[5, 10] = new Vector2Int(4, 10);bodyShirtOffsetArray[0, 11] = new Vector2Int(4, 11);bodyShirtOffsetArray[1, 11] = new Vector2Int(4, 12);bodyShirtOffsetArray[2, 11] = new Vector2Int(4, 11);bodyShirtOffsetArray[3, 11] = new Vector2Int(4, 10);bodyShirtOffsetArray[4, 11] = new Vector2Int(4, 11);bodyShirtOffsetArray[5, 11] = new Vector2Int(4, 12);bodyShirtOffsetArray[0, 12] = new Vector2Int(3, 9);bodyShirtOffsetArray[1, 12] = new Vector2Int(3, 9);bodyShirtOffsetArray[2, 12] = new Vector2Int(4, 10);bodyShirtOffsetArray[3, 12] = new Vector2Int(4, 9);bodyShirtOffsetArray[4, 12] = new Vector2Int(4, 9);bodyShirtOffsetArray[5, 12] = new Vector2Int(4, 9);bodyShirtOffsetArray[0, 13] = new Vector2Int(4, 10);bodyShirtOffsetArray[1, 13] = new Vector2Int(4, 9);bodyShirtOffsetArray[2, 13] = new Vector2Int(5, 9);bodyShirtOffsetArray[3, 13] = new Vector2Int(5, 9);bodyShirtOffsetArray[4, 13] = new Vector2Int(4, 10);bodyShirtOffsetArray[5, 13] = new Vector2Int(4, 9);bodyShirtOffsetArray[0, 14] = new Vector2Int(4, 9);bodyShirtOffsetArray[1, 14] = new Vector2Int(4, 12);bodyShirtOffsetArray[2, 14] = new Vector2Int(5, 7);bodyShirtOffsetArray[3, 14] = new Vector2Int(5, 5);bodyShirtOffsetArray[4, 14] = new Vector2Int(4, 9);bodyShirtOffsetArray[5, 14] = new Vector2Int(4, 12);bodyShirtOffsetArray[0, 15] = new Vector2Int(4, 8);bodyShirtOffsetArray[1, 15] = new Vector2Int(4, 5);bodyShirtOffsetArray[2, 15] = new Vector2Int(4, 9);bodyShirtOffsetArray[3, 15] = new Vector2Int(4, 12);bodyShirtOffsetArray[4, 15] = new Vector2Int(4, 8);bodyShirtOffsetArray[5, 15] = new Vector2Int(4, 5);bodyShirtOffsetArray[0, 16] = new Vector2Int(4, 9);bodyShirtOffsetArray[1, 16] = new Vector2Int(4, 10);bodyShirtOffsetArray[2, 16] = new Vector2Int(4, 7);bodyShirtOffsetArray[3, 16] = new Vector2Int(4, 8);bodyShirtOffsetArray[4, 16] = new Vector2Int(4, 9);bodyShirtOffsetArray[5, 16] = new Vector2Int(4, 10);bodyShirtOffsetArray[0, 17] = new Vector2Int(4, 7);bodyShirtOffsetArray[1, 17] = new Vector2Int(4, 8);bodyShirtOffsetArray[2, 17] = new Vector2Int(4, 9);bodyShirtOffsetArray[3, 17] = new Vector2Int(4, 10);bodyShirtOffsetArray[4, 17] = new Vector2Int(4, 7);bodyShirtOffsetArray[5, 17] = new Vector2Int(4, 8);bodyShirtOffsetArray[0, 18] = new Vector2Int(4, 10);bodyShirtOffsetArray[1, 18] = new Vector2Int(4, 9);bodyShirtOffsetArray[2, 18] = new Vector2Int(4, 9);bodyShirtOffsetArray[3, 18] = new Vector2Int(4, 10);bodyShirtOffsetArray[4, 18] = new Vector2Int(4, 9);bodyShirtOffsetArray[5, 18] = new Vector2Int(4, 9);bodyShirtOffsetArray[0, 19] = new Vector2Int(4, 10);bodyShirtOffsetArray[1, 19] = new Vector2Int(4, 9);bodyShirtOffsetArray[2, 19] = new Vector2Int(4, 9);bodyShirtOffsetArray[3, 19] = new Vector2Int(4, 10);bodyShirtOffsetArray[4, 19] = new Vector2Int(4, 9);bodyShirtOffsetArray[5, 19] = new Vector2Int(4, 9);bodyShirtOffsetArray[0, 20] = new Vector2Int(4, 10);bodyShirtOffsetArray[1, 20] = new Vector2Int(4, 9);bodyShirtOffsetArray[2, 20] = new Vector2Int(4, 9);bodyShirtOffsetArray[3, 20] = new Vector2Int(4, 10);bodyShirtOffsetArray[4, 20] = new Vector2Int(4, 9);bodyShirtOffsetArray[5, 20] = new Vector2Int(4, 9);}private void PopulateBodyAdornmentsOffsetArray(){bodyAdornmentsOffsetArray[0, 1] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[1, 1] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[2, 1] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[3, 1] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[4, 1] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[5, 1] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[0, 2] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[1, 2] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[2, 2] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[3, 2] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[4, 2] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[5, 2] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[0, 3] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[1, 3] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[2, 3] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[3, 3] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[4, 3] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[5, 3] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[0, 4] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[1, 4] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[2, 4] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[3, 4] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[4, 4] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[5, 4] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[0, 5] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[1, 5] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[2, 5] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[3, 5] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[4, 5] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[5, 5] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[0, 6] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[1, 6] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[2, 6] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[3, 6] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[4, 6] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[5, 6] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[0, 7] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[1, 7] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[2, 7] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[3, 7] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[4, 7] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[5, 7] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[0, 8] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[1, 8] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[2, 8] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[3, 8] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[4, 8] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[5, 8] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[0, 9] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[1, 9] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[2, 9] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[3, 9] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[4, 9] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[5, 9] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[0, 10] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[1, 10] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[2, 10] = new Vector2Int(0, 1 + 16);bodyAdornmentsOffsetArray[3, 10] = new Vector2Int(0, 2 + 16);bodyAdornmentsOffsetArray[4, 10] = new Vector2Int(0, 1 + 16);bodyAdornmentsOffsetArray[5, 10] = new Vector2Int(0, 0 + 16);bodyAdornmentsOffsetArray[0, 11] = new Vector2Int(0, 1 + 16);bodyAdornmentsOffsetArray[1, 11] = new Vector2Int(0, 2 + 16);bodyAdornmentsOffsetArray[2, 11] = new Vector2Int(0, 1 + 16);bodyAdornmentsOffsetArray[3, 11] = new Vector2Int(0, 0 + 16);bodyAdornmentsOffsetArray[4, 11] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[5, 11] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[0, 12] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[1, 12] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[2, 12] = new Vector2Int(0, 0 + 16);bodyAdornmentsOffsetArray[3, 12] = new Vector2Int(0, -1 + 16);bodyAdornmentsOffsetArray[4, 12] = new Vector2Int(0, -1 + 16);bodyAdornmentsOffsetArray[5, 12] = new Vector2Int(0, -1 + 16);bodyAdornmentsOffsetArray[0, 13] = new Vector2Int(0, 0 + 16);bodyAdornmentsOffsetArray[1, 13] = new Vector2Int(0, -1 + 16);bodyAdornmentsOffsetArray[2, 13] = new Vector2Int(1, -1 + 16);bodyAdornmentsOffsetArray[3, 13] = new Vector2Int(1, -1 + 16);bodyAdornmentsOffsetArray[4, 13] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[5, 13] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[0, 14] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[1, 14] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[2, 14] = new Vector2Int(0, -3 + 16);bodyAdornmentsOffsetArray[3, 14] = new Vector2Int(0, -5 + 16);bodyAdornmentsOffsetArray[4, 14] = new Vector2Int(0, -1 + 16);bodyAdornmentsOffsetArray[5, 14] = new Vector2Int(0, 1 + 16);bodyAdornmentsOffsetArray[0, 15] = new Vector2Int(0, -2 + 16);bodyAdornmentsOffsetArray[1, 15] = new Vector2Int(0, -5 + 16);bodyAdornmentsOffsetArray[2, 15] = new Vector2Int(0, -1 + 16);bodyAdornmentsOffsetArray[3, 15] = new Vector2Int(0, 2 + 16);bodyAdornmentsOffsetArray[4, 15] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[5, 15] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[0, 16] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[1, 16] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[2, 16] = new Vector2Int(0, -3 + 16);bodyAdornmentsOffsetArray[3, 16] = new Vector2Int(0, -2 + 16);bodyAdornmentsOffsetArray[4, 16] = new Vector2Int(0, -1 + 16);bodyAdornmentsOffsetArray[5, 16] = new Vector2Int(0, 0 + 16);bodyAdornmentsOffsetArray[0, 17] = new Vector2Int(0, -3 + 16);bodyAdornmentsOffsetArray[1, 17] = new Vector2Int(0, -2 + 16);bodyAdornmentsOffsetArray[2, 17] = new Vector2Int(0, -1 + 16);bodyAdornmentsOffsetArray[3, 17] = new Vector2Int(0, 0 + 16);bodyAdornmentsOffsetArray[4, 17] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[5, 17] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[0, 18] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[1, 18] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[2, 18] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[3, 18] = new Vector2Int(0, 0 + 16);bodyAdornmentsOffsetArray[4, 18] = new Vector2Int(0, -1 + 16);bodyAdornmentsOffsetArray[5, 18] = new Vector2Int(0, -1 + 16);bodyAdornmentsOffsetArray[0, 19] = new Vector2Int(0, 0 + 16);bodyAdornmentsOffsetArray[1, 19] = new Vector2Int(0, -1 + 16);bodyAdornmentsOffsetArray[2, 19] = new Vector2Int(0, -1 + 16);bodyAdornmentsOffsetArray[3, 19] = new Vector2Int(0, 0 + 16);bodyAdornmentsOffsetArray[4, 19] = new Vector2Int(0, -1 + 16);bodyAdornmentsOffsetArray[5, 19] = new Vector2Int(0, -1 + 16);bodyAdornmentsOffsetArray[0, 20] = new Vector2Int(0, 0 + 16);bodyAdornmentsOffsetArray[1, 20] = new Vector2Int(0, -1 + 16);bodyAdornmentsOffsetArray[2, 20] = new Vector2Int(0, -1 + 16);bodyAdornmentsOffsetArray[3, 20] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[4, 20] = new Vector2Int(99, 99);bodyAdornmentsOffsetArray[5, 20] = new Vector2Int(99, 99);}}
运行效果:
Select Adornments Style=1时:
Select Adornments Style=2时:
相关文章:

Unity3D仿星露谷物语开发60之定制角色其他部位
1、目标 上一篇中定制了角色的衬衫、手臂。 本篇中将定制角色其他部位的图形,包括:裤子、发型、皮肤、帽子等。 2、定制裤子 (1)修改ApplyCharacterCustomisation.cs脚本 我们需要设置一个输入框选择裤子的颜色。 // Select …...
C++动态链接库封装,供C#/C++ 等编程语言使用——C++动态链接库概述(总)
目录: 一、前言及背景1.1需求描述1.2常见编程语言对比1.3应用背景 二、C对外接口2.1C对外封装2.2基于目标平台封装接口形式 三、系列文章汇总 一、前言及背景 1.1需求描述 不同的编程语言,具有不同的编程生态环境,对于项目应用来说ÿ…...

Google机器学习实践指南(机器学习模型泛化能力)
🔥 Google机器学习(14)-机器学习模型泛化能力解析 Google机器学习(14)-机器学习模型泛化原理与优化(约10分钟) 一、泛化问题引入 ▲ 模型表现对比: 假设森林中树木健康状况预测模型: 图1:初始模型表现 …...

MySQL性能调优:Mysql8高频面试题汇总
1,主键和唯一键有什么区别? 主键不能重复,不能为空,唯一键不能重复,可以为空。 建立主键的目的是让外键来引用。 一个表最多只有一个主键,但可以有很多唯一键 2,MySQL常用的存储引擎有哪些&…...
Neo4j 数据建模:原理、技术与实践指南
Neo4j 作为领先的图数据库,其核心优势在于利用图结构直观地表达和高效地查询复杂关系。其数据建模理念与传统关系型数据库截然不同,专注于实体(节点)及其连接(关系)。以下基于官方文档,系统阐述其建模原理、关键技术、实用技巧及最佳实践: 一、 核心原理:以关系为中心…...
【数据结构知识分享】顺序表详解
一、存储结构 物理相邻性: 若元素 a 和 b 逻辑相邻,则它们在内存中的地址也连续(如 &a[i1] &a[i] sizeof(ElemType))。 内存布局x: 基地址 索引 元素大小,通过首地址直接计算任意位置地址。 …...

vue+elementUI+springboot实现文件合并前端展示文件类型
项目场景: element的table上传文件并渲染出文件名称点击所属行可以查看文件,并且可以导出合并文件,此文章是记录合并文档前端展示的帖子 解决方案: 后端定义三个工具类 分别是pdf,doc和word的excle的目前我没整 word的工具类 package com.sc.modules…...

高效绘制业务流程图!专业模板免费下载
在复杂的业务流程管理中,可视化工具已成为提升效能的核心基础设施。为助力开发者、项目经理及业务架构师高效落地流程标准化,本文将为你精选5套开箱即用的专业流程图模板。这些模板覆盖跨部门协作、电商订单、客户服务等高频场景,具备以下核心…...

Spring Boot + Prometheus 实现应用监控(基于 Actuator 和 Micrometer)
文章目录 Spring Boot Prometheus 实现应用监控(基于 Actuator 和 Micrometer)环境准备示例结构启动和验证验证 Spring Boot 应用Prometheus 抓取配置(静态方式)Grafana 面板配置总结 Spring Boot Prometheus 实现应用监控&…...

PowerBI企业运营分析—列互换式中国式报表分析
PowerBI企业运营分析—列互换式中国式报表分析 欢迎来到Powerbi小课堂,在竞争激烈的市场环境中,企业运营分析平台成为提升竞争力的核心工具。 该平台通过高效整合多源数据,并实时监控关键指标,能够迅速揭示业务表现的全貌&#…...

BugKu Web渗透之需要管理员
启动场景,打开网页,显示如下: 一般没有上面头绪的时候,就是两步:右键查看源代码 和 扫描网站目录。 步骤一: 右键查看源代码 和 扫描网站目录。 右键查看源代码没有发现异常。 于是扫描网站目录&…...
Java集合初始化:Lists.newArrayList vs new ArrayList()
文章目录 前言一、核心区别全景图二、代码实现深度对比1. 初始化方式对比2. 容量预分配机制 三、性能与底层原理1. 内存分配策略2. 基准测试数据(JMH) 四、Guava的进阶功能生态1. 集合转换2. 集合分片3. 不可变集合创建 五、最佳实践指南六、源码级实现解…...
VBA清空数据
列数转字母 Function CNtoW(ByVal num As Long) As String CNtoW Replace(Cells(1, num).Address(False, False), "1", "") End Function 字母转列数 Function CWtoN(ByVal AB As String) As Long CWtoN Range("a1:" & AB & &…...
【信息系统项目管理师-选择真题】2025上半年(第二批)综合知识答案和详解(回忆版)
更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 【第1题】【第2题】【第3题】【第4题】【第5题】【第6题】【第7题】【第8题】【第9题】【第10题】【第11题】【第12题】【第13题】【第14题】【第15题】【第16题】【第17题】【第18题】【第19题】【第20题】【第…...
Java Lambda 表达式的缺点和替代方案
Java 8 引入的 Lambda 表达式曾被誉为编写简洁、函数式代码的革命性工具。但说实话,它们并不是万能钥匙。它有不少问题,比如它没有宣传的那么易读,在某些场景下还带来性能开销。 作为一名多年与 Java 冗长语法搏斗的开发者,我找到了更注重清晰、可维护性和性能的替代方案。…...

TDengine 开发指南—— UDF函数
UDF 简介 在某些应用场景中,应用逻辑需要的查询功能无法直接使用内置函数来实现,TDengine 允许编写用户自定义函数(UDF),以便解决特殊应用场景中的使用需求。UDF 在集群中注册成功后,可以像系统内置函数一…...

使用vsftpd搭建FTP服务器(TLS/SSL显式加密)
安装vsftpd服务 使用vsftpd RPM安装包安装即可,如果可以访问YUM镜像源,通过dnf或者yum工具更加方便。 yum -y install vsftpd 启动vsftpd、查看服务状态 systemctl enable vsftpd systemctl start vsftpd systemctl status vsftpd 备份配置文件并进…...

1.1Nodejs和浏览器中的二进制处理
Buffer 在 Node.js 中,Buffer 类用于处理二进制数据。由于 JavaScript 在浏览器环境中主要用于处理字符串和数字等类型的数据,对二进制数据的处理能力较弱,因此 Node.js 引入了 Buffer 类来弥补这一不足,特别是在处理文件系统操作…...

入门AJAX——XMLHttpRequest(Post)
一、前言 在上篇文章中,我们已经介绍了 HMLHttpRequest 的GET 请求的基本用法,并基于我提供的接口练习了两个简单的例子。如果你还没有看过第一篇文章,强烈建议你在学习完上篇文章后再学习本篇文章: 🔗入门AJAX——XM…...

Qt(part1)Qpushbutton,信号与槽,对象树,自定义信号与槽,lamda表达式。
1、创建Qt程序 2、命名规范及快捷键 3、Qpushbutton按钮创建 4、对象树概念 5、信号与槽 6、自定义信号与槽 7、当自定义信号和槽发生重载时 8、信号可以连接信号,信号也可以断开。 9、lamda表达式...

西北某省级联通公司:3D动环模块如何实现机房“一屏统管”?
一、运营商机房监控痛点凸显 在通信行业快速发展的当下,西北某省级联通公司肩负着保障区域通信畅通的重任。然而,公司分布广泛的机房面临着诸多监控难题,尤其是偏远机房环境风险无法实时感知这一痛点,严重影响了机房的稳定运行和通…...
【WPF】从普通 ItemsControl 到支持筛选的 ItemsControl:深入掌握 CollectionViewSource 用法
✨ 从普通 ItemsControl 到支持筛选的 ItemsControl:深入掌握 CollectionViewSource 用法 在日常 WPF 开发中,我们经常需要对数据进行筛选、排序、分组等操作,而原生的 ItemsControl 并不直接支持这些功能。本文将介绍如何通过 CollectionVi…...
Zookeeper 和 Kafka 版本与 JDK 要求
Apache Zookeeper 和 Apache Kafka 在不同版本中对 JDK 的要求如下表所示(基于官方文档和历史版本记录整理): 1. Zookeeper 版本与 JDK 要求 Zookeeper 版本要求的最低 JDK 版本说明3.4.x 系列JDK 6生产环境建议用 JDK 8(旧版兼容性强)。3.5.x 系列(3.5.5+)JDK 83.5.0 …...
3步布局关键词让流量更精准
其实流量不精准,90% 是关键词没布局好! 掌握这 3 个超实用技巧,让你的内容精准推给目标人群! 第一步:深挖高潜力关键词 别再一股脑用 “好看”“好用” 这些泛词啦!打开平台搜索框,输入核心词…...

视觉分析在人员行为属性检测中的应用
基于视觉分析的人员行为属性检测方案 一、背景与需求分析 在工业生产、建筑施工、公共安全等领域,人员行为属性的合规性检测是保障安全生产的关键环节。例如,工地工人未佩戴安全帽、厨房人员未佩戴手套、作业现场人员使用手机等行为,均可能…...
学习 React【Plan - June - Week 1】
一、使用 JSX 书写标签语言 JSX 是一种 JavaScript 的语法扩展,React 使用它来描述用户界面。 什么是 JSX? JSX 是 JavaScript 的一种语法扩展。看起来像 HTML,但它实际上是在 JavaScript 代码中写 XML/HTML。浏览器并不能直接运行 JSX&…...

电子行业AI赋能软件开发经典案例——某金融软件公司
01.案例标题 金融行业某金融软件公司通过StarShip CodeSouler达成效率突破性增长,零流程侵入验证AI代码高度可行性 02.执行摘要 某金融软件公司在核心产品研发中引入开放传神(OpenCSG)的StarShip CodeSouler AI代码生成平台,在无…...
【前端】js如何处理计算精度问题
JavaScript 的精度问题源于其遵循 IEEE 754 标准的 64 位双精度浮点数表示法,导致 0.1 0.2 ! 0.3 等经典问题。以下是系统化的解决方案及适用场景: ⚙️ 一、整数转换法(适合简单运算) 将小数转换为整数运算后再还原࿰…...
使用 Python 自动化 Word 文档样式复制与内容生成
在办公自动化领域,如何高效地处理 Word 文档的样式和内容复制是一个常见需求。本文将通过一个完整的代码示例,展示如何利用 Python 的 python-docx 库实现 Word 文档样式的深度复制 和 动态内容生成,并结合知识库中的最佳实践优化文档处理流程…...
Kafka 核心架构与消息模型深度解析(二)
案例实战:Kafka 在实际场景中的应用 (一)案例背景与需求介绍 假设我们正在为一个大型电商平台构建数据处理系统。该电商平台拥有庞大的用户群体,每天会产生海量的订单数据、用户行为数据(如浏览、点击、收藏等&#…...