diff --git a/CreatureControl/Editor/Scripts/Creature_Editor.cs b/CreatureControl/Editor/Scripts/Creature_Editor.cs index 672f54f..7c0583b 100644 --- a/CreatureControl/Editor/Scripts/Creature_Editor.cs +++ b/CreatureControl/Editor/Scripts/Creature_Editor.cs @@ -10,20 +10,24 @@ namespace Passer.CreatureControl { protected Creature creature; + #region Init + public virtual void OnEnable() { creature = target as Creature; - if (creature == null) - return; - creature.targetToRootTranslation = creature.transform.position - creature.targetRig.transform.position; - creature.targetToRootRotation = Quaternion.Inverse(creature.targetRig.transform.rotation) * creature.transform.rotation; + bool anythingChanged = false; - serializedObject.Update(); + if (!IsPrefab(creature)) { + anythingChanged |= creature.CheckTargetRig(); + anythingChanged |= creature.CheckModel(); + } - if (!IsPrefab(creature)) - InitTargets(creature); + creature.targetRig.MatchTo(creature, ref anythingChanged); - serializedObject.ApplyModifiedProperties(); + if (anythingChanged) { + EditorUtility.SetDirty(creature); + AssetDatabase.SaveAssets(); + } } public static bool IsPrefab(Creature creature) { @@ -31,43 +35,17 @@ namespace Passer.CreatureControl { return prefabStage != null; } - #region Targets + #endregion Init - protected virtual void InitTargets(Creature creature) { - if (creature.CheckTargetRig("TargetRig")) { - EditorUtility.SetDirty(creature); - AssetDatabase.SaveAssets(); - } - } - - #endregion Targets - - private bool initialize = true; - // public Vector3 targetToRootTranslation; - // public Quaternion targetToRootRotation; + #region Scene public virtual void OnSceneGUI() { - if (Application.isPlaying) + if (Application.isPlaying || creature.enabled == false) return; - if (creature.enabled == false || creature.targetRig == null) - return; - - // if (this.initialize) { - // creature.targetToRootTranslation = creature.transform.position - creature.targetRig.transform.position; - // creature.targetToRootRotation = Quaternion.Inverse(creature.targetRig.transform.rotation) * creature.transform.rotation; - // this.initialize = false; - // } - - creature.targetRig.PoseLimbs(); - creature.UpdateBones(); + creature.Update(); } - // protected virtual void UpdateBones() { - // Vector3 newPosition = creature.targetRig.transform.position + targetToRootTranslation; - // Quaternion newOrientation = creature.targetRig.transform.rotation * targetToRootRotation; - // creature.transform.SetPositionAndRotation(newPosition, newOrientation); - // } - + #endregion Scene } } \ No newline at end of file diff --git a/CreatureControl/Editor/Scripts/Insect/Insect_Editor.cs b/CreatureControl/Editor/Scripts/Insect/Insect_Editor.cs index 4b120ee..a0cf1fa 100644 --- a/CreatureControl/Editor/Scripts/Insect/Insect_Editor.cs +++ b/CreatureControl/Editor/Scripts/Insect/Insect_Editor.cs @@ -11,9 +11,16 @@ namespace Passer.CreatureControl { base.OnEnable(); insect = target as Insect; - insect.targetToRootTranslation = insect.transform.position - insect.targetRig.transform.position; - insect.targetToRootRotation = Quaternion.Inverse(insect.targetRig.transform.rotation) * insect.transform.rotation; - insect.targetRig.MatchTo(insect); + + bool anythingChanged = false; + + anythingChanged |= insect.CheckTargetRig("InsectRig"); + insect.insectRig.MatchTo(insect, ref anythingChanged); + + if (anythingChanged) { + EditorUtility.SetDirty(creature); + AssetDatabase.SaveAssets(); + } } #region Inspector @@ -70,57 +77,12 @@ namespace Passer.CreatureControl { SerializedObject targetRigObj = new(targetRigProp.objectReferenceValue); - SerializedProperty animatorControllerProp = targetRigObj.FindProperty(nameof(TargetRig.animator)); + SerializedProperty animatorControllerProp = targetRigObj.FindProperty(nameof(InsectRig.animator)); animatorControllerProp.objectReferenceValue = (Animator)EditorGUILayout.ObjectField(text, animatorControllerProp.objectReferenceValue, typeof(Animator), true); } #endregion Inspector - #region Scene - - [System.NonSerialized] - private bool initialize = true; - - public override void OnSceneGUI() { - if (Application.isPlaying) - return; - - if (insect.enabled == false || insect.targetRig == null) - return; - - // if (this.initialize) { - - // this.targetToRootTranslation = insect.transform.position - insect.targetRig.transform.position; - // this.targetToRootRotation = Quaternion.Inverse(insect.targetRig.transform.rotation) * insect.transform.rotation; - - // insect.targetRig.MatchTo(insect); - - // this.initialize = false; - // } - - insect.targetRig.PoseLimbs(); - insect.UpdateBones(); - } - - // protected override void UpdateBones() { - // base.UpdateBones(); - - // if (insect.targetRig.leftFrontLeg != null) - // insect.targetRig.leftFrontLeg.UpdateBones(insect.leftFrontLeg); - // if (insect.targetRig.leftMiddleLeg != null) - // insect.targetRig.leftMiddleLeg.UpdateBones(insect.leftMiddleLeg); - // if (insect.targetRig.leftBackLeg != null) - // insect.targetRig.leftBackLeg.UpdateBones(insect.leftHindLeg); - - // if (insect.targetRig.rightFrontLeg != null) - // insect.targetRig.rightFrontLeg.UpdateBones(insect.rightFrontLeg); - // if (insect.targetRig.rightMiddleLeg != null) - // insect.targetRig.rightMiddleLeg.UpdateBones(insect.rightMiddleLeg); - // if (insect.targetRig.rightBackLeg != null) - // insect.targetRig.rightBackLeg.UpdateBones(insect.rightHindLeg); - // } - - #endregion Scene } } \ No newline at end of file diff --git a/CreatureControl/Runtime/Scripts/Creature.cs b/CreatureControl/Runtime/Scripts/Creature.cs index 27f32ba..b98a842 100644 --- a/CreatureControl/Runtime/Scripts/Creature.cs +++ b/CreatureControl/Runtime/Scripts/Creature.cs @@ -7,11 +7,14 @@ namespace Passer.CreatureControl { /// The target bones rig contain the target pose of the creature /// The creature movements will try to move the creature such that the target pose is reached /// as closely as possible - public TargetRig targetRig; - public Transform creatureRig; + public Transform model; - public Vector3 targetToRootTranslation; - public Quaternion targetToRootRotation; + public TargetRig targetRig; + + public Vector3 targetToModelTranslation; + public Quaternion targetToModelRotation; + + #region Init /// /// Ensure a target rig is available @@ -22,7 +25,7 @@ namespace Passer.CreatureControl { public bool CheckTargetRig(string targetRigResourceName) { if (this.targetRig == null) { // See if there is a target rig, but we just haven't found it - this.targetRig = this.GetComponentInChildren(); + this.targetRig = this.GetComponentInChildren(); if (this.targetRig == null) { GameObject targetsRigPrefab = Resources.Load(targetRigResourceName); GameObject targetRig = Instantiate(targetsRigPrefab); @@ -30,7 +33,7 @@ namespace Passer.CreatureControl { targetRig.transform.SetPositionAndRotation(this.transform.position, this.transform.rotation); targetRig.transform.SetParent(this.transform); - this.targetRig = targetRig.GetComponent(); + this.targetRig = targetRig.GetComponent(); } return true; } @@ -38,31 +41,59 @@ namespace Passer.CreatureControl { return false; } + public virtual bool CheckTargetRig() { + return CheckTargetRig("TargetRig"); + } + /// /// Ensure that the creature rig is available /// /// True when the creature rig has been updated - public bool CheckCreatureRig() { - if (this.creatureRig == null) { + public bool CheckModel() { + if (this.model == null) { SkinnedMeshRenderer[] skinnedMeshRenderers = this.GetComponentsInChildren(); foreach (SkinnedMeshRenderer skinnedMeshRenderer in skinnedMeshRenderers) { Transform rendererParent = skinnedMeshRenderer.transform.parent; - if (this.creatureRig == null || this.creatureRig == rendererParent) - this.creatureRig = rendererParent; + if (this.model == null || this.model == rendererParent) + this.model = rendererParent; else - Debug.LogWarning("Unclear avatar root"); + Debug.LogWarning("Unclear model root"); } - return this.creatureRig != null; + return this.model != null; } else return false; } - public virtual void UpdateBones() { - Vector3 newPosition = this.targetRig.transform.position + targetToRootTranslation; - Quaternion newOrientation = this.targetRig.transform.rotation * targetToRootRotation; - this.transform.SetPositionAndRotation(newPosition, newOrientation); + #endregion Init + + #region Start + + protected virtual void Start() { + this.CheckTargetRig(); + this.CheckModel(); + this.targetRig.MatchTo(this); } + + #endregion Start + + #region Update + + public virtual void Update() { + if (this.targetRig == null) + return; + + this.targetRig.PoseLimbs(); + UpdateBones(); + } + + public virtual void UpdateBones() { + Vector3 newPosition = this.targetRig.transform.position + this.targetToModelTranslation; + Quaternion newOrientation = this.targetRig.transform.rotation * this.targetToModelRotation; + this.model.SetPositionAndRotation(newPosition, newOrientation); + } + + #endregion Update } } \ No newline at end of file diff --git a/CreatureControl/Runtime/Scripts/Insect/Insect.cs b/CreatureControl/Runtime/Scripts/Insect/Insect.cs index 4073cc5..78869e6 100644 --- a/CreatureControl/Runtime/Scripts/Insect/Insect.cs +++ b/CreatureControl/Runtime/Scripts/Insect/Insect.cs @@ -1,6 +1,9 @@ namespace Passer.CreatureControl { public class Insect : Creature { + + public InsectRig insectRig; + public Leg leftFrontLeg; public Leg leftMiddleLeg; public Leg leftHindLeg; @@ -9,26 +12,40 @@ namespace Passer.CreatureControl { public Leg rightMiddleLeg; public Leg rightHindLeg; - protected virtual void Update() { - UpdateBones(); + #region Init + + public override bool CheckTargetRig() { + bool anythingChanged = base.CheckTargetRig("InsectTargetRig"); + if (anythingChanged || this.insectRig == null) { + this.insectRig = this.targetRig as InsectRig; + return true; + } + else + return anythingChanged; } + #endregion Init + + #region Update + public override void UpdateBones() { base.UpdateBones(); - if (this.targetRig.leftFrontLeg != null) - this.targetRig.leftFrontLeg.UpdateBones(this.leftFrontLeg); - if (this.targetRig.leftMiddleLeg != null) - this.targetRig.leftMiddleLeg.UpdateBones(this.leftMiddleLeg); - if (this.targetRig.leftBackLeg != null) - this.targetRig.leftBackLeg.UpdateBones(this.leftHindLeg); + if (this.insectRig.leftFrontLeg != null) + this.insectRig.leftFrontLeg.UpdateBones(this.leftFrontLeg); + if (this.insectRig.leftMiddleLeg != null) + this.insectRig.leftMiddleLeg.UpdateBones(this.leftMiddleLeg); + if (this.insectRig.leftBackLeg != null) + this.insectRig.leftBackLeg.UpdateBones(this.leftHindLeg); - if (this.targetRig.rightFrontLeg != null) - this.targetRig.rightFrontLeg.UpdateBones(this.rightFrontLeg); - if (this.targetRig.rightMiddleLeg != null) - this.targetRig.rightMiddleLeg.UpdateBones(this.rightMiddleLeg); - if (this.targetRig.rightBackLeg != null) - this.targetRig.rightBackLeg.UpdateBones(this.rightHindLeg); + if (this.insectRig.rightFrontLeg != null) + this.insectRig.rightFrontLeg.UpdateBones(this.rightFrontLeg); + if (this.insectRig.rightMiddleLeg != null) + this.insectRig.rightMiddleLeg.UpdateBones(this.rightMiddleLeg); + if (this.insectRig.rightBackLeg != null) + this.insectRig.rightBackLeg.UpdateBones(this.rightHindLeg); } + + #endregion Update } } \ No newline at end of file diff --git a/CreatureControl/Runtime/Scripts/Insect/InsectRig.cs b/CreatureControl/Runtime/Scripts/Insect/InsectRig.cs new file mode 100644 index 0000000..68f4e57 --- /dev/null +++ b/CreatureControl/Runtime/Scripts/Insect/InsectRig.cs @@ -0,0 +1,46 @@ +using UnityEngine; + +namespace Passer.CreatureControl { + + // An insect target rig.... + public class InsectRig : TargetRig { + public TargetLeg leftFrontLeg; + public TargetLeg leftMiddleLeg; + public TargetLeg leftBackLeg; + + public TargetLeg rightFrontLeg; + public TargetLeg rightMiddleLeg; + public TargetLeg rightBackLeg; + + public override void PoseLimbs() { + this.leftBackLeg.PoseLimb(); + this.leftMiddleLeg.PoseLimb(); + this.leftFrontLeg.PoseLimb(); + this.rightBackLeg.PoseLimb(); + this.rightMiddleLeg.PoseLimb(); + this.rightFrontLeg.PoseLimb(); + } + + public override void MatchTo(Creature creature, ref bool anythingChanged) { + base.MatchTo(creature, ref anythingChanged); + if (creature is not Insect insect) + return; + + if (this.leftFrontLeg != null && insect.leftFrontLeg != null) + this.leftFrontLeg.MatchTo(insect.leftFrontLeg); + if (this.leftMiddleLeg != null && insect.leftMiddleLeg != null) + this.leftMiddleLeg.MatchTo(insect.leftMiddleLeg); + if (this.leftBackLeg != null && insect.leftHindLeg != null) + this.leftBackLeg.MatchTo(insect.leftHindLeg); + + if (this.rightFrontLeg != null && insect.rightFrontLeg != null) + this.rightFrontLeg.MatchTo(insect.rightFrontLeg); + if (this.rightMiddleLeg != null && insect.rightMiddleLeg != null) + this.rightMiddleLeg.MatchTo(insect.rightMiddleLeg); + if (this.rightBackLeg != null && insect.rightHindLeg != null) + this.rightBackLeg.MatchTo(insect.rightHindLeg); + } + + } + +} \ No newline at end of file diff --git a/CreatureControl/Runtime/Scripts/Insect/InsectRig.cs.meta b/CreatureControl/Runtime/Scripts/Insect/InsectRig.cs.meta new file mode 100644 index 0000000..4475915 --- /dev/null +++ b/CreatureControl/Runtime/Scripts/Insect/InsectRig.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a25e8575da1d1cba48dc2b8da7a2b0ab +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/CreatureControl/Runtime/Scripts/TargetLeg.cs b/CreatureControl/Runtime/Scripts/TargetLeg.cs index 7b18b45..8c4ed72 100644 --- a/CreatureControl/Runtime/Scripts/TargetLeg.cs +++ b/CreatureControl/Runtime/Scripts/TargetLeg.cs @@ -20,8 +20,8 @@ namespace Passer.CreatureControl { this.femurTarget.position = leg.femur.position; this.tibiaTarget.position = leg.tibia.position; this.tarsusTarget.position = leg.tarsus.position; - targetToBoneFemur = TargetRig.TargetToBoneRotation(leg.femur, leg.tibia); - targetToBoneTibia = TargetRig.TargetToBoneRotation(leg.tibia, leg.tarsus); + targetToBoneFemur = InsectRig.TargetToBoneRotation(leg.femur, leg.tibia); + targetToBoneTibia = InsectRig.TargetToBoneRotation(leg.tibia, leg.tarsus); this.target.position = this.tarsusTarget.position; this.target.rotation = this.tarsusTarget.rotation; diff --git a/CreatureControl/Runtime/Scripts/TargetRig.cs b/CreatureControl/Runtime/Scripts/TargetRig.cs index e8247fc..9b5956d 100644 --- a/CreatureControl/Runtime/Scripts/TargetRig.cs +++ b/CreatureControl/Runtime/Scripts/TargetRig.cs @@ -2,44 +2,35 @@ using UnityEngine; namespace Passer.CreatureControl { - // An insect target rig.... + /// + /// A target rig for a creature + /// public class TargetRig : MonoBehaviour { - public TargetLeg leftFrontLeg; - public TargetLeg leftMiddleLeg; - public TargetLeg leftBackLeg; - - public TargetLeg rightFrontLeg; - public TargetLeg rightMiddleLeg; - public TargetLeg rightBackLeg; public Animator animator; - public void PoseLimbs() { - this.leftBackLeg.PoseLimb(); - this.leftMiddleLeg.PoseLimb(); - this.leftFrontLeg.PoseLimb(); - this.rightBackLeg.PoseLimb(); - this.rightMiddleLeg.PoseLimb(); - this.rightFrontLeg.PoseLimb(); + public virtual void PoseLimbs() { } - public void MatchTo(Insect insect) { - if (insect == null) - return; + public void MatchTo(Creature creature) { + bool anythingChangedDummy = false; + MatchTo(creature, ref anythingChangedDummy); + } - if (this.leftFrontLeg != null && insect.leftFrontLeg != null) - this.leftFrontLeg.MatchTo(insect.leftFrontLeg); - if (this.leftMiddleLeg != null && insect.leftMiddleLeg != null) - this.leftMiddleLeg.MatchTo(insect.leftMiddleLeg); - if (this.leftBackLeg != null && insect.leftHindLeg != null) - this.leftBackLeg.MatchTo(insect.leftHindLeg); + public virtual void MatchTo(Creature creature, ref bool anythingChanged) { + Vector3 targetToModelTranslation = creature.model.position - this.transform.position; + bool changed = targetToModelTranslation != creature.targetToModelTranslation; + if (changed) { + anythingChanged = true; + creature.targetToModelTranslation = targetToModelTranslation; + } - if (this.rightFrontLeg != null && insect.rightFrontLeg != null) - this.rightFrontLeg.MatchTo(insect.rightFrontLeg); - if (this.rightMiddleLeg != null && insect.rightMiddleLeg != null) - this.rightMiddleLeg.MatchTo(insect.rightMiddleLeg); - if (this.rightBackLeg != null && insect.rightHindLeg != null) - this.rightBackLeg.MatchTo(insect.rightHindLeg); + Quaternion targetToModelRotation = Quaternion.Inverse(this.transform.rotation) * creature.model.rotation; + changed = targetToModelRotation != creature.targetToModelRotation; + if (changed) { + anythingChanged = true; + creature.targetToModelRotation = targetToModelRotation; + } } public static Quaternion TargetToBoneRotation(Transform bone, Transform nextBone) { diff --git a/CreatureControl/Runtime/Scripts/TargetRig.cs.meta b/CreatureControl/Runtime/Scripts/TargetRig.cs.meta index 4475915..11ee687 100644 --- a/CreatureControl/Runtime/Scripts/TargetRig.cs.meta +++ b/CreatureControl/Runtime/Scripts/TargetRig.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: a25e8575da1d1cba48dc2b8da7a2b0ab +guid: d2609296f45aabe86b35997eeef1e59a MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Editor/Scripts/Ant_Editor.cs b/Editor/Scripts/Ant_Editor.cs index 5492c2d..8b211f3 100644 --- a/Editor/Scripts/Ant_Editor.cs +++ b/Editor/Scripts/Ant_Editor.cs @@ -12,13 +12,6 @@ namespace Passer.CreatureControl { base.OnEnable(); } - - protected override void InitTargets(Creature creature) { - if (creature.CheckTargetRig("InsectTargetRig")) { - EditorUtility.SetDirty(creature); - AssetDatabase.SaveAssets(); - } - } } } \ No newline at end of file diff --git a/Runtime/Scripts/Ant.cs b/Runtime/Scripts/Ant.cs index 736e58e..cd5c03a 100644 --- a/Runtime/Scripts/Ant.cs +++ b/Runtime/Scripts/Ant.cs @@ -32,6 +32,8 @@ namespace Passer.CreatureControl { public Vector3 linearVelocity; public Vector3 angularVelocity; + #region Init + protected virtual void Awake() { if (this.targetRig != null) this.animator = this.targetRig.animator; @@ -39,7 +41,13 @@ namespace Passer.CreatureControl { this.nanoBrain = GetComponentInChildren(); } - void Start() { + #endregion Init + + #region Start + + protected override void Start() { + base.Start(); + Cluster brain = this.nanoBrain.brain; if (brain != null) { // brain outputs @@ -68,6 +76,10 @@ namespace Passer.CreatureControl { } + #endregion Start + + #region Update + void PlaceFoodPheromone() { GameObject pheromoneObj = Instantiate(foodPheromonePrefab); pheromoneObj.transform.position = this.transform.position; @@ -78,9 +90,9 @@ namespace Passer.CreatureControl { } // Update is called once per frame - protected override void Update() { + public override void Update() { base.Update(); - + UpdateBeat(); UpdateSmell(); @@ -215,6 +227,8 @@ namespace Passer.CreatureControl { touchDirection = this.transform.InverseTransformVector(touchRight.transform.forward); hitRight?.SetBias(touchDirection); } + + #endregion Update } } \ No newline at end of file