diff --git a/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizard.cs b/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizard.cs index 46d4d8dbed..5a9bbd5cd0 100644 --- a/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizard.cs +++ b/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizard.cs @@ -706,6 +706,11 @@ void OnWizardUpdate() m_validations.Clear(); m_validations.AddRange(Validate()); m_validations.AddRange(VRMSpringBoneValidator.Validate(ExportRoot)); + var firstPerson = ExportRoot.GetComponent(); + if (firstPerson != null) + { + m_validations.AddRange(firstPerson.Validate()); + } var hasError = m_validations.Any(x => !x.CanExport); m_IsValid = !hasError && !MetaHasError; diff --git a/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizardMessages.cs b/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizardMessages.cs index 16f4c53ba9..9cc63ecf02 100644 --- a/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizardMessages.cs +++ b/Assets/VRM/UniVRM/Editor/Format/VRMExporterWizardMessages.cs @@ -49,7 +49,7 @@ public enum VRMExporterWizardMessages [LangMsg(Languages.en, "Animator.avatar is not humanoid. Please change model's AnimationType to humanoid")] AVATAR_IS_NOT_HUMANOID, - [LangMsg(Languages.ja, "humanoid設定に顎が含まれている。FBX importer の rig 設定に戻って設定を解除することをおすすめします")] + [LangMsg(Languages.ja, "humanoid設定に顎が含まれている。FBX importer の rig 設定で顎ボーンの割り当てを確認できます")] [LangMsg(Languages.en, "Jaw bone is included. It may not what you intended. Please check the humanoid avatar setting screen")] JAW_BONE_IS_INCLUDED, diff --git a/Assets/VRM/UniVRM/Editor/SpringBone/VRMSpringBoneValidator.cs b/Assets/VRM/UniVRM/Editor/SpringBone/VRMSpringBoneValidator.cs index d4abef4407..e552b5696f 100644 --- a/Assets/VRM/UniVRM/Editor/SpringBone/VRMSpringBoneValidator.cs +++ b/Assets/VRM/UniVRM/Editor/SpringBone/VRMSpringBoneValidator.cs @@ -14,12 +14,26 @@ public static IEnumerable Validate(GameObject root) yield break; } + var hierarchy = root.GetComponentsInChildren(); + Dictionary> rootMap = new Dictionary>(); foreach (var sb in root.GetComponentsInChildren()) { - foreach (var springRoot in sb.RootBones) + for (int i = 0; i < sb.RootBones.Count; ++i) { + var springRoot = sb.RootBones[i]; + if (springRoot == null) + { + yield return Validation.Error($"{sb.name}.RootBones[{i}] is null"); + continue; + } + if (!hierarchy.Contains(springRoot)) + { + yield return Validation.Error($"{sb.name}.RootBones[{i}] is out of hierarchy"); + continue; + } + if (!rootMap.TryGetValue(springRoot, out List list)) { list = new List(); @@ -27,6 +41,21 @@ public static IEnumerable Validate(GameObject root) } list.Add(sb); } + + for (int i = 0; i < sb.ColliderGroups.Length; ++i) + { + var c = sb.ColliderGroups[i]; + if (c == null) + { + yield return Validation.Error($"{sb.name}.ColliderGroups[{i}] is null"); + continue; + } + if (!hierarchy.Contains(c.transform)) + { + yield return Validation.Error($"{sb.name}.ColliderGroups[{i}] is out of hierarchy"); + continue; + } + } } foreach (var kv in rootMap) diff --git a/Assets/VRM/UniVRM/Scripts/FirstPerson/VRMFirstPerson.cs b/Assets/VRM/UniVRM/Scripts/FirstPerson/VRMFirstPerson.cs index 7777830494..11b59375cb 100644 --- a/Assets/VRM/UniVRM/Scripts/FirstPerson/VRMFirstPerson.cs +++ b/Assets/VRM/UniVRM/Scripts/FirstPerson/VRMFirstPerson.cs @@ -50,17 +50,23 @@ public Mesh SharedMesh [SerializeField] public List Renderers = new List(); - static IEnumerable Traverse(Transform parent) + public IEnumerable Validate() { - yield return parent; + var hierarchy = GetComponentsInChildren(); - foreach (Transform child in parent) + for (int i = 0; i < Renderers.Count; ++i) { - foreach (var x in Traverse(child)) + var r = Renderers[i]; + if (r.Renderer == null) { - yield return x; + yield return Validation.Error($"{name}.Renderers[{i}].Renderer is null"); + } + if (!hierarchy.Contains(r.Renderer.transform)) + { + yield return Validation.Error($"{name}.Renderers[{i}].Renderer is out of hierarchy"); } } + yield break; } public void CopyTo(GameObject _dst, Dictionary map)