// Use this for initialization void Start() { if (this.data == null) { this.data = new IceDrillData() { PowerableInstanceID = Guid.NewGuid().ToString() } } ; Drill.localPosition = Vector3.zero; foreach (Animator LegController in LegControllers) { LegController.SetBool("LegDown", LegsDown); } this.InitializePowerVisualization(); CrateAnchor.gameObject.SetActive(false); } // Update is called once per frame void Update() { if (IsOn) { Drill.Rotate(Vector3.forward, 2f, Space.Self); if (HasAttachedWaterContainer && capturedResource.Data.Container.CurrentAmount < 1f) { capturedResource.Data.Container.Push(this.HostDeposit.Data.Extractable.Pull(Time.deltaTime * WaterPerSecond)); } } }
public override void Analyze(GameObject o) { GameObject gameObject = o; animation = orig.animation; name = animation.name + "_bk"; motionType = orig.motionType; motionGroup = orig.motionGroup; // Initialize legs and cycle data LegController legC = gameObject.GetComponent(typeof(LegController)) as LegController; int legs = legC.legs.Length; m_cycles = new LegCycleData[legs]; for (int leg = 0; leg < legs; leg++) { cycles[leg] = new LegCycleData(); cycles[leg].cycleCenter = orig.cycles[leg].cycleCenter; cycles[leg].cycleScaling = orig.cycles[leg].cycleScaling; cycles[leg].cycleDirection = -orig.cycles[leg].cycleDirection; cycles[leg].stanceTime = 1 - orig.cycles[leg].stanceTime; cycles[leg].liftTime = 1 - orig.cycles[leg].landTime; cycles[leg].liftoffTime = 1 - orig.cycles[leg].strikeTime; cycles[leg].postliftTime = 1 - orig.cycles[leg].prelandTime; cycles[leg].prelandTime = 1 - orig.cycles[leg].postliftTime; cycles[leg].strikeTime = 1 - orig.cycles[leg].liftoffTime; cycles[leg].landTime = 1 - orig.cycles[leg].liftTime; cycles[leg].cycleDistance = orig.cycles[leg].cycleDistance; cycles[leg].stancePosition = orig.cycles[leg].stancePosition; cycles[leg].heelToetipVector = orig.cycles[leg].heelToetipVector; } }
static void RenderGizmo (LegController legC, GizmoType gizmoType) { if (Application.isPlaying || AnimationUtility.InAnimationMode()) return; Vector3 up = legC.transform.up; Vector3 forward = legC.transform.forward; Vector3 right = legC.transform.right; // Draw cross signifying the Ground Plane Height Vector3 groundCenter = ( legC.transform.position + legC.groundPlaneHeight * up * legC.transform.lossyScale.y ); Gizmos.color = (Color.green+Color.white)/2; Gizmos.DrawLine(groundCenter-forward, groundCenter+forward); Gizmos.DrawLine(groundCenter-right, groundCenter+right); // Draw rect showing foot boundaries if (legC.groundedPose==null) return; float scale = legC.transform.lossyScale.z; for (int leg=0; leg<legC.legs.Length; leg++) { if (legC.legs[leg].ankle==null) continue; if (legC.legs[leg].toe==null) continue; if (legC.legs[leg].footLength+legC.legs[leg].footWidth==0) continue; legC.InitFootData(leg); Vector3 heel = legC.legs[leg].ankle.TransformPoint(legC.legs[leg].ankleHeelVector); Vector3 toetip = legC.legs[leg].toe.TransformPoint(legC.legs[leg].toeToetipVector); Vector3 side = (Quaternion.AngleAxis(90,up) * (toetip-heel)).normalized * legC.legs[leg].footWidth * scale; Gizmos.DrawLine(heel+side/2, toetip+side/2); Gizmos.DrawLine(heel-side/2, toetip-side/2); Gizmos.DrawLine(heel-side/2, heel+side/2); Gizmos.DrawLine(toetip-side/2, toetip+side/2); } }
private void Awake() { legController = GetComponentInParent <LegController>(); transform.parent = bodyTransform; rayOrigin.parent = bodyTransform; TipPos = ikTarget.transform.position; }
public LegInfo(ChassisController chassis, LegController leg) { this.chassis = chassis; this.leg = leg; foot = leg.getDefaultPos(); setLastDefault(); setLastPlanted(); }
public bool OnLoadIKAnimData() { //设置默认动画为idle GetComponent <Animation>().clip = GetComponent <Animation>().GetClip("idle"); //设置spider的ik信息 //ground info and root bone LegController legController = GetComponent <LegController>(); legController.groundPlaneHeight = 0.0f; legController.groundedPose = GetComponent <Animation>().GetClip("idle"); legController.rootBone = transform.Find("Bone02"); //legs info legController.legs = new LegInfo[4]; LegInfo _legInfo = new LegInfo(); _legInfo.hip = RecursionFindTransform(transform, "Bone83"); _legInfo.ankle = RecursionFindTransform(transform, "Bone90"); _legInfo.toe = RecursionFindTransform(transform, "Bone90"); _legInfo.footLength = 0.5f; _legInfo.footWidth = 0.5f; _legInfo.footOffset = new Vector2(0.0f, 0.0f); legController.legs[0] = _legInfo; _legInfo = new LegInfo(); _legInfo.hip = RecursionFindTransform(transform, "Bone43"); _legInfo.ankle = RecursionFindTransform(transform, "Bone50"); _legInfo.toe = RecursionFindTransform(transform, "Bone50"); _legInfo.footLength = 0.5f; _legInfo.footWidth = 0.5f; _legInfo.footOffset = new Vector2(0.0f, 0.0f); legController.legs[1] = _legInfo; _legInfo = new LegInfo(); _legInfo.hip = RecursionFindTransform(transform, "Bone26"); _legInfo.ankle = RecursionFindTransform(transform, "Bone33"); _legInfo.toe = RecursionFindTransform(transform, "Bone33"); _legInfo.footLength = 0.5f; _legInfo.footWidth = 0.5f; _legInfo.footOffset = new Vector2(0.0f, 0.0f); legController.legs[2] = _legInfo; _legInfo = new LegInfo(); _legInfo.hip = RecursionFindTransform(transform, "Bone34"); _legInfo.ankle = RecursionFindTransform(transform, "Bone41"); _legInfo.toe = RecursionFindTransform(transform, "Bone41"); _legInfo.footLength = 0.5f; _legInfo.footWidth = 0.5f; _legInfo.footOffset = new Vector2(0.0f, 0.0f); legController.legs[3] = _legInfo; return(true); }
public void ToggleLegs() { LegsDown = !LegsDown; foreach(Animator LegController in LegControllers) { LegController.SetBool("LegDown", LegsDown); } Socket.tag = LegsDown ? "powerplug" : "Untagged"; CrateAnchor.gameObject.SetActive(LegsDown); }
protected LegInfo getLegInfo(LegController leg) { LegInfo info; if (!legInfo.TryGetValue(leg, out info)) { info = new LegInfo(this, leg); legInfo.Add(leg, info); } return(info); }
static void RenderGizmo(LegController legC, GizmoType gizmoType) { if (Application.isPlaying || AnimationUtility.InAnimationMode()) { return; } Vector3 up = legC.transform.up; Vector3 forward = legC.transform.forward; Vector3 right = legC.transform.right; // Draw cross signifying the Ground Plane Height Vector3 groundCenter = ( legC.transform.position + legC.groundPlaneHeight * up * legC.transform.lossyScale.y ); Gizmos.color = (Color.green + Color.white) / 2; Gizmos.DrawLine(groundCenter - forward, groundCenter + forward); Gizmos.DrawLine(groundCenter - right, groundCenter + right); // Draw rect showing foot boundaries if (legC.groundedPose == null) { return; } float scale = legC.transform.lossyScale.z; for (int leg = 0; leg < legC.legs.Length; leg++) { if (legC.legs[leg].ankle == null) { continue; } if (legC.legs[leg].toe == null) { continue; } if (legC.legs[leg].footLength + legC.legs[leg].footWidth == 0) { continue; } legC.InitFootData(leg); Vector3 heel = legC.legs[leg].ankle.TransformPoint(legC.legs[leg].ankleHeelVector); Vector3 toetip = legC.legs[leg].toe.TransformPoint(legC.legs[leg].toeToetipVector); Vector3 side = (Quaternion.AngleAxis(90, up) * (toetip - heel)).normalized * legC.legs[leg].footWidth * scale; Gizmos.DrawLine(heel + side / 2, toetip + side / 2); Gizmos.DrawLine(heel - side / 2, toetip - side / 2); Gizmos.DrawLine(heel - side / 2, heel + side / 2); Gizmos.DrawLine(toetip - side / 2, toetip + side / 2); } }
protected float calculateStepPercent(LegController[] plantedGroup) { float offsetMagnitude = 0; foreach (LegController leg in plantedGroup) { LegInfo info = getLegInfo(leg); // maybe the following should be added back in? //if (info.planted) // continue; Vector3 normalizedVelocity = info.getVelocity().normalized; Vector3 offset = info.foot - leg.getDefaultPos(); offsetMagnitude = Mathf.Max(offsetMagnitude, Vector3.Dot(offset /strideLength, -normalizedVelocity) +1); } return offsetMagnitude / 2; }
private void Awake() { maw = GetComponent <Maw>(); rb = GetComponent <Rigidbody>(); rb.position = new Vector3(rb.position.x, optimumHeightFromGround, rb.position.z); moveTarget = rb.position; breathingCurveOffset = UnityEngine.Random.value; arms = new List <ArmController>(armCount); if (armCount > 0) { var rotationAnglePer = 360 / armCount; for (int i = 0; i < armCount; i++) { var elevationAngle = UnityEngine.Random.Range(-40, -10); var rotation = Quaternion.Euler(elevationAngle, rotationAnglePer * i, 0); var vector = rotation * Vector3.forward; var armController = Instantiate(armPrefab, transform); armController.maw = maw.gameObject; armController.transform.name = $"Arm {i}"; armController.transform.Translate(vector * limbOffsetRadius); armController.transform.rotation = rotation; arms.Add(armController); } } legs = new List <LegController>(legCount); stepPeriod = stepCyclePeriod / (float)legCount; if (legCount > 0) { var rotationAnglePer = 360 / legCount; for (int i = 0; i < legCount; i++) { var elevationAngle = UnityEngine.Random.Range(30, 30); var rotation = Quaternion.Euler(elevationAngle, rotationAnglePer * i, 0); var vector = rotation * Vector3.forward; LegController legController = Instantiate(legPrefab, transform); legController.transform.name = $"Leg {i}"; legController.transform.Translate(vector * limbOffsetRadius); legController.transform.rotation = Quaternion.RotateTowards(rotation, Quaternion.Euler(-elevationAngle, rotationAnglePer * i, 0), 20); legController.movementDurationSeconds = stepPeriod; legController.baseRotation = rotation; legs.Add(legController); } } }
private static bool SanityCheckAnimationCurves(LegController legC, AnimationClip animation) { AnimationClipCurveData[] curveData = AnimationUtility.GetAllCurves(animation,false); bool hasRootPosition = false; bool hasRootRotation = false; // Check each joint from hip to ankle in each leg bool[][] hasJointRotation = new bool[legC.legs.Length][]; for (int i=0; i<legC.legs.Length; i++) { hasJointRotation[i] = new bool[legC.legs[i].legChain.Length]; } foreach (AnimationClipCurveData data in curveData) { Transform bone = legC.transform.Find(data.path); if (bone==legC.root && data.propertyName=="m_LocalPosition.x") hasRootPosition = true; if (bone==legC.root && data.propertyName=="m_LocalRotation.x") hasRootRotation = true; for (int i=0; i<legC.legs.Length; i++) { for (int j=0; j<legC.legs[i].legChain.Length; j++) { if (bone==legC.legs[i].legChain[j] && data.propertyName=="m_LocalRotation.x") { hasJointRotation[i][j] = true; } } } } bool success = true; if (!hasRootPosition) { Debug.LogError("AnimationClip \""+animation.name+"\" is missing animation curve for the position of the root bone \""+legC.root.name+"\"."); success = false; } if (!hasRootRotation) { Debug.LogError("AnimationClip \""+animation.name+"\" is missing animation curve for the rotation of the root bone \""+legC.root.name+"\"."); success = false; } for (int i=0; i<legC.legs.Length; i++) { for (int j=0; j<legC.legs[i].legChain.Length; j++) { if (!hasJointRotation[i][j]) { Debug.LogError("AnimationClip \""+animation.name+"\" is missing animation curve for the rotation of the joint \""+legC.legs[i].legChain[j].name+"\" in leg "+i+"."); success = false; } } } return success; }
private void UpdateOptions() { // Activate character currentCharacter = characters[selectedCharacter]; legC = currentCharacter.GetComponent(typeof(LegController)) as LegController; currentCharacter.SetActive(true); // Activate animation MotionAnalyzer newAnalyzer = legC.motions[selectedAnimation] as MotionAnalyzer; if (newAnalyzer != null) { analyzer = newAnalyzer; //(MotionAnalyzer)legC.motions[selectedAnimation]; } else { return; } currentAnimation = analyzer.animation; StartAnimation(); optionsCharacter = new string[characters.Length]; for (int i = 0; i < characters.Length; i++) { optionsCharacter[i] = characters[i].name; } optionsAnimation = new string[legC.motions.Length]; for (int i = 0; i < legC.motions.Length; i++) { MotionAnalyzer newMotion = legC.motions[i] as MotionAnalyzer; if (newMotion != null) { optionsAnimation[i] = legC.motions[i].animation.name; } else { optionsAnimation[i] = "N/A"; } } optionsLeg = new string[legC.legs.Length]; for (int i = 0; i < legC.legs.Length; i++) { optionsLeg[i] = "Leg " + (i + 1); } }
// Use this for initialization void Start () { if (this.data == null) this.data = new IceDrillData() { PowerableInstanceID = Guid.NewGuid().ToString() }; Drill.localPosition = Vector3.zero; foreach (Animator LegController in LegControllers) { LegController.SetBool("LegDown", LegsDown); } this.InitializePowerVisualization(); CrateAnchor.gameObject.SetActive(false); }
protected float calculateAltitudeAdjustment(Vector3 stepOffset, LegController leg) { Vector3 maxStepPos = stepOffset + new Vector3(0, maxStepHeight, 0); RaycastHit hitInfo = new RaycastHit(); float yOffset = 0f; if (Physics.Raycast(new Ray(maxStepPos, new Vector3(0, -1, 0)), out hitInfo, maxStepHeight * 10)) { #if UNITY_EDITOR if (debug) { drawPoint(hitInfo.point, Color.green, leg + "one"); drawPoint(stepOffset, Color.red, leg + "two"); } #endif yOffset = hitInfo.point.y - stepOffset.y; } return(yOffset); }
protected void updateSteppingGroup(LegController[] steppingGroup, float stepPercent) { foreach (LegController leg in steppingGroup) { LegInfo info = getLegInfo(leg); Vector3 stepOffset = leg.getDefaultPos() +info.getVelocity().normalized * strideLength; stepOffset.y += calculateAltitudeAdjustment(stepOffset, leg); Vector3 target = Vector3.Lerp(info.getLastPlanted(), stepOffset, stepPercent); target.y += Mathf.Min((1 - Mathf.Abs(stepPercent - 0.5f) * 2) * stepHeight, maxStepHeight); Vector3 diff = (target - info.foot); info.foot += diff.normalized * Mathf.Min(Mathf.Max(0.5f, diff.magnitude /8), diff.magnitude); #if UNITY_EDITOR if(debug) { drawPoint(info.foot, Color.blue, leg + "three"); } #endif } }
// Use this for initialization void Start() { if (gunOnAnimation == null || gunOffAnimation == null || reloadAnimation == null || fireAnimation == null || muzzleFlash == null) { enabled = false; } SetupGunAnimation(gunOnAnimation); SetupGunAnimation(gunOffAnimation); SetupGunAnimation(reloadAnimation); // setup additive fire animation AnimationState fireAS = animation[fireAnimation.name]; fireAS.wrapMode = WrapMode.Once; fireAS.layer = 101; // we put it in a separate layer than impact animations fireAS.blendMode = AnimationBlendMode.Additive; motor = GetComponent(typeof(CharacterMotor)) as CharacterMotor; LegController legC = GetComponent(typeof(LegController)) as LegController; IMotionAnalyzer[] motions = legC.motions; foreach (IMotionAnalyzer motion in motions) { if (motion.name == "RunForward") { maxSpeedWithGun = motion.cycleSpeed; } if (motion.name == "RunForwardNoGun") { maxSpeedWithoutGun = motion.cycleSpeed; } //if (motion.name == "RunForwardFastNoGun") // maxSpeedWithoutGun = motion.cycleSpeed; } muzzleFlash.enabled = false; }
static void DoToggle() { Debug.Log("Menu item selected"); GameObject activeGO = Selection.activeGameObject; LegController legC = activeGO.GetComponent(typeof(LegController)) as LegController; legC.Init(); bool success = true; foreach (MotionAnalyzer analyzer in legC.sourceAnimations) { if (!SanityCheckAnimationCurves(legC, analyzer.animation)) { success = false; } } if (!success) { return; } legC.Init2(); }
public void OnEnable() { lc = target as LegController; }
private void UpdateOptions() { // Activate character currentCharacter = characters[selectedCharacter]; legC = currentCharacter.GetComponent(typeof(LegController)) as LegController; currentCharacter.SetActive(true); // Activate animation MotionAnalyzer newAnalyzer = legC.motions[selectedAnimation] as MotionAnalyzer; if (newAnalyzer!=null) analyzer = newAnalyzer;//(MotionAnalyzer)legC.motions[selectedAnimation]; else return; currentAnimation = analyzer.animation; StartAnimation(); optionsCharacter = new string[characters.Length]; for (int i=0; i<characters.Length; i++) { optionsCharacter[i] = characters[i].name; } optionsAnimation = new string[legC.motions.Length]; for (int i=0; i<legC.motions.Length; i++) { MotionAnalyzer newMotion = legC.motions[i] as MotionAnalyzer; if (newMotion!=null) optionsAnimation[i] = legC.motions[i].animation.name; else optionsAnimation[i] = "N/A"; } optionsLeg = new string[legC.legs.Length]; for (int i=0; i<legC.legs.Length; i++) { optionsLeg[i] = "Leg "+(i+1); } }
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(); 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) ); } }
private static bool SanityCheckAnimationCurves(LegController legC, AnimationClip animation) { AnimationClipCurveData[] curveData = AnimationUtility.GetAllCurves(animation, false); bool hasRootPosition = false; bool hasRootRotation = false; // Check each joint from hip to ankle in each leg bool[][] hasJointRotation = new bool[legC.legs.Length][]; for (int i = 0; i < legC.legs.Length; i++) { hasJointRotation[i] = new bool[legC.legs[i].legChain.Length]; } foreach (AnimationClipCurveData data in curveData) { Transform bone = legC.transform.Find(data.path); if (bone == legC.root && data.propertyName == "m_LocalPosition.x") { hasRootPosition = true; } if (bone == legC.root && data.propertyName == "m_LocalRotation.x") { hasRootRotation = true; } for (int i = 0; i < legC.legs.Length; i++) { for (int j = 0; j < legC.legs[i].legChain.Length; j++) { if (bone == legC.legs[i].legChain[j] && data.propertyName == "m_LocalRotation.x") { hasJointRotation[i][j] = true; } } } } bool success = true; if (!hasRootPosition) { Debug.LogError("AnimationClip \"" + animation.name + "\" is missing animation curve for the position of the root bone \"" + legC.root.name + "\"."); success = false; } if (!hasRootRotation) { Debug.LogError("AnimationClip \"" + animation.name + "\" is missing animation curve for the rotation of the root bone \"" + legC.root.name + "\"."); success = false; } for (int i = 0; i < legC.legs.Length; i++) { for (int j = 0; j < legC.legs[i].legChain.Length; j++) { if (!hasJointRotation[i][j]) { Debug.LogError("AnimationClip \"" + animation.name + "\" is missing animation curve for the rotation of the joint \"" + legC.legs[i].legChain[j].name + "\" in leg " + i + "."); success = false; } } } return(success); }
public override void Analyze(GameObject o) { Debug.Log("Starting analysis"); gameObject = o; name = animation.name; m_samples = 50; // Initialize legs and cycle data legC = gameObject.GetComponent(typeof(LegController)) as LegController; legs = legC.legs.Length; m_cycles = new LegCycleData[legs]; for (int leg=0; leg<legs; leg++) { cycles[leg] = new LegCycleData(); cycles[leg].samples = new LegCycleSample[samples+1]; for (int i=0; i<samples+1; i++) { cycles[leg].samples[i] = new LegCycleSample(); } cycles[leg].debugInfo = new CycleDebugInfo(); } graphMin = new Vector3(0, 1000, 1000); graphMax = new Vector3(0,-1000,-1000); for (int leg=0; leg<legs; leg++) { // Sample ankle, heel, toe, and toetip positions over the length of the animation. Transform ankleT = legC.legs[leg].ankle; Transform toeT = legC.legs[leg].toe; float rangeMax = 0; float ankleMin; float ankleMax; float toeMin; float toeMax; ankleMin = 1000; ankleMax = -1000; toeMin = 1000; toeMax = -1000; for (int i=0; i<samples+1; i++) { LegCycleSample s = cycles[leg].samples[i]; gameObject.SampleAnimation(animation,i*1.0f/samples*animation.length); s.ankleMatrix = Util.RelativeMatrix(ankleT,gameObject.transform); s.toeMatrix = Util.RelativeMatrix(toeT,gameObject.transform); s.heel = s.ankleMatrix.MultiplyPoint(legC.legs[leg].ankleHeelVector); s.toetip = s.toeMatrix.MultiplyPoint(legC.legs[leg].toeToetipVector); s.middle = (s.heel+s.toetip)/2; // For each sample in time we want to know if the heel or toetip is closer to the ground. // We need a smooth curve with 0 = ankle is closer and 1 = toe is closer. s.balance = MotionAnalyzer.GetFootBalance(s.heel.y, s.toetip.y, legC.legs[leg].footLength); // Find the minimum and maximum extends on all axes of the ankle and toe positions. ankleMin = Mathf.Min(ankleMin,s.heel.y); toeMin = Mathf.Min(toeMin,s.toetip.y); ankleMax = Mathf.Max(ankleMax,s.heel.y); toeMax = Mathf.Max(toeMax,s.toetip.y); } rangeMax = Mathf.Max(ankleMax-ankleMin,toeMax-toeMin); // Determine motion type /*if (motionType==MotionType.AutoDetect) { motionType = MotionType.WalkCycle; }*/ if (motionType==MotionType.WalkCycle) { FindCycleAxis(leg); // Foot stance time // Find the time when the foot stands most firmly on the ground. float stanceValue = Mathf.Infinity; for (int i=0; i<samples+1; i++) { LegCycleSample s = cycles[leg].samples[i]; float sampleValue = // We want the point in time when the max of the heel height and the toe height is lowest Mathf.Max(s.heel.y, s.toetip.y)/rangeMax // Add some bias to poses where the leg is in the middle of the swing // i.e. the foot position is close to the middle of the foot curve +Mathf.Abs( Util.ProjectOntoPlane(s.middle-cycles[leg].cycleCenter, Vector3.up).magnitude )/cycles[leg].cycleScaling; // Use the new value if it is lower (better). if (sampleValue<stanceValue) { cycles[leg].stanceIndex = i; stanceValue = sampleValue; } } } else { cycles[leg].cycleDirection = Vector3.forward; cycles[leg].cycleScaling = 0; cycles[leg].stanceIndex = 0; } // The stance time cycles[leg].stanceTime = GetTimeFromIndex(cycles[leg].stanceIndex); // The stance index sample LegCycleSample ss = cycles[leg].samples[cycles[leg].stanceIndex]; // Sample the animation at stance time gameObject.SampleAnimation(animation,cycles[leg].stanceTime*animation.length); // Using the stance sample as reference we can now determine: // The vector from heel to toetip at the stance pose cycles[leg].heelToetipVector = ( ss.toeMatrix.MultiplyPoint(legC.legs[leg].toeToetipVector) - ss.ankleMatrix.MultiplyPoint(legC.legs[leg].ankleHeelVector) ); cycles[leg].heelToetipVector = Util.ProjectOntoPlane(cycles[leg].heelToetipVector, Vector3.up); cycles[leg].heelToetipVector = cycles[leg].heelToetipVector.normalized * legC.legs[leg].footLength; // Calculate foot flight path based on weighted average between ankle flight path and toe flight path, // using foot balance as weight. // The distance between ankle and toe is accounted for, using the stance pose for reference. for (int i=0; i<samples+1; i++) { LegCycleSample s = cycles[leg].samples[i]; s.footBase = ( (s.heel)*(1-s.balance) +(s.toetip-cycles[leg].heelToetipVector)*(s.balance) ); } // The position of the footbase in the stance pose cycles[leg].stancePosition = ss.footBase; cycles[leg].stancePosition.y = legC.groundPlaneHeight; if (motionType==MotionType.WalkCycle) { // Find contact times: // Strike time: foot first touches the ground (0% grounding) // Down time: all of the foot touches the ground (100% grounding) // Lift time: all of the foot still touches the ground but begins to lift (100% grounding) // Liftoff time: last part of the foot leaves the ground (0% grounding) float timeA; float timeB; // Find upwards contact times for projected ankle and toe // Use the first occurance as lift time and the second as liftoff time timeA = FindContactTime(cycles[leg], false, +1, rangeMax, 0.1f); cycles[leg].debugInfo.ankleLiftTime = timeA; timeB = FindContactTime(cycles[leg], true, +1, rangeMax, 0.1f); cycles[leg].debugInfo.toeLiftTime = timeB; if (timeA<timeB) { cycles[leg].liftTime = timeA; cycles[leg].liftoffTime = timeB; } else { cycles[leg].liftTime = timeB; cycles[leg].liftoffTime = timeA; } // Find time where swing direction and speed changes significantly. // If this happens sooner than the found liftoff time, // then the liftoff time must be overwritten with this value. timeA = FindSwingChangeTime(cycles[leg], +1, 0.5f); cycles[leg].debugInfo.footLiftTime = timeA; if (cycles[leg].liftoffTime > timeA) { cycles[leg].liftoffTime = timeA; if (cycles[leg].liftTime > cycles[leg].liftoffTime) { cycles[leg].liftTime = cycles[leg].liftoffTime; } } // Find downwards contact times for projected ankle and toe // Use the first occurance as strike time and the second as down time timeA = FindContactTime(cycles[leg], false, -1, rangeMax, 0.1f); timeB = FindContactTime(cycles[leg], true, -1, rangeMax, 0.1f); if (timeA<timeB) { cycles[leg].strikeTime = timeA; cycles[leg].landTime = timeB; } else { cycles[leg].strikeTime = timeB; cycles[leg].landTime = timeA; } // Find time where swing direction and speed changes significantly. // If this happens later than the found strike time, // then the strike time must be overwritten with this value. timeA = FindSwingChangeTime(cycles[leg], -1, 0.5f); cycles[leg].debugInfo.footLandTime = timeA; if (cycles[leg].strikeTime < timeA) { cycles[leg].strikeTime = timeA; if (cycles[leg].landTime < cycles[leg].strikeTime) { cycles[leg].landTime = cycles[leg].strikeTime; } } // Set postliftTime and prelandTime float softening = 0.2f; cycles[leg].postliftTime = cycles[leg].liftoffTime; if (cycles[leg].postliftTime < cycles[leg].liftTime+softening) { cycles[leg].postliftTime = cycles[leg].liftTime+softening; } cycles[leg].prelandTime = cycles[leg].strikeTime; if (cycles[leg].prelandTime > cycles[leg].landTime-softening) { cycles[leg].prelandTime = cycles[leg].landTime-softening; } // Calculate the distance traveled during one cycle (for this foot). Vector3 stanceSlideVector = ( cycles[leg].samples[GetIndexFromTime(Util.Mod(cycles[leg].liftoffTime+cycles[leg].stanceTime))].footBase -cycles[leg].samples[GetIndexFromTime(Util.Mod(cycles[leg].strikeTime+cycles[leg].stanceTime))].footBase ); // FIXME: Assumes horizontal ground plane stanceSlideVector.y = 0; cycles[leg].cycleDistance = stanceSlideVector.magnitude/(cycles[leg].liftoffTime-cycles[leg].strikeTime+1); cycles[leg].cycleDirection = -(stanceSlideVector.normalized); } else { cycles[leg].cycleDirection = Vector3.zero; cycles[leg].cycleDistance = 0; } graphMax.y = Mathf.Max(graphMax.y,Mathf.Max(ankleMax,toeMax)); } // Find the overall speed and direction traveled during one cycle, // based on average of speed values for each individual foot. // (They should be very close, but animations are often imperfect, // leading to different speeds for different legs.) m_cycleDistance = 0; m_cycleDirection = Vector3.zero; for (int leg=0; leg<legs; leg++) { m_cycleDistance += cycles[leg].cycleDistance; m_cycleDirection += cycles[leg].cycleDirection; Debug.Log("Cycle direction of leg "+leg+" is "+cycles[leg].cycleDirection+" with step distance "+cycles[leg].cycleDistance); } m_cycleDistance /= legs; m_cycleDirection /= legs; m_cycleDuration = animation.length; m_cycleSpeed = cycleDistance/cycleDuration; Debug.Log("Overall cycle direction is "+m_cycleDirection+" with step distance "+m_cycleDistance+" and speed "+m_cycleSpeed); nativeSpeed = m_cycleSpeed * gameObject.transform.localScale.x; // Calculate normalized foot flight path for (int leg=0; leg<legs; leg++) { if (motionType==MotionType.WalkCycle) { for (int j=0; j<samples; j++) { int i = Util.Mod(j+cycles[leg].stanceIndex,samples); LegCycleSample s = cycles[leg].samples[i]; float time = GetTimeFromIndex(j); s.footBaseNormalized = s.footBase; if (fixFootSkating) { // Calculate normalized foot flight path // based on the calculated cycle distance of each individual foot Vector3 reference = ( -cycles[leg].cycleDistance * cycles[leg].cycleDirection * (time-cycles[leg].liftoffTime) +cycles[leg].samples[ GetIndexFromTime(cycles[leg].liftoffTime+cycles[leg].stanceTime) ].footBase ); s.footBaseNormalized = (s.footBaseNormalized-reference); if (cycles[leg].cycleDirection!=Vector3.zero) { s.footBaseNormalized = Quaternion.Inverse( Quaternion.LookRotation(cycles[leg].cycleDirection) ) * s.footBaseNormalized; } s.footBaseNormalized.z /= cycles[leg].cycleDistance; if (time<=cycles[leg].liftoffTime) { s.footBaseNormalized.z = 0; } if (time>=cycles[leg].strikeTime) { s.footBaseNormalized.z = 1; } s.footBaseNormalized.y = s.footBase.y - legC.groundPlaneHeight; } else { // Calculate normalized foot flight path // based on the cycle distance of the whole motion // (the calculated average cycle distance) Vector3 reference = ( -m_cycleDistance * m_cycleDirection * (time-cycles[leg].liftoffTime*0) // FIXME: Is same as stance position: +cycles[leg].samples[ GetIndexFromTime(cycles[leg].liftoffTime*0+cycles[leg].stanceTime) ].footBase ); s.footBaseNormalized = (s.footBaseNormalized-reference); if (cycles[leg].cycleDirection!=Vector3.zero) { s.footBaseNormalized = Quaternion.Inverse( Quaternion.LookRotation(m_cycleDirection) ) * s.footBaseNormalized; } s.footBaseNormalized.z /= m_cycleDistance; s.footBaseNormalized.y = s.footBase.y - legC.groundPlaneHeight; } } //cycles[leg].samples[cycles[leg].stanceIndex].footBaseNormalized.z = 0; cycles[leg].samples[samples] = cycles[leg].samples[0]; } else { for (int j=0; j<samples; j++) { int i = Util.Mod(j+cycles[leg].stanceIndex,samples); LegCycleSample s = cycles[leg].samples[i]; s.footBaseNormalized = s.footBase - cycles[leg].stancePosition; } } } for (int leg=0; leg<legs; leg++) { float heelToeZDist = Vector3.Dot(cycles[leg].heelToetipVector,cycleDirection); for (int i=0; i<samples; i++) { LegCycleSample s = cycles[leg].samples[i]; float zVal = Vector3.Dot(s.footBase, cycleDirection); if (zVal < graphMin.z) graphMin.z = zVal; if (zVal > graphMax.z) graphMax.z = zVal; if (zVal+heelToeZDist < graphMin.z) graphMin.z = zVal+heelToeZDist; if (zVal+heelToeZDist > graphMax.z) graphMax.z = zVal+heelToeZDist; } } graphMin.y = legC.groundPlaneHeight; }
public override void OnInspectorGUI() { LegController lc = target as LegController; if (!lc) { return; } EditorGUIUtility.LookLikeControls(); lc.groundPlaneHeight = EditorGUILayout.FloatField("Ground Height", lc.groundPlaneHeight); lc.groundedPose = EditorGUILayout.ObjectField("Grounded Pose", lc.groundedPose, typeof(AnimationClip)) as AnimationClip; lc.rootBone = EditorGUILayout.ObjectField("Root Bone", lc.rootBone, typeof(Transform)) as Transform; EditorGUILayout.Space(); // Handle legs array List <LegInfo> legs = new List <LegInfo>(lc.legs); if (legs.Count != legFoldouts.Count) { legFoldouts = new List <bool>(new bool[legs.Count]); } legsFoldout = EditorGUILayout.Foldout(legsFoldout, "Legs"); if (legsFoldout) { GUI.changed = false; int removeIndex = -1; for (int l = 0; l < legs.Count; l++) { GUILayout.BeginHorizontal(); string str = "Leg " + (l + 1) + (legs[l].hip != null ? " (" + legs[l].hip.name + ")" : ""); legFoldouts[l] = EditorGUILayout.Foldout(legFoldouts[l], str); if (GUILayout.Button("Remove", GUILayout.Width(80))) { removeIndex = l; } GUILayout.EndHorizontal(); if (legFoldouts[l]) { EditorGUI.indentLevel++; LegInfo li = legs[l]; li.hip = EditorGUILayout.ObjectField("Hip", li.hip, typeof(Transform)) as Transform; li.ankle = EditorGUILayout.ObjectField("Ankle", li.ankle, typeof(Transform)) as Transform; li.toe = EditorGUILayout.ObjectField("Toe", li.toe, typeof(Transform)) as Transform; GUILayout.BeginHorizontal(); EditorGUILayout.PrefixLabel("Foot"); GUILayout.BeginVertical(); GUILayout.Label("Width", GUILayout.Width(40)); GUILayout.Label("Length", GUILayout.Width(40)); GUILayout.EndVertical(); GUILayout.BeginVertical(); li.footWidth = EditorGUILayout.FloatField(li.footWidth, GUILayout.Width(50)); li.footLength = EditorGUILayout.FloatField(li.footLength, GUILayout.Width(50)); GUILayout.EndVertical(); GUILayout.BeginVertical(); GUILayout.Label("Offset", GUILayout.Width(40)); GUILayout.Label("Offset", GUILayout.Width(40)); GUILayout.EndVertical(); GUILayout.BeginVertical(); li.footOffset.x = EditorGUILayout.FloatField(li.footOffset.x, GUILayout.Width(50)); li.footOffset.y = EditorGUILayout.FloatField(li.footOffset.y, GUILayout.Width(50)); GUILayout.EndVertical(); GUILayout.EndHorizontal(); EditorGUI.indentLevel--; EditorGUILayout.Space(); } } // Remove a leg? if (removeIndex >= 0) { legs.RemoveAt(removeIndex); legFoldouts.RemoveAt(removeIndex); } // Add a leg? GUILayout.BeginHorizontal(); GUILayout.Label(""); if (GUILayout.Button("Add Leg", GUILayout.Width(80))) { LegInfo li = new LegInfo(); if (legs.Count > 0) { li.footWidth = legs[legs.Count - 1].footWidth; li.footLength = legs[legs.Count - 1].footLength; li.footOffset = legs[legs.Count - 1].footOffset; } legs.Add(li); legFoldouts.Add(true); } GUILayout.EndHorizontal(); lc.legs = legs.ToArray(); } EditorGUILayout.Space(); // Handle animations array animsFoldout = EditorGUILayout.Foldout(animsFoldout, "Source Animations"); if (animsFoldout) { GUI.changed = false; List <InspectorAnimationGroup> groups = new List <InspectorAnimationGroup>(); groups.Add(new InspectorAnimationGroup("")); if (GUILayout.Button("Reset") || lc.sourceAnimations.Length == 0) { AnimationClip[] clips = AnimationUtility.GetAnimationClips(lc.animation); for (int c = 0; c < clips.Length; c++) { MotionAnalyzer motion = new MotionAnalyzer(); motion.animation = clips[c]; //motion.motionGroup = ""; groups[0].motions.Add(motion); } GUI.changed = true; } else { for (int m = 0; m < lc.sourceAnimations.Length; m++) { MotionAnalyzer ma = lc.sourceAnimations[m]; if (ma.motionGroup == null) { ma.motionGroup = ""; } bool found = false; for (int g = 0; g < groups.Count; g++) { if (ma.motionGroup == groups[g].name) { groups[g].motions.Add(ma); found = true; } } if (!found) { InspectorAnimationGroup group = new InspectorAnimationGroup(ma.motionGroup); group.motions.Add(ma); groups.Add(group); } } } groups.Add(new InspectorAnimationGroup("NewGroup")); groups.Add(new InspectorAnimationGroup("Remove")); string[] groupNames = new string[groups.Count]; for (int g = 0; g < groups.Count; g++) { groupNames[g] = groups[g].name; } groupNames[0] = "Ungrouped"; for (int g = 0; g < groups.Count - 1; g++) { InspectorAnimationGroup group = groups[g]; if (group.motions.Count == 0) { continue; } if (group.name == "") { GUILayout.Label("Ungrouped Animations"); } else { GUILayout.BeginHorizontal(); GUILayout.Label("Animation Group:", GUILayout.ExpandWidth(false)); group.name = GUILayout.TextField(group.name, GUILayout.ExpandWidth(true)); GUILayout.EndHorizontal(); } for (int m = 0; m < group.motions.Count; m++) { MotionAnalyzer ma = group.motions[m]; GUILayout.BeginHorizontal(); ma.animation = EditorGUILayout.ObjectField(ma.animation, typeof(AnimationClip)) as AnimationClip; ma.motionType = (MotionType)EditorGUILayout.EnumPopup(ma.motionType, GUILayout.Width(70)); //ma.alsoUseBackwards = GUILayout.Toggle(ma.alsoUseBackwards, "", GUILayout.Width(15)); //ma.fixFootSkating = GUILayout.Toggle(ma.fixFootSkating, "", GUILayout.Width(15)); int selectedGroup = EditorGUILayout.Popup(g, groupNames, GUILayout.Width(70)); if (selectedGroup != g) { group.motions.Remove(ma); groups[selectedGroup].motions.Add(ma); GUI.changed = true; } GUILayout.Label("" + ma.nativeSpeed, GUILayout.Width(40)); GUILayout.EndHorizontal(); } if (GUILayout.Button("Add Animation to " + groupNames[g])) { MotionAnalyzer motion = new MotionAnalyzer(); group.motions.Add(motion); GUI.changed = true; } EditorGUILayout.Space(); } if (GUI.changed) { List <MotionAnalyzer> motions = new List <MotionAnalyzer>(); for (int g = 0; g < groups.Count - 1; g++) { for (int m = 0; m < groups[g].motions.Count; m++) { groups[g].motions[m].motionGroup = groups[g].name; motions.Add(groups[g].motions[m]); } } lc.sourceAnimations = motions.ToArray(); } } }
protected LegInfo getLegInfo(LegController leg) { LegInfo info; if (!legInfo.TryGetValue(leg, out info)) { info = new LegInfo(this, leg); legInfo.Add(leg, info); } return info; }
void CopySerialized(Transform src, Transform tar) { if (src == null || tar == null) { return; } Rigidbody rigid = src.GetComponent <Rigidbody>(); if (rigid != null) { Rigidbody rigid1 = tar.GetComponent <Rigidbody>(); if (rigid1 == null) { rigid1 = tar.gameObject.AddComponent <Rigidbody>(); } EditorUtility.CopySerialized(rigid, rigid1); } CapsuleCollider cap1 = src.GetComponent <CapsuleCollider>(); if (cap1 != null) { CapsuleCollider cap2 = tar.GetComponent <CapsuleCollider>(); if (cap2 == null) { cap2 = tar.gameObject.AddComponent <CapsuleCollider>(); } EditorUtility.CopySerialized(cap1, cap2); cap2.center *= scale; cap2.radius *= scale; cap2.height *= scale; } SphereCollider s1 = src.GetComponent <SphereCollider>(); if (s1 != null) { SphereCollider s2 = tar.GetComponent <SphereCollider>(); if (s2 == null) { s2 = tar.gameObject.AddComponent <SphereCollider>(); } EditorUtility.CopySerialized(s1, s2); s2.center *= scale; s2.radius *= scale; } BoxCollider box1 = src.GetComponent <BoxCollider>(); if (box1 != null) { BoxCollider box2 = tar.GetComponent <BoxCollider>(); if (box2 == null) { box2 = tar.gameObject.AddComponent <BoxCollider>(); } EditorUtility.CopySerialized(box1, box2); box2.center *= scale; box2.size *= scale; } CharacterJoint joint1 = src.GetComponent <CharacterJoint>(); if (joint1 != null) { CharacterJoint joint2 = tar.GetComponent <CharacterJoint>(); if (joint2 == null) { joint2 = tar.gameObject.AddComponent <CharacterJoint>(); } EditorUtility.CopySerialized(joint1, joint2); joint2.connectedBody = AiUtil.GetChild(target.transform, joint2.connectedBody.name).GetComponent <Rigidbody>(); } LegController leg1 = src.GetComponent <LegController>(); if (leg1 != null) { LegController leg2 = tar.GetComponent <LegController>(); if (leg2 == null) { leg2 = tar.gameObject.AddComponent <LegController>(); } EditorUtility.CopySerialized(leg1, leg2); leg2.groundedPose = target.GetComponent <Animation>()[leg2.groundedPose.name].clip; leg2.rootBone = AiUtil.GetChild(target.transform, leg2.rootBone.name); foreach (LegInfo leg in leg2.legs) { leg.ankle = AiUtil.GetChild(target.transform, leg.ankle.name); leg.hip = AiUtil.GetChild(target.transform, leg.hip.name); leg.toe = AiUtil.GetChild(target.transform, leg.toe.name); leg.footLength *= scale; leg.footWidth *= scale; leg.footOffset.x *= scale; leg.footOffset.y *= scale; } foreach (MotionAnalyzer motion in leg2.sourceAnimations) { motion.animation = target.GetComponent <Animation>()[motion.animation.name].clip; } } AlignmentTracker al1 = src.GetComponent <AlignmentTracker>(); if (leg1 != null) { AlignmentTracker al2 = tar.GetComponent <AlignmentTracker>(); if (al2 == null) { al2 = tar.gameObject.AddComponent <AlignmentTracker>(); } EditorUtility.CopySerialized(al1, al2); } LegAnimator legA1 = src.GetComponent <LegAnimator>(); if (legA1 != null) { LegAnimator legA2 = tar.GetComponent <LegAnimator>(); if (legA2 == null) { legA2 = tar.gameObject.AddComponent <LegAnimator>(); } EditorUtility.CopySerialized(legA1, legA2); } }
protected override void initialize() { this.m_PlayerMotor = (base.GetComponent(typeof(M_PlayerMotor)) as M_PlayerMotor); if (this.m_PlayerMotor == null) { Debug.Log("Motor is null!!"); } this.m_JumpMotor = (base.GetComponent(typeof(JumpAndIdle)) as JumpAndIdle); Vector3 position = base.transform.position; if (!base.GetComponent <NavMeshAgent>()) { this.m_NavMeshAgent = base.gameObject.AddComponent <NavMeshAgent>(); this.m_NavMeshAgent.acceleration = 200f; this.m_NavMeshAgent.angularSpeed = 500f; this.m_NavMeshAgent.baseOffset = -0.01f; this.m_NavMeshAgent.walkableMask = 1; this.m_NavMeshAgent.enabled = false; } base.transform.position = position; this.m_RoleMotion = base.GetComponent <M_GameRoleMotion>(); if (this.m_RoleMotion != null) { this.m_RoleMotion.Init(base.RoleID, 601); } LegAnimator component = base.gameObject.GetComponent <LegAnimator>(); if (component) { int num = 1024; num |= 4; num |= 16; num = ~num; component.groundLayers = num; } LegController component2 = base.gameObject.GetComponent <LegController>(); if (component2) { for (int i = 0; i < component2.sourceAnimations.Length; i++) { if (component2.sourceAnimations[i].name == "walk") { this.m_WalkSpeed = component2.sourceAnimations[i].nativeSpeed; } if (component2.sourceAnimations[i].name == "run") { this.m_RunSpeed = component2.sourceAnimations[i].nativeSpeed; } if (component2.sourceAnimations[i].name == "sprint") { this.m_DashSpeed = component2.sourceAnimations[i].nativeSpeed; } } } base.gameObject.AddComponent <M_FootStep>(); if (Swd6Application.instance.m_ExploreSystem.m_MapData.emType == ENUM_MapType.World) { this.m_RunSpeed = 3.6f; } this.targetPointObj = Swd6Application.instance.m_ExploreSystem.m_MoveTargetPoint; this.m_GuiManager = Swd6Application.instance.guiManager; this.m_MoveTarget = null; this.m_IsRun = Swd6Application.instance.m_ExploreSystem.Run; this.m_PlayerMotor.maxForwardSpeed = this.m_RunSpeed; this.m_JumpHeight = this.m_PlayerMotor.jumpHeight; this.m_JumpGravity = this.m_PlayerMotor.gravity; if (Swd6Application.instance.m_ExploreSystem.m_MapData.emType == ENUM_MapType.Town) { this.m_JumpHeight = 1.1f; } this.PlayFaceMotion(2); UI_Explore.Instance.SetDashState(false, this.m_IsRun); if (Swd6Application.instance.m_ResourceType == ENUM_ResourceType.Develop) { Debug.Log("Player Init OK!!"); } }
/// <summary> /// Same as the original Start() function, but remaps transforms to /// shadow transforms. The original LegAnimator got references to /// Transform objects that corresponded to the root, feet, ankle, hip, /// etc. from Transforms that were input by the user as fields of the /// LegController class. These must be remapped to the corresponding /// transforms in the shadow, and that is what the Start() function does. /// </summary> public override void ControlledStart() { legC = GetComponent(typeof(LegController)) as LegController; legs = legC.legs; // NB: We need to change the root bone of LegController to equivalent // bone of the shadow's skeleton. This is because the LegController's // root bone is set by the user in the inspector, and this is a // reference to the original bone, not the shadow's bone. - NM LegController leg_ctrl = GetComponent<LegController>(); legC.rootBone = this.shadow.FindInShadow(leg_ctrl.rootBone); // NB: Similar to when we set the rootBone of the LegController, we // need to change all the references for hip/angle/toe to references // to the SHADOW's hip, ankle, and toe. These references originally // refer to the original skeleton's transforms, since they are input // by the user. - NM for (int i = 0; i < legs.Length; i++) { legs[i].hip = this.shadow.FindInShadow(legs[i].hip); legs[i].ankle = this.shadow.FindInShadow(legs[i].ankle); legs[i].toe = this.shadow.FindInShadow(legs[i].toe); for (int j = 0; j < legs[i].legChain.Length; j++) legs[i].legChain[j] = this.shadow.FindInShadow(legs[i].legChain[j]); for (int j = 0; j < legs[i].footChain.Length; j++) legs[i].footChain[j] = this.shadow.FindInShadow(legs[i].footChain[j]); } if (legC.initialized == false) { UnityEngine.Debug.LogError( name + ": Locomotion System has not been initialized.", this); this.enabled = false; } legStates = new LegState[legs.Length]; updateStates = true; stupidRaycasts = true; ResetMotionStates(); ResetSteps(); stupidRaycasts = false; 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)); } }
protected float calculateAltitudeAdjustment(Vector3 stepOffset, LegController leg) { Vector3 maxStepPos = stepOffset + new Vector3(0, maxStepHeight, 0); RaycastHit hitInfo = new RaycastHit(); float yOffset = 0f; if(Physics.Raycast(new Ray(maxStepPos, new Vector3(0, -1, 0)), out hitInfo, maxStepHeight * 10)) { #if UNITY_EDITOR if(debug) { drawPoint(hitInfo.point, Color.green, leg + "one"); drawPoint(stepOffset, Color.red, leg + "two"); } #endif yOffset = hitInfo.point.y - stepOffset.y; } return yOffset; }
protected void updateLegs(LegController[] group, bool planted) { foreach(LegController leg in group) { LegInfo info = getLegInfo(leg); leg.setPosition(getLegInfo(leg).foot); info.setPlanted(planted); info.setLastDefault(); } }