using UnityEngine;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
public enum LegCyclePhase {
Stance, Lift, Flight, Land
}
public class LegState {
// Past and future step
public Vector3 stepFromPosition;
public Vector3 stepToPosition;
public Vector3 stepToPositionGoal;
public Matrix4x4 stepFromMatrix;
public Matrix4x4 stepToMatrix;
public float stepFromTime;
public float stepToTime;
public int stepNr = 0;
// Continiously changing foot state
public float cycleTime = 1;
public float designatedCycleTimePrev = 0.9f;
public Vector3 hipReference;
public Vector3 ankleReference;
public Vector3 footBase;
public Quaternion footBaseRotation;
public Vector3 ankle;
// Foot cycle event time stamps
public float stanceTime = 0;
public float liftTime = 0.1f;
public float liftoffTime = 0.2f;
public float postliftTime = 0.3f;
public float prelandTime = 0.7f;
public float strikeTime = 0.8f;
public float landTime = 0.9f;
public LegCyclePhase phase = LegCyclePhase.Stance;
// Standing logic
public bool parked;
// Cycle properties
public Vector3 stancePosition;
public Vector3 heelToetipVector;
public List<string> debugHistory = new List<string>();
public float GetFootGrounding(float time) {
if ( (time<=liftTime) || (time>=landTime) ) return 0;
if ( (time>=postliftTime) && (time<=prelandTime) ) return 1;
if ( time<postliftTime ) {
return (time-liftTime)/(postliftTime-liftTime);
}
else {
return 1-(time-prelandTime)/(landTime-prelandTime);
}
}
}
public class MotionGroupState {
public AnimationState controller;
public float weight;
public AnimationState[] motionStates;
public float[] relativeWeights;
public float[] relativeWeightsBlended;
public int primaryMotionIndex;
}
[RequireComponent(typeof(LegController))]
[RequireComponent(typeof(AlignmentTracker))]
public class LegAnimator : MonoBehaviour {
public bool startAutomatically = true;
public bool useIK = true;
public float maxFootRotationAngle = 45.0f;
public float maxIKAdjustmentDistance = 0.5f;
// Step behavior settings
public float minStepDistance = 0.2f; // Model dependent, thus no better default
public float maxStepDuration = 1.5f; // Sensible for most models
public float maxStepRotation = 160; // Sensible for most models, must be less than 180
public float maxStepAcceleration = 5.0f; // Model dependent, thus no better default
public float maxStepHeight = 1.0f;
public float maxSlopeAngle = 60; // Sensible for most models, must be less than 90
// Transition behavior settings
public bool enableLegParking = true;
public float blendSmoothing = 0.2f;
public LayerMask groundLayers = 1; // Default layer per default
// Tilting settings
public float groundHugX = 0; // Sensible for humanoids
public float groundHugZ = 0; // Sensible for humanoids
public float climbTiltAmount = 0.5f; // Sensible default value
public float climbTiltSensitivity = 0.0f; // None as default
public float accelerateTiltAmount = 0.02f; // Sensible default value
public float accelerateTiltSensitivity = 0.0f; // None as default;
// Debug settings
public bool renderFootMarkers = false;
public bool renderBlendingGraph = false;
public bool renderCycleGraph = false;
public bool renderAnimationStates = false;
private bool isActive;
private float currentTime;
private LegController legC;
private AlignmentTracker tr;
private LegInfo[] legs;
private LegState[] legStates;
private Vector3 position;
private float speed;
private float hSpeedSmoothed;
private Vector3 objectVelocity;
private Vector3 usedObjectVelocity;
private Quaternion rotation;
private Vector3 up;
private Vector3 forward;
private float scale;
private Vector3 baseUpGround;
private Vector3 bodyUp;
private Vector3 legsUp;
private float accelerationTiltX;
private float accelerationTiltZ;
private AnimationState controlMotionState;
private MotionGroupState[] motionGroupStates;
private AnimationState[] nonGroupMotionStates;
private float[] nonGroupMotionWeights;
private AnimationState[] motionStates;
private AnimationState[] cycleMotionStates;
private float[] motionWeights;
private float[] cycleMotionWeights;
private float summedMotionWeight;
private float summedCycleMotionWeight;
private float locomotionWeight;
private float cycleDuration;
private float cycleDistance;
private float normalizedTime;
private bool updateStates = true;
[System.NonSerialized]
public GameObject ghost;
private Dictionary<string,TrajectoryVisualizer> trajectories
= new Dictionary<string,TrajectoryVisualizer>();
[Conditional("VISUALIZE")]
void AddTrajectoryPoint(string name, Vector3 point) {
trajectories[name].AddPoint(Time.time,point);
}
[Conditional("DEBUG")]
void Assert(bool condition, string text) {
if (!condition) UnityEngine.Debug.LogError(text);
}
[Conditional("DEBUG")]
void AssertSane(float f, string text) {
if (!Util.IsSaneNumber(f)) UnityEngine.Debug.LogError(text+"="+f);
}
[Conditional("DEBUG")]
void AssertSane(Vector3 vect, string text) {
if (!Util.IsSaneNumber(vect.x)
|| !Util.IsSaneNumber(vect.y)
|| !Util.IsSaneNumber(vect.z)
) UnityEngine.Debug.LogError(text+"="+vect);
}
[Conditional("DEBUG")]
void AssertSane(Quaternion q, string text) {
if (!Util.IsSaneNumber(q.x)
|| !Util.IsSaneNumber(q.y)
|| !Util.IsSaneNumber(q.z)
|| !Util.IsSaneNumber(q.w)
) UnityEngine.Debug.LogError(text+"="+q);
}
void Start () {
tr = GetComponent(typeof(AlignmentTracker)) as AlignmentTracker;
legC = GetComponent(typeof(LegController)) as LegController;
legs = legC.legs;
if (!legC.initialized) {
UnityEngine.Debug.LogError(name+": Locomotion System has not been initialized.",this);
enabled = false;
}
legStates = new LegState[legs.Length];
updateStates = true;
ResetMotionStates();
ResetSteps();
isActive = false;
for (int leg=0; leg<legs.Length; leg++) {
trajectories.Add(
"leg"+leg+"heel",
new TrajectoryVisualizer(legs[leg].debugColor, 3)
);
trajectories.Add(
"leg"+leg+"toetip",
new TrajectoryVisualizer(legs[leg].debugColor, 3)
);
trajectories.Add(
"leg"+leg+"footbase",
new TrajectoryVisualizer(legs[leg].debugColor, 3)
);
}
}