123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- using UnityEngine;
- using System.Collections;
- namespace RootMotion.Demos {
- /// <summary>
- /// Mech spider Demo.
- /// </summary>
- public class MechSpider : MonoBehaviour {
- public LayerMask raycastLayers; // The ground layers
- public float scale = 1f; // For resizing the values when the mech is resized
- public Transform body; // The body transform, the root of the legs
- public MechSpiderLeg[] legs; // All the legs of this spider
- public float legRotationWeight = 1f; // The weight of rotating the body to each leg
- public float rootPositionSpeed = 5f; // The speed of positioning the root
- public float rootRotationSpeed = 30f; // The slerp speed of rotating the root to leg heights
- public float breatheSpeed = 2f; // Speed of the breathing cycle
- public float breatheMagnitude = 0.2f; // Magnitude of breathing
- public float height = 3.5f; // Height from ground
- public float minHeight = 2f; // The minimum height from ground
- public float raycastHeight = 10f; // The height of ray origin
- public float raycastDistance = 5f; // The distance of rays (total ray length = raycastHeight + raycastDistance)
- public Vector3 velocity { get; private set; }
- private Vector3 lastPosition;
- private Vector3 defaultBodyLocalPosition;
- private float sine;
- private RaycastHit rootHit;
- private void Start()
- {
- lastPosition = transform.position;
- }
- void Update() {
- velocity = (transform.position - lastPosition) / Time.deltaTime;
- lastPosition = transform.position;
- // Find the normal of the plane defined by leg positions
- Vector3 legsPlaneNormal = GetLegsPlaneNormal();
- // Rotating the root
- Quaternion fromTo = Quaternion.FromToRotation(transform.up, legsPlaneNormal);
- transform.rotation = Quaternion.Slerp(transform.rotation, fromTo * transform.rotation, Time.deltaTime * rootRotationSpeed);
- // Positioning the root
- Vector3 legCentroid = GetLegCentroid();
- Vector3 heightOffset = Vector3.Project((legCentroid + transform.up * height * scale) - transform.position, transform.up);
- transform.position += heightOffset * Time.deltaTime * (rootPositionSpeed * scale);
- if (Physics.Raycast(transform.position + transform.up * raycastHeight * scale, -transform.up, out rootHit, (raycastHeight * scale) + (raycastDistance * scale), raycastLayers)) {
- rootHit.distance -= (raycastHeight * scale) + (minHeight * scale);
- if (rootHit.distance < 0f) {
- Vector3 targetPosition = transform.position - transform.up * rootHit.distance;
- transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * rootPositionSpeed * scale);
- }
- }
- // Update Breathing
- sine += Time.deltaTime * breatheSpeed;
- if (sine >= Mathf.PI * 2f) sine -= Mathf.PI * 2f;
- float br = Mathf.Sin(sine) * breatheMagnitude * scale;
- // Apply breathing
- Vector3 breatheOffset = transform.up * br;
- body.transform.position = transform.position + breatheOffset;
- }
- // Calculate the normal of the plane defined by leg positions, so we know how to rotate the body
- private Vector3 GetLegCentroid() {
- Vector3 position = Vector3.zero;
- float footWeight = 1f / (float)legs.Length;
-
- // Go through all the legs, rotate the normal by it's offset
- for (int i = 0; i < legs.Length; i++) {
- position += legs[i].position * footWeight;
- }
-
- return position;
- }
- // Calculate the normal of the plane defined by leg positions, so we know how to rotate the body
- private Vector3 GetLegsPlaneNormal() {
- Vector3 normal = transform.up;
- if (legRotationWeight <= 0f) return normal;
- float legWeight = 1f / Mathf.Lerp(legs.Length, 1f, legRotationWeight);
- // Go through all the legs, rotate the normal by it's offset
- for (int i = 0; i < legs.Length; i++) {
- // Direction from the root to the leg
- Vector3 legDirection = legs[i].position - (transform.position - transform.up * height * scale);
- // Find the tangent to transform.up
- Vector3 legNormal = transform.up;
- Vector3 legTangent = legDirection;
- Vector3.OrthoNormalize(ref legNormal, ref legTangent);
- // Find the rotation offset from the tangent to the direction
- Quaternion fromTo = Quaternion.FromToRotation(legTangent, legDirection);
- fromTo = Quaternion.Lerp(Quaternion.identity, fromTo, legWeight);
- // Rotate the normal
- normal = fromTo * normal;
- }
-
- return normal;
- }
- }
- }
|