/// <summary> /// Update the specified UMA. /// </summary> /// <returns> /// Returns a bool, true if the UMA was successfully updated, false if it was unchanged. /// </returns> /// <param name='name'> /// The name of the GameObject containing the UMA. /// </param> /// <param name='human'> /// The UMAElements.HumanoidStructure to update the UMA. /// </param> /// <param name='meshDirty'> /// If set to <c>true</c> the mesh will be updated. This includes body parts, clothing, accessories, and attachments. /// </param> /// <param name='shapeDirty'> /// If set to <c>true</c> the shape of the UMA will be updated. This is usually only needed at character creation time, or at gametime to make an UMA fatter or thinner. /// </param> public static bool Update(string GOName, HumanoidStructure human, bool meshDirty, bool shapeDirty) { // are we initialized? if (!_initialized) { Debug.Log("UMAElements.HumanoidBuilder.Update: Attempted use before initialization. Must call HumanoidBuilder.Initialize(scale) first."); return(false); } // find the required UMA object GameObject thisUMA = GameObject.Find(GOName); if (thisUMA == null) { return(false); } // get the umaData UMAData thisUMAData = thisUMA.GetComponentInChildren <UMAData>(); if (thisUMAData == null) { return(false); } // set all the DataSet settings if (shapeDirty) { BuildUMAShape(thisUMAData, human, false); } if (meshDirty) { BuildUMASlots(thisUMAData, human, false); } // make it dirty so that it updates if (shapeDirty) { thisUMAData.isShapeDirty = true; } if (meshDirty) { thisUMAData.isMeshDirty = true; } if (meshDirty) { thisUMAData.isTextureDirty = true; } if (shapeDirty || meshDirty) { thisUMAData.Dirty(); } // rebuild the attachments if requied BuildUMAAttachments(thisUMAData, human, null); // all done return(true); }
private static void UMAFinished(UMAData thisUMAData) { HumanoidStructure human = GetHumanoid(thisUMAData.gameObject.name); AttachmentPoints points = thisUMAData.gameObject.AddComponent <AttachmentPoints>(); BuildUMAAttachments(thisUMAData, human, points); }
//When UMA has finished loaded: private void UMAFemaleFinished(UMAData umaData) { // and finally lets give him a sword HumanoidStructure.AttachmentsAdd(humanf, "Item AngelicSword 01"); // activate his sword HumanoidStructure.AttachmentSetActive(humanf, "Item AngelicSword 01"); // Update UMA HumanoidBuilder.Update(myumaf.name, humanf, false, false); }
void Update() { // holster/ready weapon if (Input.GetKeyUp(KeyCode.Z)) { if (HumanoidStructure.AttachcmentIsActive(human, "Item AngelicSword 01")) { HumanoidStructure.AttachmentSetDefault(human, "Item AngelicSword 01"); } else { HumanoidStructure.AttachmentSetActive(human, "Item AngelicSword 01"); } HumanoidBuilder.Update(myuma.name, human, false, false); } // toggle trousers with recoloring if (Input.GetKeyUp(KeyCode.X)) { if (HumanoidStructure.WardrobeHasElement(human, "Male Jeans 01")) { HumanoidStructure.WardrobeRemove(human, "Male Jeans 01"); } else { int c1 = Random.Range(1, 20); HumanoidStructure.WardrobeAdd(human, "Male Jeans 01", c1); } HumanoidBuilder.Update(myuma.name, human, true, false); } // change chainmail dye colors if (Input.GetKeyUp(KeyCode.C)) { HumanoidStructure.WardrobeRemove(human, "MaleShirt 01"); int c1 = Random.Range(1, 20); int c2 = Random.Range(1, 20); int c3 = Random.Range(1, 20); HumanoidStructure.WardrobeAdd(human, "MaleShirt 01", c1, c2, c3); HumanoidBuilder.Update(myuma.name, human, true, false); } }
//private static void AddAttachment public static void BuildUMAAttachments(UMAData thisUMAData, HumanoidStructure human, AttachmentPoints aPoints) { if (aPoints == null) { // get the attachment points component aPoints = thisUMAData.gameObject.GetComponent <AttachmentPoints>(); if (aPoints == null) { Debug.LogError("UMAElements.HumanoidBuilder.BuildUMAAttachments: Could not find AttachmentPoints script on UMA"); return; } } // remove all current attachments for (int i = 1; i < aPoints.Points.Length; i++) { int childcount = aPoints.Points[i].childCount; for (int c = childcount - 1; c >= 0; c--) { GameObject.Destroy(aPoints.Points[i].GetChild(c).gameObject); } } // iterate through the list of attachments and see what we need to add for (int i = 0; i < human.Attachments.Count; i++) { // what position is this attachment in? int position = (int)human.Attachments[i].element.attachmentDefaultPos; if (human.Attachments[i].attachmentIsActive) { position = (int)human.Attachments[i].element.attachmentActivePos; } // instantiate the prefab GameObject attachment = GameObject.Instantiate(human.Attachments[i].element.prefabItem) as GameObject; attachment.name = human.Attachments[i].element.prefabItem.name; attachment.transform.parent = aPoints.Points[position]; attachment.transform.localPosition = Vector3.zero; attachment.transform.localRotation = Quaternion.Euler(Vector3.zero); } }
/// <summary> /// Create a new UMA from a given HumanoidStructure. /// </summary> /// <returns> /// Returns a reference to the created GameObject containing the generated UMA. /// </returns> /// <param name='name'> /// The name given to the GameObject in the heirarchy. /// </param> /// <param name='position'> /// The Vector3 position to give the new UMA. /// </param> /// <param name='layer'> /// The layer to put the UMA in, or 0 for the default layer /// </param> /// <param name='human'> /// The UMAElements.HumanoidStructure to build from. /// </param> /// <param name='useRigidBody'> /// Whether to keep a RigidBody on the new UMA. /// </param> /// <param name='useCharController'> /// Whether to add a CharacterController to the new UMA. /// </param> /// <param name='animationController'> /// If null, will keep the original Locomotion script, or use the given RuntimeAnimationController. /// </param> public static GameObject Create(HumanoidStructure human, string name, RuntimeAnimatorController animationController, Vector3 position = default(Vector3), int layer = 0, bool useRigidBody = true, bool useCharController = true) { // are we initialized? if (!_initialized) { Debug.LogError("UMAElements.HumanoidBuilder.Create: Attempted use before initialization. Must call HumanoidBuilder.Initialize(scale) first."); return(null); } // create a new UMARecipe GameObject thisUMA = new GameObject(name); UMADynamicAvatar dynamicAvatar = thisUMA.AddComponent <UMADynamicAvatar>(); dynamicAvatar.Initialize(); UMAData thisUMAData = dynamicAvatar.umaData; dynamicAvatar.umaGenerator = _generator; thisUMAData.umaGenerator = _generator; var umaRecipe = dynamicAvatar.umaData.umaRecipe; thisUMAData.OnCharacterCreated += UMAFinished; // race and gender bool found = false; if (human.gender == 'M') { umaRecipe.SetRace(_raceLibrary.GetRace("HumanMale")); found = true; } else if (human.gender == 'F') { umaRecipe.SetRace(_raceLibrary.GetRace("HumanFemale")); found = true; } if (!found) { Debug.LogError("UMAElements.HumanoidBuilder.Create: Incorrect gender given as '" + human.gender + "'. UMA could not be built."); return(null); } // do the build (this is the same as update) thisUMAData.atlasResolutionScale = _atlasScale; BuildUMAShape(thisUMAData, human, true); BuildUMASlots(thisUMAData, human, true); // remove the rigidbody (if required) if (useRigidBody) { thisUMA.AddComponent <Rigidbody>(); } // add a character controller (if required) if (useCharController) { CapsuleCollider chc = thisUMA.AddComponent <CapsuleCollider>(); chc.radius = 0.0015f * human.height; chc.height = (human.height / 100.0f); chc.center = new Vector3(0, chc.height / 2.0f, 0); } // add the correct animator (if required) if (animationController != null) { dynamicAvatar.animationController = animationController; } // put the uma in the correct position thisUMA.transform.position = position; // ensure that all elements of the uma are set to the "Entities" layer thisUMA.layer = layer; foreach (Transform t in thisUMA.GetComponentsInChildren <Transform>()) { t.gameObject.layer = layer; } dynamicAvatar.UpdateNewRace(); Humanoid tmp = new Humanoid(); tmp.name = name; tmp.human = human; _charList.Add(tmp); // finally return this UMA's game object return(thisUMA); }
// private method to build the UMA slots private static void BuildUMASlots(UMA.UMAData thisUMAData, HumanoidStructure human, bool isNewUMA) { // the slot list one for each element in UMAElementsPositions.BuildSlots thisUMAData.umaRecipe.slotDataList = new SlotData[40]; // now we add the items from the BODY elements list one at a time for (int i = 0; i < human.Body.Count; i++) { if (human.Body[i] == null) { continue; } // instantiate the body slot in this element at the correct position if (human.Body[i].element.slotItem) { thisUMAData.umaRecipe.slotDataList[(int)human.Body[i].element.buildPos] = InstantiateSlot(human.Body[i].element.slotItem); } // add the body overlay to this position if (human.Body[i].element.overlayItem) { if (human.Body[i].colors == null) { thisUMAData.umaRecipe.slotDataList[(int)human.Body[i].element.buildPos].AddOverlay(InstantiateOverlay(human.Body[i].element.overlayItem, human.Body[i].color)); } else if (human.Body[i].colors.Count == 0) { thisUMAData.umaRecipe.slotDataList[(int)human.Body[i].element.buildPos].AddOverlay(InstantiateOverlay(human.Body[i].element.overlayItem, Color.white)); } else if (human.Body[i].colors.Count == 1) { thisUMAData.umaRecipe.slotDataList[(int)human.Body[i].element.buildPos].AddOverlay(InstantiateOverlay(human.Body[i].element.overlayItem, GamePalette.BodySwatch[human.Body[i].colors[0]].color)); } else if (human.Body[i].colors.Count == 3) { thisUMAData.umaRecipe.slotDataList[(int)human.Body[i].element.buildPos].AddOverlay(InstantiateOverlay(human.Body[i].element.overlayItem, Color.white)); thisUMAData.umaRecipe.slotDataList[(int)human.Body[i].element.buildPos].GetOverlay(human.Body[i].element.overlayItem.asset.overlayName).asset.textureList[0] = human.Body[i].dyedDiffuse; } } // hide any slots that need it foreach (Positions.BuildSlots pos in human.Body[i].element.hides) { thisUMAData.umaRecipe.slotDataList[(int)pos] = null; } } // instantiate the wardrobe slot in this element at the correct position for (int i = 0; i < human.Wardrobe.Count; i++) { // instantiate all the slots in this element if (human.Wardrobe[i].element.slotItem) { thisUMAData.umaRecipe.slotDataList[(int)human.Wardrobe[i].element.buildPos] = InstantiateSlot(human.Wardrobe[i].element.slotItem); } // add the body overlay to this position if (human.Wardrobe[i].element.overlayItem) { if (human.Wardrobe[i].colors == null) { thisUMAData.umaRecipe.slotDataList[(int)human.Wardrobe[i].element.buildPos].AddOverlay(InstantiateOverlay(human.Wardrobe[i].element.overlayItem, human.Body[i].color)); } else if (human.Wardrobe[i].colors.Count == 0) { thisUMAData.umaRecipe.slotDataList[(int)human.Wardrobe[i].element.buildPos].AddOverlay(InstantiateOverlay(human.Wardrobe[i].element.overlayItem, Color.white)); } else if (human.Wardrobe[i].colors.Count == 1) { thisUMAData.umaRecipe.slotDataList[(int)human.Wardrobe[i].element.buildPos].AddOverlay(InstantiateOverlay(human.Wardrobe[i].element.overlayItem, GamePalette.DyeSwatch[human.Wardrobe[i].colors[0]].color)); } else if (human.Wardrobe[i].colors.Count == 3) { thisUMAData.umaRecipe.slotDataList[(int)human.Wardrobe[i].element.buildPos].AddOverlay(InstantiateOverlay(human.Wardrobe[i].element.overlayItem, Color.white)); thisUMAData.umaRecipe.slotDataList[(int)human.Wardrobe[i].element.buildPos].GetOverlay(human.Wardrobe[i].element.overlayItem.asset.overlayName).asset.textureList[0] = human.Wardrobe[i].dyedDiffuse; } } // hide any slots that need it foreach (Positions.BuildSlots pos in human.Wardrobe[i].element.hides) { thisUMAData.umaRecipe.slotDataList[(int)pos] = null; } } }
// private method to build the UMA shape private static void BuildUMAShape(UMAData thisUMAData, HumanoidStructure human, bool isNewUMA) { UMADnaHumanoid thisUMAdna; // if it already exists - clear out the old data if (!isNewUMA) { thisUMAData.umaRecipe.ClearDna(); } // create a new set of data thisUMAdna = new UMADnaHumanoid(); thisUMAData.umaRecipe.AddDna(thisUMAdna); // thisUMAData.umaRecipe.umaDna.Add(thisUMAdna.GetType(), thisUMAdna); // set the height to 0.5f (using scale is better than changing this, but that's for you the game dev to decide) thisUMAdna.height = 0.5f; // muscle v weight thisUMAdna.upperMuscle = human.upperMuscle; thisUMAdna.upperWeight = human.upperWeight + human.upperMuscle; if (thisUMAdna.upperWeight > 1.0) { thisUMAdna.upperWeight = 1.0f; } if (thisUMAdna.upperWeight < 0.0) { thisUMAdna.upperWeight = 0.0f; } thisUMAdna.lowerMuscle = human.lowerMuscle + thisUMAdna.upperMuscle; if (thisUMAdna.lowerMuscle > 1.0) { thisUMAdna.lowerMuscle = 1.0f; } if (thisUMAdna.lowerMuscle < 0.0) { thisUMAdna.lowerMuscle = 0.0f; } thisUMAdna.lowerWeight = human.lowerWeight + thisUMAdna.upperWeight; if (thisUMAdna.lowerWeight > 1.0) { thisUMAdna.lowerWeight = 1.0f; } if (thisUMAdna.lowerWeight < 0.0) { thisUMAdna.lowerWeight = 0.0f; } // set the body shape thisUMAdna.armLength = human.armLength; thisUMAdna.forearmLength = human.forearmLength; thisUMAdna.legSeparation = human.legSeparation; thisUMAdna.handsSize = human.handSize; thisUMAdna.feetSize = human.feetSize; thisUMAdna.legsSize = human.legsSize; thisUMAdna.armWidth = human.armWidth; thisUMAdna.forearmWidth = human.forearmWidth; thisUMAdna.breastSize = human.breastSize; thisUMAdna.belly = human.belly; thisUMAdna.waist = human.waist; thisUMAdna.gluteusSize = human.gluteusSize; // set the head shape thisUMAdna.headSize = human.headSize; thisUMAdna.headWidth = human.headWidth; thisUMAdna.neckThickness = human.neckThickness; // set the facial morphs - ears thisUMAdna.earsSize = human.earsSize; thisUMAdna.earsPosition = human.earsPosition; thisUMAdna.earsRotation = human.earsRotation; // set the facial morphs - nose thisUMAdna.noseSize = human.noseSize; thisUMAdna.noseCurve = human.noseCurve; thisUMAdna.noseWidth = human.noseWidth; thisUMAdna.noseInclination = human.noseInclination; thisUMAdna.nosePosition = human.nosePosition; thisUMAdna.nosePronounced = human.nosePronounced; thisUMAdna.noseFlatten = human.noseFlatten; // set the facial morphs - chin thisUMAdna.chinSize = human.chinSize; thisUMAdna.chinPronounced = human.chinPronounced; thisUMAdna.chinPosition = human.chinPosition; // set the facial morphs - jaw thisUMAdna.mandibleSize = human.mandibleSize; thisUMAdna.jawsSize = human.jawsSize; thisUMAdna.jawsPosition = human.jawsPosition; // set the facial morphs - cheeks thisUMAdna.cheekSize = human.cheekSize; thisUMAdna.cheekPosition = human.cheekPosition; thisUMAdna.lowCheekPronounced = human.lowCheekPronounced; thisUMAdna.lowCheekPosition = human.lowCheekPosition; // set the facial morphs - forehead thisUMAdna.foreheadSize = human.foreheadSize; thisUMAdna.foreheadPosition = human.foreheadPosition; // set the facial morphs - mouth thisUMAdna.lipsSize = human.lipsSize; thisUMAdna.mouthSize = human.mouthSize; // eye size and rotation thisUMAdna.eyeSize = human.eyeSize; thisUMAdna.eyeRotation = human.eyeRotation; }
void Start() { // let's start by initialising the builder with the atlas scale of half HumanoidBuilder.Initialize(1.0f); // now let's generate a humanoid male human = new HumanoidStructure('M'); // set the basic body slots. // Use color indexes from the GamePalette.cs HumanoidStructure.BodyAdd(human, "Human Male Eyes 01"); HumanoidStructure.BodyAdd(human, "Human Male Head 01", 4); HumanoidStructure.BodyAdd(human, "Human Male HeadEars 01", 4); HumanoidStructure.BodyAdd(human, "Human Male HeadEyes 01", 4); HumanoidStructure.BodyAdd(human, "Human Male HeadMouth 01", 4); HumanoidStructure.BodyAdd(human, "Human Male HeadNose 01", 4); HumanoidStructure.BodyAdd(human, "Human Male Head InnerMouth"); HumanoidStructure.BodyAdd(human, "Human Male Torso 01", 4); HumanoidStructure.BodyAdd(human, "Human Male Hands 01", 4); HumanoidStructure.BodyAdd(human, "Human Male Legs 01", 4); HumanoidStructure.BodyAdd(human, "Human Male Feet 01", 4); // let's add some clothing HumanoidStructure.WardrobeAdd(human, "Male Jeans 01", 12); HumanoidStructure.WardrobeAdd(human, "MaleShirt 01", 1); // just a test of packing a human ( just a proof it all works) string testpack = HumanoidStructure.Pack(human); Debug.Log(testpack); Debug.Log("Pack size " + testpack.Length); // now lets unpack and generate the uma (we're using the packed version just to show that packing/unpacking works) HumanoidStructure testhuman = HumanoidStructure.Unpack(testpack); myuma = HumanoidBuilder.Create(testhuman, "myumaM", animController, new Vector3(0.5f, 0, 0), 0, false, true); //Set up a callback thats run when UMA has finished loading myuma.GetComponent <UMAData>().OnCharacterCreated += UMAMaleFinished; // now let's generate a humanoid female humanf = new HumanoidStructure('F'); // you can add tails, horns, eyelashes, etc after these basics // but the build order is vital to keep attachment vertex indecies // This time we use Color32 to set the color instead. HumanoidStructure.BodyAdd(humanf, "Human Female Eyes 01"); HumanoidStructure.BodyAdd(humanf, "Human Female Head 01", new Color32(188, 188, 188, 255)); HumanoidStructure.BodyAdd(humanf, "Human Female HeadEars 01", new Color32(188, 188, 188, 255)); HumanoidStructure.BodyAdd(humanf, "Human Female HeadEyes 01", new Color32(188, 188, 188, 255)); HumanoidStructure.BodyAdd(humanf, "Human Female HeadMouth 01", new Color32(188, 188, 188, 255)); HumanoidStructure.BodyAdd(humanf, "Human Female HeadNose 01", new Color32(188, 188, 188, 255)); HumanoidStructure.BodyAdd(humanf, "Human Female Head InnerMouth"); HumanoidStructure.BodyAdd(humanf, "Human Female Torso 01", new Color32(188, 188, 188, 255)); HumanoidStructure.BodyAdd(humanf, "Human Female Hands 01", new Color32(188, 188, 188, 255)); HumanoidStructure.BodyAdd(humanf, "Human Female Legs 01", new Color32(188, 188, 188, 255)); HumanoidStructure.BodyAdd(humanf, "Human Female Feet 01", new Color32(188, 188, 188, 255)); // let's add some clothing HumanoidStructure.WardrobeAdd(humanf, "MaleShirt 01", 2); // just a test of packing a human ( just a proof it all works) string testpackf = HumanoidStructure.Pack(humanf); Debug.Log(testpackf); Debug.Log("Pack size " + testpackf.Length); // now lets unpack and generate the uma HumanoidStructure testhumanf = HumanoidStructure.Unpack(testpackf); myumaf = HumanoidBuilder.Create(testhumanf, "myumaF", animController, new Vector3(-0.5f, 0, 0), 0, false, true); //Set up a callback thats run when UMA has finished loading myumaf.GetComponent <UMAData>().OnCharacterCreated += UMAFemaleFinished; }