Any walks

This commit is contained in:
Pascal Serrarens 2026-03-10 10:01:38 +01:00
parent e709ea4e60
commit 018c99dce5
11 changed files with 204 additions and 161 deletions

View File

@ -10,20 +10,24 @@ namespace Passer.CreatureControl {
protected Creature creature; protected Creature creature;
#region Init
public virtual void OnEnable() { public virtual void OnEnable() {
creature = target as Creature; creature = target as Creature;
if (creature == null)
return;
creature.targetToRootTranslation = creature.transform.position - creature.targetRig.transform.position; bool anythingChanged = false;
creature.targetToRootRotation = Quaternion.Inverse(creature.targetRig.transform.rotation) * creature.transform.rotation;
serializedObject.Update(); if (!IsPrefab(creature)) {
anythingChanged |= creature.CheckTargetRig();
anythingChanged |= creature.CheckModel();
}
if (!IsPrefab(creature)) creature.targetRig.MatchTo(creature, ref anythingChanged);
InitTargets(creature);
serializedObject.ApplyModifiedProperties(); if (anythingChanged) {
EditorUtility.SetDirty(creature);
AssetDatabase.SaveAssets();
}
} }
public static bool IsPrefab(Creature creature) { public static bool IsPrefab(Creature creature) {
@ -31,43 +35,17 @@ namespace Passer.CreatureControl {
return prefabStage != null; return prefabStage != null;
} }
#region Targets #endregion Init
protected virtual void InitTargets(Creature creature) { #region Scene
if (creature.CheckTargetRig("TargetRig")) {
EditorUtility.SetDirty(creature);
AssetDatabase.SaveAssets();
}
}
#endregion Targets
private bool initialize = true;
// public Vector3 targetToRootTranslation;
// public Quaternion targetToRootRotation;
public virtual void OnSceneGUI() { public virtual void OnSceneGUI() {
if (Application.isPlaying) if (Application.isPlaying || creature.enabled == false)
return; return;
if (creature.enabled == false || creature.targetRig == null) creature.Update();
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();
} }
// protected virtual void UpdateBones() { #endregion Scene
// Vector3 newPosition = creature.targetRig.transform.position + targetToRootTranslation;
// Quaternion newOrientation = creature.targetRig.transform.rotation * targetToRootRotation;
// creature.transform.SetPositionAndRotation(newPosition, newOrientation);
// }
} }
} }

View File

@ -11,9 +11,16 @@ namespace Passer.CreatureControl {
base.OnEnable(); base.OnEnable();
insect = target as Insect; insect = target as Insect;
insect.targetToRootTranslation = insect.transform.position - insect.targetRig.transform.position;
insect.targetToRootRotation = Quaternion.Inverse(insect.targetRig.transform.rotation) * insect.transform.rotation; bool anythingChanged = false;
insect.targetRig.MatchTo(insect);
anythingChanged |= insect.CheckTargetRig("InsectRig");
insect.insectRig.MatchTo(insect, ref anythingChanged);
if (anythingChanged) {
EditorUtility.SetDirty(creature);
AssetDatabase.SaveAssets();
}
} }
#region Inspector #region Inspector
@ -70,57 +77,12 @@ namespace Passer.CreatureControl {
SerializedObject targetRigObj = new(targetRigProp.objectReferenceValue); 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); animatorControllerProp.objectReferenceValue = (Animator)EditorGUILayout.ObjectField(text, animatorControllerProp.objectReferenceValue, typeof(Animator), true);
} }
#endregion Inspector #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
} }
} }

View File

