/// <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(HumanBodyBones rHumanBodyBoneID) { if (rHumanBodyBoneID < 0) { return; } if (rHumanBodyBoneID > HumanBodyBones.LastBone) { return; } _BoneName = ""; Transform lParentTransform = _Owner.transform; if (_Anchor == null) { _Anchor = new GameObject(); } Animator lAnimator = _Owner.GetComponent <Animator>(); if (lAnimator != null) { lParentTransform = lAnimator.GetBoneTransform(rHumanBodyBoneID); if (lParentTransform != null) { _BoneName = MountPoints.GetHumanBodyBoneName(rHumanBodyBoneID); } } // 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> /// Grab the closest mount point to any of the mount points in this list. /// </summary> /// <param name="rSourceMountPoints"></param> /// <returns></returns> public static MountPoint GetClosestMountPoint(MountPoints rSourceMountPoints) { MountPoint lMountPoint = null; float lDistance = float.MaxValue; for (int i = 0; i < rSourceMountPoints.Points.Count; i++) { MountPoint lSourceMountPoint = rSourceMountPoints.Points[i]; Vector3 lSourceMountPosition = lSourceMountPoint._Anchor.transform.position; MountPoint lTestMountPoint = GetClosestMountPoint(lSourceMountPosition, null, rSourceMountPoints); if (lTestMountPoint != null) { Vector3 lTestPosition = lTestMountPoint._Anchor.transform.position; float lTestDistance = Vector3.Distance(lSourceMountPosition, lTestPosition); if (lTestDistance < lDistance) { lDistance = lTestDistance; lMountPoint = lTestMountPoint; } } } return(lMountPoint); }
/// <summary> /// Conntects the child mount point to the parent /// </summary> /// <param name="rParent">String representing the parents mount point name</param> /// <param name="rChildItemPath">Resource path to the object we'll instanciate</param> /// <param name="rChildPointName">String representing the child's mount point name</param> /// <returns>GameObject that is the child that is instanciated</returns> public GameObject ConnectMountPoints(string rParentPoint, string rChildItemPath, string rChildPointName) { if (rChildItemPath.Length == 0) { return(null); } MountPoint lParentMP = GetMountPoint(rParentPoint); if (lParentMP == null) { return(null); } GameObject lChild = (GameObject)Instantiate(Resources.Load(rChildItemPath)); if (lChild == null) { return(null); } lChild.name = "Instanciated" + lChild.GetInstanceID(); MountPoint lChildMP = null; MountPoints lChildMPList = lChild.GetComponent <MountPoints>(); if (lChildMPList != null) { lChildMP = lChildMPList.GetMountPoint(rChildPointName); lChildMP.OwnerResourcePath = rChildItemPath; } else { Mount lChildMount = lChild.GetComponent <Mount>(); if (lChildMount != null) { lChildMP = lChildMount.Point; lChildMP.OwnerResourcePath = rChildItemPath; } } // If there is no mount point, get out if (lChildMP == null) { GameObject.DestroyObject(lChild); return(null); } // Finally, connect the objects ConnectMountPoints(lParentMP, lChildMP); // Return the newly created child return(lChild); }
/// <summary> /// Called when the script object is loaded /// </summary> void OnEnable() { LoadBoneNames(); // Grab the serialized objects mTarget = (MountPoints)target; mTargetSO = new SerializedObject(target); InstanciatePointList(); InstanciateItemList(); // Runs through all other objects and loads the mount point LoadOtherMountPoints(); }
/// <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> /// Conntects the child mount point to the parent /// </summary> /// <param name="rParent">String representing the parents mount point name</param> /// <param name="rChildItemPath">Resource path to the object we'll instanciate</param> /// <param name="rChildPointName">String representing the child's mount point name</param> /// <returns>GameObject that is the child that is instanciated</returns> public bool ConnectMountPoints(GameObject rParent, string rParentPoint) { if (rParent == null) { return(false); } MountPoints lParentMPs = rParent.GetComponent <MountPoints>(); if (lParentMPs == null) { return(false); } return(lParentMPs.ConnectMountPoints(rParentPoint, Point)); }
/// <summary> /// Conntects the child mount point to the parent /// </summary> /// <param name="rParent">String representing the parents mount point name</param> /// <param name="rChildItemPath">Resource path to the object we'll instanciate</param> /// <param name="rChildPointName">String representing the child's mount point name</param> /// <returns>GameObject that is the child that is instanciated</returns> public bool ConnectMountPoints(string rParentName, string rParentPoint) { GameObject lParent = GameObject.Find(rParentName); if (lParent == null) { return(false); } MountPoints lParentMPs = lParent.GetComponent <MountPoints>(); if (lParentMPs == null) { return(false); } return(lParentMPs.ConnectMountPoints(rParentPoint, Point)); }
/// <summary> /// Conntects the child mount point to the parent /// </summary> /// <param name="rParentPoint">String representing the parents mount point name</param> /// <param name="rChild">GameObject representing the child</param> /// <param name="rChildPointName">String representing the child mount point name</param> /// <returns>Boolean used to determine if the connection was made</returns> public bool ConnectMountPoints(string rParentPoint, GameObject rChild, string rChildPointName) { if (rChild == null) { return(false); } MountPoint lParentMP = GetMountPoint(rParentPoint); if (lParentMP == null) { return(false); } MountPoint lChildMP = null; MountPoints lChildMPList = rChild.GetComponent <MountPoints>(); if (lChildMPList != null) { lChildMP = lChildMPList.GetMountPoint(rChildPointName); } else { Mount lParentMount = rChild.GetComponent <Mount>(); if (lParentMount != null) { lChildMP = lParentMount.Point; } } // If there is no child, get out if (lChildMP == null) { return(false); } // Finally, connect the objects return(ConnectMountPoints(lParentMP, lChildMP)); }
/// <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> /// Raised when the object becomes active. Initialization can happen here. /// </summary> void Awake() { mMountPoints = GameObject.Find("DefaultMale").GetComponent<MountPoints>(); }
/// <summary> /// Determine if we're dealing with an actual prefab or an instance /// </summary> /// <param name="rMountPoints"></param> /// <returns></returns> private bool IsAddMountPointEnabled(MountPoints rMountPoints) { PrefabType lType = PrefabUtility.GetPrefabType(rMountPoints); return lType != PrefabType.Prefab; }
/// <summary> /// Given the position, find the closest mount point. However, we don't want that mount point to be part of the /// current Mount or MountPoints component. /// </summary> /// <param name="rPosition"></param> /// <param name="rSourceMount"></param> /// <param name="rSourceMountPoints"></param> /// <returns></returns> public static MountPoint GetClosestMountPoint(Vector3 rPosition, Mount rSourceMount, MountPoints rSourceMountPoints) { MountPoint lMountPoint = null; float lDistance = float.MaxValue; MountPoints[] lMountPoints = Component.FindObjectsOfType <MountPoints>(); for (int i = 0; i < lMountPoints.Length; i++) { if (lMountPoints[i] == rSourceMountPoints) { continue; } for (int j = 0; j < lMountPoints[i].Points.Count; j++) { Vector3 lTestPosition = lMountPoints[i].Points[j]._Anchor.transform.position; float lTestDistance = Vector3.Distance(rPosition, lTestPosition); if (lTestDistance < lDistance) { lDistance = lTestDistance; lMountPoint = lMountPoints[i].Points[j]; } } } Mount[] lMounts = Component.FindObjectsOfType <Mount>(); for (int i = 0; i < lMounts.Length; i++) { if (lMounts[i] == rSourceMount) { continue; } Vector3 lTestPosition = lMounts[i].Point._Anchor.transform.position; float lTestDistance = Vector3.Distance(rPosition, lTestPosition); if (lTestDistance < lDistance) { lDistance = lTestDistance; lMountPoint = lMounts[i].Point; } } return(lMountPoint); }
/// <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); }