/// <summary> /// Creates a mount point at run-time. This won't persist unless you /// serialize the data yourself during run-time. /// </summary> /// <param name="rName">Name of the mount point</param> /// <param name="rBoneName">Bone name to attach it to or empty string to attach to root</param> /// <param name="rIgnoreParentScale">Determines if we should ignore the parent object's scale value</param> /// <returns></returns> public MountPoint CreateMountPoint(string rName, string rBoneName, bool rIgnoreParentScale) { // Create the mount point MountPoint lPoint = new MountPoint(); lPoint.Owner = gameObject; lPoint.Name = rName; lPoint.BoneName = rBoneName; // Attach it to the right bone Transform lParentTransform = gameObject.transform; lPoint.Anchor = new GameObject(); lPoint.Anchor.name = "MP_" + lPoint.Anchor.GetInstanceID(); if (lPoint.BoneName.Length > 0) { Animator lAnimator = gameObject.GetComponent <Animator>(); if (lAnimator != null) { int lBoneIndex = MountPoints.GetHumanBodyBoneID(lPoint.BoneName); if (lBoneIndex >= 0 && lBoneIndex <= (int)HumanBodyBones.LastBone) { lParentTransform = lAnimator.GetBoneTransform((HumanBodyBones)lBoneIndex); } else { Transform lBoneTransform = MountPoints.FindBone(transform, lPoint.BoneName); if (lBoneTransform != null) { lParentTransform = lBoneTransform; } } } } lPoint.Anchor.transform.position = lParentTransform.position; lPoint.Anchor.transform.rotation = lParentTransform.rotation; lPoint.Anchor.transform.parent = lParentTransform; // Initialize by ignoring the scale lPoint.IgnoreParentScale = rIgnoreParentScale; // Add to the list of mount points Points.Add(lPoint); // Return the point return(lPoint); }
/// <summary> /// Anchors the mount point to the specified bone, essencially making /// this mount point a child of the bone. /// </summary> /// <param name="rBoneName">Bone name to anchor to or empty string to anchor to the root</param> public void AnchorTo(string rBoneName) { Transform lParentTransform = _Owner.transform; if (_Anchor == null) { _Anchor = new GameObject(); _Anchor.name = "MP_" + _Anchor.GetInstanceID(); } _BoneName = rBoneName; if (_BoneName.Length > 0) { Animator lAnimator = _Owner.GetComponent <Animator>(); if (lAnimator != null) { int lBoneIndex = MountPoints.GetHumanBodyBoneID(_BoneName); if (lBoneIndex >= 0 && lBoneIndex < (int)HumanBodyBones.LastBone) { lParentTransform = lAnimator.GetBoneTransform((HumanBodyBones)lBoneIndex); } else { Transform lBoneTransform = MountPoints.FindBone(_Owner.transform, _BoneName); if (lBoneTransform != null) { lParentTransform = lBoneTransform; } } } } // Parent the mount point to this new transform. We don't // change it's position or rotation since we may need an offset. _Anchor.transform.parent = lParentTransform; }
/// <summary> /// Creates an instance of the prefab at the resource path /// </summary> /// <param name="rParent">MountPoints that will be the parent of the instance</param> /// <returns>Instance that was created</returns> public GameObject CreateInstance(MountPoints rParent) { if (_ResourcePath.Length == 0) { return(null); } // Extract out the parent's skinned mesh renderer. This should be a high level // renderer that contains all the bones we'll need. SkinnedMeshRenderer lParentSMR = rParent._Renderer; if (lParentSMR == null) { lParentSMR = rParent.gameObject.GetComponent <SkinnedMeshRenderer>(); } if (lParentSMR == null) { lParentSMR = rParent.gameObject.GetComponentInChildren <SkinnedMeshRenderer>(); } if (lParentSMR == null) { return(null); } // Create the child UnityEngine.Object lResource = Resources.Load(_ResourcePath); #if UNITY_EDITOR if (lResource == null) { lResource = UnityEditor.AssetDatabase.LoadAssetAtPath <GameObject>("Assets\\" + _ResourcePath); } if (lResource == null) { lResource = UnityEditor.AssetDatabase.LoadAssetAtPath <GameObject>("Assets\\" + _ResourcePath + ".prefab"); } if (lResource == null) { lResource = UnityEditor.AssetDatabase.LoadAssetAtPath <GameObject>("Assets\\" + _ResourcePath + ".fbx"); } #endif if (lResource == null) { return(null); } _GameObject = (GameObject)GameObject.Instantiate(lResource); if (_GameObject == null) { return(null); } //NetworkServer.Spawn(_GameObject); // Don't show the child in the hierarchy //lChild.hideFlags = HideFlags.HideInHierarchy; // Extract out the Skinned Mesh Renderers SkinnedMeshRenderer[] lChildSMRs = _GameObject.GetComponents <SkinnedMeshRenderer>(); if (lChildSMRs == null || lChildSMRs.Length == 0) { lChildSMRs = _GameObject.GetComponentsInChildren <SkinnedMeshRenderer>(); } // If there's no skinned mesh renderer, we can't really continue if (lChildSMRs == null || lChildSMRs.Length == 0) { DestroyInstance(); return(null); } // For each of the renderers, we need to set the bones List <Transform> lOldRootBones = new List <Transform>(); for (int i = 0; i < lChildSMRs.Length; i++) { SkinnedMeshRenderer lChildSMR = lChildSMRs[i]; Cloth lChildSMRCloth = lChildSMR.gameObject.GetComponent <Cloth>(); // Parent it to the parent _GameObject.transform.parent = rParent.gameObject.transform; _GameObject.transform.localPosition = Vector3.zero; _GameObject.transform.localRotation = Quaternion.identity; _GameObject.transform.localScale = Vector3.one; // Go through the bones of the new SM and try to find matching // bones from the parent List <Transform> lChildBones = new List <Transform>(); List <Transform> lTargetBones = new List <Transform>(); for (int j = 0; j < lChildSMR.bones.Length; j++) { Transform lChildBone = lChildSMR.bones[j]; Transform lTargetBone = null; for (int k = 0; k < lParentSMR.bones.Length; k++) { if (MountPoints.CompareBoneNames(lParentSMR.bones[k].name, lChildBone.name)) { lTargetBone = lParentSMR.bones[k]; break; } } if (lTargetBone == null) { lTargetBone = MountPoints.FindBone(rParent.gameObject.transform, lChildBone.name); } if (lTargetBone != null) { lChildBones.Add(lChildBone); lTargetBones.Add(lTargetBone); } } lChildSMR.bones = lTargetBones.ToArray(); // We want to grab the parent's bone that corresponds to our root. We don't // just take the parent's root bone since it could be different (ie for boots). if (!lOldRootBones.Contains(lChildSMR.rootBone)) { lOldRootBones.Add(lChildSMR.rootBone); } lChildSMR.rootBone = MountPoints.FindBone(rParent.gameObject.transform, lChildSMR.rootBone.name); // If we're dealing with clothe we need to reassign the colliders // Handle clothing if it exists. We may need to move colliders if (lChildSMRCloth != null && lChildSMRCloth.capsuleColliders != null) { List <CapsuleCollider> lTargetColliders = new List <CapsuleCollider>(); for (int j = 0; j < lChildSMRCloth.capsuleColliders.Length; j++) { if (lChildSMRCloth.capsuleColliders[j] == null) { lTargetColliders.Add(null); continue; } int lIndex = lChildBones.IndexOf(lChildSMRCloth.capsuleColliders[j].transform); // If the clothing bone has a collider, our real skeleton may need one too CapsuleCollider lChildCollider = lChildSMRCloth.capsuleColliders[j]; if (lChildCollider != null) { // If there's not one, create it CapsuleCollider lParentCollider = lTargetBones[lIndex].GetComponent <CapsuleCollider>(); if (lParentCollider == null) { lParentCollider = lTargetBones[lIndex].gameObject.AddComponent <CapsuleCollider>(); lParentCollider.GetCopyOf(lChildCollider); } // Change the collider in the clothing for (int k = 0; k < lChildSMRCloth.capsuleColliders.Length; k++) { if (lChildSMRCloth.capsuleColliders[k] == lChildCollider) { lTargetColliders.Add(lParentCollider); } } } } lChildSMRCloth.capsuleColliders = lTargetColliders.ToArray(); } // Set the update flag per request if (_UpdateWhenOffScreen) { lChildSMR.updateWhenOffscreen = _UpdateWhenOffScreen; } } // Destroy any old root bones for (int i = lOldRootBones.Count - 1; i >= 0; i--) { if (Application.isPlaying) { UnityEngine.GameObject.Destroy(lOldRootBones[i].gameObject); } else { UnityEngine.GameObject.DestroyImmediate(lOldRootBones[i].gameObject); } } // Destroy any old animators Animator[] lOldAnimators = _GameObject.GetComponents <Animator>(); if (lOldAnimators == null || lOldAnimators.Length == 0) { _GameObject.GetComponentsInChildren <Animator>(); } for (int i = lOldAnimators.Length - 1; i >= 0; i--) { if (Application.isPlaying) { UnityEngine.Component.Destroy(lOldAnimators[i]); } else { UnityEngine.Component.DestroyImmediate(lOldAnimators[i]); } } // Disable visibility if we need to if (!_IsVisible) { Renderer lRenderer = _GameObject.GetComponent <Renderer>(); if (lRenderer == null) { lRenderer = _GameObject.GetComponentInChildren <Renderer>(); } if (lRenderer != null) { lRenderer.enabled = false; } } // Return the new game object return(_GameObject); }