@ -7,11 +7,14 @@ namespace Passer.CreatureControl {
/// The target bones rig contain the target pose of the creature /// 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 /// The creature movements will try to move the creature such that the target pose is reached
/// as closely as possible /// as closely as possible
public TargetRig targetRig; public Transform model;
public Transform creatureRig;
public Vector3 targetToRootTranslation; public TargetRig targetRig;
public Quaternion targetToRootRotation;
public Vector3 targetToModelTranslation;
public Quaternion targetToModelRotation;
#region Init
/// <summary> /// <summary>
/// Ensure a target rig is available /// Ensure a target rig is available
@ -22,7 +25,7 @@ namespace Passer.CreatureControl {
public bool CheckTargetRig(string targetRigResourceName) { public bool CheckTargetRig(string targetRigResourceName) {
if (this.targetRig == null) { if (this.targetRig == null) {
// See if there is a target rig, but we just haven't found it // See if there is a target rig, but we just haven't found it
this.targetRig = this.GetComponentInChildren<TargetRig>(); this.targetRig = this.GetComponentInChildren<InsectRig>();
if (this.targetRig == null) { if (this.targetRig == null) {
GameObject targetsRigPrefab = Resources.Load<GameObject>(targetRigResourceName); GameObject targetsRigPrefab = Resources.Load<GameObject>(targetRigResourceName);
GameObject targetRig = Instantiate(targetsRigPrefab); GameObject targetRig = Instantiate(targetsRigPrefab);
@ -30,7 +33,7 @@ namespace Passer.CreatureControl {
targetRig.transform.SetPositionAndRotation(this.transform.position, this.transform.rotation); targetRig.transform.SetPositionAndRotation(this.transform.position, this.transform.rotation);
targetRig.transform.SetParent(this.transform); targetRig.transform.SetParent(this.transform);
this.targetRig = targetRig.GetComponent<TargetRig>(); this.targetRig = targetRig.GetComponent<InsectRig>();
} }
return true; return true;
} }
@ -38,31 +41,59 @@ namespace Passer.CreatureControl {
return false; return false;
} }
public virtual bool CheckTargetRig() {
return CheckTargetRig("TargetRig");
}
/// <summary> /// <summary>
/// Ensure that the creature rig is available /// Ensure that the creature rig is available
/// </summary> /// </summary>
/// <returns>True when the creature rig has been updated</returns> /// <returns>True when the creature rig has been updated</returns>
public bool CheckCreatureRig() { public bool CheckModel() {
if (this.creatureRig == null) { if (this.model == null) {
SkinnedMeshRenderer[] skinnedMeshRenderers = this.GetComponentsInChildren<SkinnedMeshRenderer>(); SkinnedMeshRenderer[] skinnedMeshRenderers = this.GetComponentsInChildren<SkinnedMeshRenderer>();
foreach (SkinnedMeshRenderer skinnedMeshRenderer in skinnedMeshRenderers) { foreach (SkinnedMeshRenderer skinnedMeshRenderer in skinnedMeshRenderers) {
Transform rendererParent = skinnedMeshRenderer.transform.parent; Transform rendererParent = skinnedMeshRenderer.transform.parent;
if (this.creatureRig == null || this.creatureRig == rendererParent) if (this.model == null || this.model == rendererParent)
this.creatureRig = rendererParent; this.model = rendererParent;
else else
Debug.LogWarning("Unclear avatar root"); Debug.LogWarning("Unclear model root");
} }
return this.creatureRig != null; return this.model != null;
} }
else else
return false; return false;
} }
public virtual void UpdateBones() { #endregion Init
Vector3 newPosition = this.targetRig.transform.position + targetToRootTranslation;
Quaternion newOrientation = this.targetRig.transform.rotation * targetToRootRotation; #region Start
this.transform.SetPositionAndRotation(newPosition, newOrientation);
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
} }
} }

View File

@ -1,6 +1,9 @@
namespace Passer.CreatureControl { namespace Passer.CreatureControl {
public class Insect : Creature { public class Insect : Creature {
public InsectRig insectRig;
public Leg leftFrontLeg; public Leg leftFrontLeg;
public Leg leftMiddleLeg; public Leg leftMiddleLeg;
public Leg leftHindLeg; public Leg leftHindLeg;
@ -9,26 +12,40 @@ namespace Passer.CreatureControl {
public Leg rightMiddleLeg; public Leg rightMiddleLeg;
public Leg rightHindLeg; public Leg rightHindLeg;
protected virtual void Update() { #region Init
UpdateBones();
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() { public override void UpdateBones() {
base.UpdateBones(); base.UpdateBones();
if (this.targetRig.leftFrontLeg != null) if (this.insectRig.leftFrontLeg != null)
this.targetRig.leftFrontLeg.UpdateBones(this.leftFrontLeg); this.insectRig.leftFrontLeg.UpdateBones(this.leftFrontLeg);
if (this.targetRig.leftMiddleLeg != null) if (this.insectRig.leftMiddleLeg != null)
this.targetRig.leftMiddleLeg.UpdateBones(this.leftMiddleLeg); this.insectRig.leftMiddleLeg.UpdateBones(this.leftMiddleLeg);
if (this.targetRig.leftBackLeg != null) if (this.insectRig.leftBackLeg != null)
this.targetRig.leftBackLeg.UpdateBones(this.leftHindLeg); this.insectRig.leftBackLeg.UpdateBones(this.leftHindLeg);
if (this.targetRig.rightFrontLeg != null) if (this.insectRig.rightFrontLeg != null)
this.targetRig.rightFrontLeg.UpdateBones(this.rightFrontLeg); this.insectRig.rightFrontLeg.UpdateBones(this.rightFrontLeg);
if (this.targetRig.rightMiddleLeg != null) if (this.insectRig.rightMiddleLeg != null)
this.targetRig.rightMiddleLeg.UpdateBones(this.rightMiddleLeg); this.insectRig.rightMiddleLeg.UpdateBones(this.rightMiddleLeg);
if (this.targetRig.rightBackLeg != null) if (this.insectRig.rightBackLeg != null)
this.targetRig.rightBackLeg.UpdateBones(this.rightHindLeg); this.insectRig.rightBackLeg.UpdateBones(this.rightHindLeg);
} }
#endregion Update
} }
} }

View File

@ -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);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a25e8575da1d1cba48dc2b8da7a2b0ab
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -20,8 +20,8 @@ namespace Passer.CreatureControl {
this.femurTarget.position = leg.femur.position; this.femurTarget.position = leg.femur.position;
this.tibiaTarget.position = leg.tibia.position; this.tibiaTarget.position = leg.tibia.position;
this.tarsusTarget.position = leg.tarsus.position; this.tarsusTarget.position = leg.tarsus.position;
targetToBoneFemur = TargetRig.TargetToBoneRotation(leg.femur, leg.tibia); targetToBoneFemur = InsectRig.TargetToBoneRotation(leg.femur, leg.tibia);
targetToBoneTibia = TargetRig.TargetToBoneRotation(leg.tibia, leg.tarsus); targetToBoneTibia = InsectRig.TargetToBoneRotation(leg.tibia, leg.tarsus);
this.target.position = this.tarsusTarget.position; this.target.position = this.tarsusTarget.position;
this.target.rotation = this.tarsusTarget.rotation; this.target.rotation = this.tarsusTarget.rotation;

View File

@ -2,44 +2,35 @@ using UnityEngine;
namespace Passer.CreatureControl { namespace Passer.CreatureControl {
// An insect target rig.... /// <summary>
/// A target rig for a creature
/// </summary>
public class TargetRig : MonoBehaviour { 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 Animator animator;
public void PoseLimbs() { public virtual void PoseLimbs() {
this.leftBackLeg.PoseLimb();
this.leftMiddleLeg.PoseLimb();
this.leftFrontLeg.PoseLimb();
this.rightBackLeg.PoseLimb();
this.rightMiddleLeg.PoseLimb();
this.rightFrontLeg.PoseLimb();
} }
public void MatchTo(Insect insect) { public void MatchTo(Creature creature) {
if (insect == null) bool anythingChangedDummy = false;
return; MatchTo(creature, ref anythingChangedDummy);
}
if (this.leftFrontLeg != null && insect.leftFrontLeg != null) public virtual void MatchTo(Creature creature, ref bool anythingChanged) {
this.leftFrontLeg.MatchTo(insect.leftFrontLeg); Vector3 targetToModelTranslation = creature.model.position - this.transform.position;
if (this.leftMiddleLeg != null && insect.leftMiddleLeg != null) bool changed = targetToModelTranslation != creature.targetToModelTranslation;
this.leftMiddleLeg.MatchTo(insect.leftMiddleLeg); if (changed) {
if (this.leftBackLeg != null && insect.leftHindLeg != null) anythingChanged = true;
this.leftBackLeg.MatchTo(insect.leftHindLeg); creature.targetToModelTranslation = targetToModelTranslation;
}
if (this.rightFrontLeg != null && insect.rightFrontLeg != null) Quaternion targetToModelRotation = Quaternion.Inverse(this.transform.rotation) * creature.model.rotation;
this.rightFrontLeg.MatchTo(insect.rightFrontLeg); changed = targetToModelRotation != creature.targetToModelRotation;
if (this.rightMiddleLeg != null && insect.rightMiddleLeg != null) if (changed) {
this.rightMiddleLeg.MatchTo(insect.rightMiddleLeg); anythingChanged = true;
if (this.rightBackLeg != null && insect.rightHindLeg != null) creature.targetToModelRotation = targetToModelRotation;
this.rightBackLeg.MatchTo(insect.rightHindLeg); }
} }
public static Quaternion TargetToBoneRotation(Transform bone, Transform nextBone) { public static Quaternion TargetToBoneRotation(Transform bone, Transform nextBone) {

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: a25e8575da1d1cba48dc2b8da7a2b0ab guid: d2609296f45aabe86b35997eeef1e59a
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

View File

@ -12,13 +12,6 @@ namespace Passer.CreatureControl {
base.OnEnable(); base.OnEnable();
} }
protected override void InitTargets(Creature creature) {
if (creature.CheckTargetRig("InsectTargetRig")) {
EditorUtility.SetDirty(creature);
AssetDatabase.SaveAssets();
}
}
} }
} }

View File

@ -32,6 +32,8 @@ namespace Passer.CreatureControl {
public Vector3 linearVelocity; public Vector3 linearVelocity;
public Vector3 angularVelocity; public Vector3 angularVelocity;
#region Init
protected virtual void Awake() { protected virtual void Awake() {
if (this.targetRig != null) if (this.targetRig != null)
this.animator = this.targetRig.animator; this.animator = this.targetRig.animator;
@ -39,7 +41,13 @@ namespace Passer.CreatureControl {
this.nanoBrain = GetComponentInChildren<NanoBrain>(); this.nanoBrain = GetComponentInChildren<NanoBrain>();
} }
void Start() { #endregion Init
#region Start
protected override void Start() {
base.Start();
Cluster brain = this.nanoBrain.brain; Cluster brain = this.nanoBrain.brain;
if (brain != null) { if (brain != null) {
// brain outputs // brain outputs
@ -68,6 +76,10 @@ namespace Passer.CreatureControl {
} }
#endregion Start
#region Update
void PlaceFoodPheromone() { void PlaceFoodPheromone() {
GameObject pheromoneObj = Instantiate(foodPheromonePrefab); GameObject pheromoneObj = Instantiate(foodPheromonePrefab);
pheromoneObj.transform.position = this.transform.position; pheromoneObj.transform.position = this.transform.position;
@ -78,9 +90,9 @@ namespace Passer.CreatureControl {
} }
// Update is called once per frame // Update is called once per frame
protected override void Update() { public override void Update() {
base.Update(); base.Update();
UpdateBeat(); UpdateBeat();
UpdateSmell(); UpdateSmell();
@ -215,6 +227,8 @@ namespace Passer.CreatureControl {
touchDirection = this.transform.InverseTransformVector(touchRight.transform.forward); touchDirection = this.transform.InverseTransformVector(touchRight.transform.forward);
hitRight?.SetBias(touchDirection); hitRight?.SetBias(touchDirection);
} }
#endregion Update
} }
} }