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;
#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
}
}

View File

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

View File

@ -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
/// <summary>
/// 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<TargetRig>();
this.targetRig = this.GetComponentInChildren<InsectRig>();
if (this.targetRig == null) {
GameObject targetsRigPrefab = Resources.Load<GameObject>(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<TargetRig>();
this.targetRig = targetRig.GetComponent<InsectRig>();
}
return true;
}
@ -38,31 +41,59 @@ namespace Passer.CreatureControl {
return false;
}
public virtual bool CheckTargetRig() {
return CheckTargetRig("TargetRig");
}
/// <summary>
/// Ensure that the creature rig is available
/// </summary>
/// <returns>True when the creature rig has been updated</returns>
public bool CheckCreatureRig() {
if (this.creatureRig == null) {
public bool CheckModel() {
if (this.model == null) {
SkinnedMeshRenderer[] skinnedMeshRenderers = this.GetComponentsInChildren<SkinnedMeshRenderer>();
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
}
}

View File

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

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.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;

View File

@ -2,44 +2,35 @@ using UnityEngine;
namespace Passer.CreatureControl {
// An insect target rig....
/// <summary>
/// A target rig for a creature
/// </summary>
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) {

View File

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

View File

@ -12,13 +12,6 @@ namespace Passer.CreatureControl {
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 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<NanoBrain>();
}
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
}
}