Added FinalIK
This commit is contained in:
@@ -0,0 +1,188 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using RootMotion.FinalIK;
|
||||
|
||||
namespace RootMotion.Demos {
|
||||
|
||||
/// <summary>
|
||||
/// Demo script for using the Interaction System for touching scene geometry.
|
||||
/// </summary>
|
||||
public class TouchWalls : MonoBehaviour {
|
||||
|
||||
/// <summary>
|
||||
/// Touching functionality for an effector
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class EffectorLink {
|
||||
public bool enabled = true; // Can this effector start touching?
|
||||
public FullBodyBipedEffector effectorType; // The type of the effector
|
||||
public InteractionObject interactionObject; // The touch interaction object
|
||||
public Transform spherecastFrom; // The bone to start the sperecast from
|
||||
public float spherecastRadius = 0.1f; // The radius of sperecasting
|
||||
public float minDistance = 0.3f; // The minimum spherecast radius to touch
|
||||
public float distanceMlp = 1f; // Multiplies the distance of the spherecast
|
||||
public LayerMask touchLayers; // The layers to touch
|
||||
public float lerpSpeed = 10f; // The speed of lerping the interaction object
|
||||
public float minSwitchTime = 0.2f; // The minimum time to switch between touching
|
||||
public float releaseDistance= 0.4f; // The distance from the original touch point where the effector will lose contact
|
||||
public bool sliding; // Can the effector slide smoothly over the surfaces?
|
||||
|
||||
private Vector3 raycastDirectionLocal;
|
||||
private float raycastDistance;
|
||||
private bool inTouch;
|
||||
private RaycastHit hit = new RaycastHit();
|
||||
private Vector3 targetPosition;
|
||||
private Quaternion targetRotation;
|
||||
private bool initiated;
|
||||
private float nextSwitchTime;
|
||||
private float speedF;
|
||||
|
||||
// Initiate this instance
|
||||
public void Initiate(InteractionSystem interactionSystem) {
|
||||
// Find the direction to the interaction objet relative to the sperecastFrom Transform
|
||||
raycastDirectionLocal = spherecastFrom.InverseTransformDirection(interactionObject.transform.position - spherecastFrom.position);
|
||||
|
||||
// Find the max distance the sperecast
|
||||
raycastDistance = Vector3.Distance(spherecastFrom.position, interactionObject.transform.position);
|
||||
|
||||
// Add to the interaction system delegates
|
||||
interactionSystem.OnInteractionStart += OnInteractionStart;
|
||||
interactionSystem.OnInteractionResume += OnInteractionResume;
|
||||
interactionSystem.OnInteractionStop += OnInteractionStop;
|
||||
|
||||
hit.normal = Vector3.forward;
|
||||
targetPosition = interactionObject.transform.position;
|
||||
targetRotation = interactionObject.transform.rotation;
|
||||
|
||||
initiated = true;
|
||||
}
|
||||
|
||||
// Spherecasting to find the walls
|
||||
private bool FindWalls(Vector3 direction) {
|
||||
if (!enabled) return false;
|
||||
bool found = Physics.SphereCast(spherecastFrom.position, spherecastRadius, direction, out hit, raycastDistance * distanceMlp, touchLayers);
|
||||
|
||||
if (hit.distance < minDistance) found = false;
|
||||
return found;
|
||||
}
|
||||
|
||||
// Update this instance
|
||||
public void Update(InteractionSystem interactionSystem) {
|
||||
if (!initiated) return;
|
||||
|
||||
// The default position
|
||||
Vector3 direction = spherecastFrom.TransformDirection(raycastDirectionLocal);
|
||||
hit.point = spherecastFrom.position + direction;
|
||||
|
||||
// Spherecasting
|
||||
bool wallFound = FindWalls(direction);
|
||||
|
||||
// Starting and ending the interactions
|
||||
if (!inTouch) {
|
||||
if (wallFound && Time.time > nextSwitchTime) {
|
||||
interactionObject.transform.parent = null;
|
||||
interactionSystem.StartInteraction(effectorType, interactionObject, true);
|
||||
nextSwitchTime = Time.time + minSwitchTime / interactionSystem.speed;
|
||||
|
||||
targetPosition = hit.point;
|
||||
targetRotation = Quaternion.LookRotation(-hit.normal);
|
||||
|
||||
interactionObject.transform.position = targetPosition;
|
||||
interactionObject.transform.rotation = targetRotation;
|
||||
}
|
||||
} else {
|
||||
if (!wallFound) {
|
||||
// Resume if no wall found
|
||||
StopTouch(interactionSystem);
|
||||
} else {
|
||||
if (!interactionSystem.IsPaused(effectorType) || sliding) {
|
||||
targetPosition = hit.point;
|
||||
targetRotation = Quaternion.LookRotation(-hit.normal);
|
||||
}
|
||||
}
|
||||
|
||||
if (Vector3.Distance(interactionObject.transform.position, hit.point) > releaseDistance) {
|
||||
if (wallFound) {
|
||||
targetPosition = hit.point;
|
||||
targetRotation = Quaternion.LookRotation(-hit.normal);
|
||||
} else {
|
||||
StopTouch(interactionSystem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float speedFTarget = !inTouch || (interactionSystem.IsPaused(effectorType) && interactionObject.transform.position == targetPosition)? 0f: 1f;
|
||||
speedF = Mathf.Lerp(speedF, speedFTarget, Time.deltaTime * 3f * interactionSystem.speed);
|
||||
|
||||
// Interpolating the interaction object
|
||||
float s = Time.deltaTime * lerpSpeed * speedF * interactionSystem.speed;
|
||||
interactionObject.transform.position = Vector3.Lerp(interactionObject.transform.position, targetPosition, s);
|
||||
interactionObject.transform.rotation = Quaternion.Slerp(interactionObject.transform.rotation, targetRotation, s);
|
||||
}
|
||||
|
||||
// Stop touching the walls
|
||||
private void StopTouch(InteractionSystem interactionSystem) {
|
||||
interactionObject.transform.parent = interactionSystem.transform;
|
||||
nextSwitchTime = Time.time + minSwitchTime / interactionSystem.speed;
|
||||
|
||||
if (interactionSystem.IsPaused(effectorType)) interactionSystem.ResumeInteraction(effectorType);
|
||||
else {
|
||||
speedF = 0f;
|
||||
targetPosition = hit.point;
|
||||
if (hit.normal != Vector3.zero) targetRotation = Quaternion.LookRotation(-hit.normal);
|
||||
}
|
||||
}
|
||||
|
||||
// Called by the interaction system
|
||||
private void OnInteractionStart(FullBodyBipedEffector effectorType, InteractionObject interactionObject) {
|
||||
if (effectorType != this.effectorType || interactionObject != this.interactionObject) return;
|
||||
|
||||
inTouch = true;
|
||||
}
|
||||
|
||||
// Called by the interaction system
|
||||
private void OnInteractionResume(FullBodyBipedEffector effectorType, InteractionObject interactionObject) {
|
||||
if (effectorType != this.effectorType || interactionObject != this.interactionObject) return;
|
||||
|
||||
inTouch = false;
|
||||
}
|
||||
|
||||
// Called by the interaction system
|
||||
private void OnInteractionStop(FullBodyBipedEffector effectorType, InteractionObject interactionObject) {
|
||||
if (effectorType != this.effectorType || interactionObject != this.interactionObject) return;
|
||||
|
||||
inTouch = false;
|
||||
}
|
||||
|
||||
// Cleaning up the delegates
|
||||
public void Destroy(InteractionSystem interactionSystem) {
|
||||
if (!initiated) return;
|
||||
|
||||
interactionSystem.OnInteractionStart -= OnInteractionStart;
|
||||
interactionSystem.OnInteractionResume -= OnInteractionResume;
|
||||
interactionSystem.OnInteractionStop -= OnInteractionStop;
|
||||
}
|
||||
}
|
||||
|
||||
public InteractionSystem interactionSystem; // Reference to the interaciton sytem of the character
|
||||
public EffectorLink[] effectorLinks; // The wall touching effectors
|
||||
|
||||
// Initiate the effector links
|
||||
void Start() {
|
||||
foreach (EffectorLink e in effectorLinks) e.Initiate(interactionSystem);
|
||||
}
|
||||
|
||||
// Update touching
|
||||
void FixedUpdate() {
|
||||
for (int i = 0; i < effectorLinks.Length; i++) effectorLinks[i].Update(interactionSystem);
|
||||
}
|
||||
|
||||
// Clean up the delegates
|
||||
void OnDestroy() {
|
||||
if (interactionSystem != null) {
|
||||
for (int i = 0; i < effectorLinks.Length; i++) effectorLinks[i].Destroy(interactionSystem);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user