980 lines
26 KiB
C#
980 lines
26 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.Serialization;
|
|
|
|
namespace RootMotion.FinalIK
|
|
{
|
|
[HelpURL("https://www.youtube.com/watch?v=r5jiZnsDH3M")]
|
|
[AddComponentMenu("Scripts/RootMotion.FinalIK/Interaction System/Interaction System")]
|
|
public class InteractionSystem : MonoBehaviour
|
|
{
|
|
public delegate void InteractionDelegate(FullBodyBipedEffector effectorType, InteractionObject interactionObject);
|
|
|
|
public delegate void InteractionEventDelegate(FullBodyBipedEffector effectorType, InteractionObject interactionObject, InteractionObject.InteractionEvent interactionEvent);
|
|
|
|
[Tooltip("If not empty, only the targets with the specified tag will be used by this Interaction System.")]
|
|
public string targetTag = "";
|
|
|
|
[Tooltip("The fade in time of the interaction.")]
|
|
public float fadeInTime = 0.3f;
|
|
|
|
[Tooltip("The master speed for all interactions.")]
|
|
public float speed = 1f;
|
|
|
|
[Tooltip("If > 0, lerps all the FBBIK channels used by the Interaction System back to their default or initial values when not in interaction.")]
|
|
public float resetToDefaultsSpeed = 1f;
|
|
|
|
[Header("Triggering")]
|
|
[Tooltip("The collider that registers OnTriggerEnter and OnTriggerExit events with InteractionTriggers.")]
|
|
[FormerlySerializedAs("collider")]
|
|
public Collider characterCollider;
|
|
|
|
[Tooltip("Will be used by Interaction Triggers that need the camera's position. Assign the first person view character camera.")]
|
|
[FormerlySerializedAs("camera")]
|
|
public Transform FPSCamera;
|
|
|
|
[Tooltip("The layers that will be raycasted from the camera (along camera.forward). All InteractionTrigger look at target colliders should be included.")]
|
|
public LayerMask camRaycastLayers;
|
|
|
|
[Tooltip("Max distance of raycasting from the camera.")]
|
|
public float camRaycastDistance = 1f;
|
|
|
|
private List<InteractionTrigger> inContact = new List<InteractionTrigger>();
|
|
|
|
private List<int> bestRangeIndexes = new List<int>();
|
|
|
|
public InteractionDelegate OnInteractionStart;
|
|
|
|
public InteractionDelegate OnInteractionPause;
|
|
|
|
public InteractionDelegate OnInteractionPickUp;
|
|
|
|
public InteractionDelegate OnInteractionResume;
|
|
|
|
public InteractionDelegate OnInteractionStop;
|
|
|
|
public InteractionEventDelegate OnInteractionEvent;
|
|
|
|
public RaycastHit raycastHit;
|
|
|
|
[Space(10f)]
|
|
[Tooltip("Reference to the FBBIK component.")]
|
|
[SerializeField]
|
|
private FullBodyBipedIK fullBody;
|
|
|
|
[Tooltip("Handles looking at the interactions.")]
|
|
public InteractionLookAt lookAt = new InteractionLookAt();
|
|
|
|
private InteractionEffector[] interactionEffectors = new InteractionEffector[9]
|
|
{
|
|
new InteractionEffector(FullBodyBipedEffector.Body),
|
|
new InteractionEffector(FullBodyBipedEffector.LeftFoot),
|
|
new InteractionEffector(FullBodyBipedEffector.LeftHand),
|
|
new InteractionEffector(FullBodyBipedEffector.LeftShoulder),
|
|
new InteractionEffector(FullBodyBipedEffector.LeftThigh),
|
|
new InteractionEffector(FullBodyBipedEffector.RightFoot),
|
|
new InteractionEffector(FullBodyBipedEffector.RightHand),
|
|
new InteractionEffector(FullBodyBipedEffector.RightShoulder),
|
|
new InteractionEffector(FullBodyBipedEffector.RightThigh)
|
|
};
|
|
|
|
private Collider lastCollider;
|
|
|
|
private Collider c;
|
|
|
|
private float lastTime;
|
|
|
|
public bool inInteraction
|
|
{
|
|
get
|
|
{
|
|
if (!IsValid(log: true))
|
|
{
|
|
return false;
|
|
}
|
|
for (int i = 0; i < interactionEffectors.Length; i++)
|
|
{
|
|
if (interactionEffectors[i].inInteraction && !interactionEffectors[i].isPaused)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public FullBodyBipedIK ik
|
|
{
|
|
get
|
|
{
|
|
return fullBody;
|
|
}
|
|
set
|
|
{
|
|
fullBody = value;
|
|
}
|
|
}
|
|
|
|
public List<InteractionTrigger> triggersInRange { get; private set; }
|
|
|
|
public bool initiated { get; private set; }
|
|
|
|
[ContextMenu("User Manual")]
|
|
private void OpenUserManual()
|
|
{
|
|
Application.OpenURL("http://www.root-motion.com/finalikdox/html/page10.html");
|
|
}
|
|
|
|
[ContextMenu("Scrpt Reference")]
|
|
private void OpenScriptReference()
|
|
{
|
|
Application.OpenURL("http://www.root-motion.com/finalikdox/html/class_root_motion_1_1_final_i_k_1_1_interaction_system.html");
|
|
}
|
|
|
|
[ContextMenu("TUTORIAL VIDEO (PART 1: BASICS)")]
|
|
private void OpenTutorial1()
|
|
{
|
|
Application.OpenURL("https://www.youtube.com/watch?v=r5jiZnsDH3M");
|
|
}
|
|
|
|
[ContextMenu("TUTORIAL VIDEO (PART 2: PICKING UP...)")]
|
|
private void OpenTutorial2()
|
|
{
|
|
Application.OpenURL("https://www.youtube.com/watch?v=eP9-zycoHLk");
|
|
}
|
|
|
|
[ContextMenu("TUTORIAL VIDEO (PART 3: ANIMATION)")]
|
|
private void OpenTutorial3()
|
|
{
|
|
Application.OpenURL("https://www.youtube.com/watch?v=sQfB2RcT1T4&index=14&list=PLVxSIA1OaTOu8Nos3CalXbJ2DrKnntMv6");
|
|
}
|
|
|
|
[ContextMenu("TUTORIAL VIDEO (PART 4: TRIGGERS)")]
|
|
private void OpenTutorial4()
|
|
{
|
|
Application.OpenURL("https://www.youtube.com/watch?v=-TDZpNjt2mk&index=15&list=PLVxSIA1OaTOu8Nos3CalXbJ2DrKnntMv6");
|
|
}
|
|
|
|
[ContextMenu("Support")]
|
|
private void SupportGroup()
|
|
{
|
|
Application.OpenURL("https://groups.google.com/forum/#!forum/final-ik");
|
|
}
|
|
|
|
[ContextMenu("Asset Store Thread")]
|
|
private void ASThread()
|
|
{
|
|
Application.OpenURL("http://forum.unity3d.com/threads/final-ik-full-body-ik-aim-look-at-fabrik-ccd-ik-1-0-released.222685/");
|
|
}
|
|
|
|
public bool IsInInteraction(FullBodyBipedEffector effectorType)
|
|
{
|
|
if (!IsValid(log: true))
|
|
{
|
|
return false;
|
|
}
|
|
for (int i = 0; i < interactionEffectors.Length; i++)
|
|
{
|
|
if (interactionEffectors[i].effectorType == effectorType)
|
|
{
|
|
if (interactionEffectors[i].inInteraction)
|
|
{
|
|
return !interactionEffectors[i].isPaused;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public bool IsPaused(FullBodyBipedEffector effectorType)
|
|
{
|
|
if (!IsValid(log: true))
|
|
{
|
|
return false;
|
|
}
|
|
for (int i = 0; i < interactionEffectors.Length; i++)
|
|
{
|
|
if (interactionEffectors[i].effectorType == effectorType)
|
|
{
|
|
if (interactionEffectors[i].inInteraction)
|
|
{
|
|
return interactionEffectors[i].isPaused;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public bool IsPaused()
|
|
{
|
|
if (!IsValid(log: true))
|
|
{
|
|
return false;
|
|
}
|
|
for (int i = 0; i < interactionEffectors.Length; i++)
|
|
{
|
|
if (interactionEffectors[i].inInteraction && interactionEffectors[i].isPaused)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public bool IsInSync()
|
|
{
|
|
if (!IsValid(log: true))
|
|
{
|
|
return false;
|
|
}
|
|
for (int i = 0; i < interactionEffectors.Length; i++)
|
|
{
|
|
if (!interactionEffectors[i].isPaused)
|
|
{
|
|
continue;
|
|
}
|
|
for (int j = 0; j < interactionEffectors.Length; j++)
|
|
{
|
|
if (j != i && interactionEffectors[j].inInteraction && !interactionEffectors[j].isPaused)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public bool StartInteraction(FullBodyBipedEffector effectorType, InteractionObject interactionObject, bool interrupt)
|
|
{
|
|
if (!IsValid(log: true))
|
|
{
|
|
return false;
|
|
}
|
|
if (interactionObject == null)
|
|
{
|
|
return false;
|
|
}
|
|
for (int i = 0; i < interactionEffectors.Length; i++)
|
|
{
|
|
if (interactionEffectors[i].effectorType == effectorType)
|
|
{
|
|
return interactionEffectors[i].Start(interactionObject, targetTag, fadeInTime, interrupt);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public bool StartInteractionWithClosestTarget(FullBodyBipedEffector effectorType, InteractionObject interactionObject, bool interrupt)
|
|
{
|
|
if (!IsValid(log: true))
|
|
{
|
|
return false;
|
|
}
|
|
if (interactionObject == null)
|
|
{
|
|
return false;
|
|
}
|
|
for (int i = 0; i < interactionEffectors.Length; i++)
|
|
{
|
|
if (interactionEffectors[i].effectorType == effectorType && GetClosestTargetIndex(effectorType, interactionObject) != -1)
|
|
{
|
|
return interactionEffectors[i].Start(interactionObject, interactionObject.GetTargets()[i], fadeInTime, interrupt);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private int GetClosestTargetIndex(FullBodyBipedEffector effectorType, InteractionObject obj)
|
|
{
|
|
int result = -1;
|
|
float num = float.PositiveInfinity;
|
|
Quaternion rotation = ik.solver.GetEffector(effectorType).bone.rotation;
|
|
for (int i = 0; i < obj.GetTargets().Length; i++)
|
|
{
|
|
float num2 = Quaternion.Angle(rotation, obj.GetTargets()[i].transform.rotation);
|
|
if (num2 < num)
|
|
{
|
|
num = num2;
|
|
result = i;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public bool StartInteraction(FullBodyBipedEffector effectorType, InteractionObject interactionObject, InteractionTarget target, bool interrupt)
|
|
{
|
|
if (!IsValid(log: true))
|
|
{
|
|
return false;
|
|
}
|
|
if (interactionObject == null)
|
|
{
|
|
return false;
|
|
}
|
|
for (int i = 0; i < interactionEffectors.Length; i++)
|
|
{
|
|
if (interactionEffectors[i].effectorType == effectorType)
|
|
{
|
|
return interactionEffectors[i].Start(interactionObject, target, fadeInTime, interrupt);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public bool PauseInteraction(FullBodyBipedEffector effectorType)
|
|
{
|
|
if (!IsValid(log: true))
|
|
{
|
|
return false;
|
|
}
|
|
for (int i = 0; i < interactionEffectors.Length; i++)
|
|
{
|
|
if (interactionEffectors[i].effectorType == effectorType)
|
|
{
|
|
return interactionEffectors[i].Pause();
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public bool ResumeInteraction(FullBodyBipedEffector effectorType)
|
|
{
|
|
if (!IsValid(log: true))
|
|
{
|
|
return false;
|
|
}
|
|
for (int i = 0; i < interactionEffectors.Length; i++)
|
|
{
|
|
if (interactionEffectors[i].effectorType == effectorType)
|
|
{
|
|
return interactionEffectors[i].Resume();
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public bool StopInteraction(FullBodyBipedEffector effectorType)
|
|
{
|
|
if (!IsValid(log: true))
|
|
{
|
|
return false;
|
|
}
|
|
for (int i = 0; i < interactionEffectors.Length; i++)
|
|
{
|
|
if (interactionEffectors[i].effectorType == effectorType)
|
|
{
|
|
return interactionEffectors[i].Stop();
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public void PauseAll()
|
|
{
|
|
if (IsValid(log: true))
|
|
{
|
|
for (int i = 0; i < interactionEffectors.Length; i++)
|
|
{
|
|
interactionEffectors[i].Pause();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void ResumeAll()
|
|
{
|
|
if (IsValid(log: true))
|
|
{
|
|
for (int i = 0; i < interactionEffectors.Length; i++)
|
|
{
|
|
interactionEffectors[i].Resume();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void StopAll()
|
|
{
|
|
for (int i = 0; i < interactionEffectors.Length; i++)
|
|
{
|
|
interactionEffectors[i].Stop();
|
|
}
|
|
}
|
|
|
|
public InteractionObject GetInteractionObject(FullBodyBipedEffector effectorType)
|
|
{
|
|
if (!IsValid(log: true))
|
|
{
|
|
return null;
|
|
}
|
|
for (int i = 0; i < interactionEffectors.Length; i++)
|
|
{
|
|
if (interactionEffectors[i].effectorType == effectorType)
|
|
{
|
|
return interactionEffectors[i].interactionObject;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public float GetProgress(FullBodyBipedEffector effectorType)
|
|
{
|
|
if (!IsValid(log: true))
|
|
{
|
|
return 0f;
|
|
}
|
|
for (int i = 0; i < interactionEffectors.Length; i++)
|
|
{
|
|
if (interactionEffectors[i].effectorType == effectorType)
|
|
{
|
|
return interactionEffectors[i].progress;
|
|
}
|
|
}
|
|
return 0f;
|
|
}
|
|
|
|
public float GetMinActiveProgress()
|
|
{
|
|
if (!IsValid(log: true))
|
|
{
|
|
return 0f;
|
|
}
|
|
float num = 1f;
|
|
for (int i = 0; i < interactionEffectors.Length; i++)
|
|
{
|
|
if (interactionEffectors[i].inInteraction)
|
|
{
|
|
float progress = interactionEffectors[i].progress;
|
|
if (progress > 0f && progress < num)
|
|
{
|
|
num = progress;
|
|
}
|
|
}
|
|
}
|
|
return num;
|
|
}
|
|
|
|
public bool TriggerInteraction(int index, bool interrupt)
|
|
{
|
|
if (!IsValid(log: true))
|
|
{
|
|
return false;
|
|
}
|
|
if (!TriggerIndexIsValid(index))
|
|
{
|
|
return false;
|
|
}
|
|
bool result = true;
|
|
InteractionTrigger.Range range = triggersInRange[index].ranges[bestRangeIndexes[index]];
|
|
for (int i = 0; i < range.interactions.Length; i++)
|
|
{
|
|
for (int j = 0; j < range.interactions[i].effectors.Length; j++)
|
|
{
|
|
if (!StartInteraction(range.interactions[i].effectors[j], range.interactions[i].interactionObject, interrupt))
|
|
{
|
|
result = false;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public bool TriggerInteraction(int index, bool interrupt, out InteractionObject interactionObject)
|
|
{
|
|
interactionObject = null;
|
|
if (!IsValid(log: true))
|
|
{
|
|
return false;
|
|
}
|
|
if (!TriggerIndexIsValid(index))
|
|
{
|
|
return false;
|
|
}
|
|
bool result = true;
|
|
InteractionTrigger.Range range = triggersInRange[index].ranges[bestRangeIndexes[index]];
|
|
for (int i = 0; i < range.interactions.Length; i++)
|
|
{
|
|
for (int j = 0; j < range.interactions[i].effectors.Length; j++)
|
|
{
|
|
interactionObject = range.interactions[i].interactionObject;
|
|
if (!StartInteraction(range.interactions[i].effectors[j], interactionObject, interrupt))
|
|
{
|
|
result = false;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public bool TriggerInteraction(int index, bool interrupt, out InteractionTarget interactionTarget)
|
|
{
|
|
interactionTarget = null;
|
|
if (!IsValid(log: true))
|
|
{
|
|
return false;
|
|
}
|
|
if (!TriggerIndexIsValid(index))
|
|
{
|
|
return false;
|
|
}
|
|
bool result = true;
|
|
InteractionTrigger.Range range = triggersInRange[index].ranges[bestRangeIndexes[index]];
|
|
for (int i = 0; i < range.interactions.Length; i++)
|
|
{
|
|
for (int j = 0; j < range.interactions[i].effectors.Length; j++)
|
|
{
|
|
InteractionObject interactionObject = range.interactions[i].interactionObject;
|
|
Transform target = interactionObject.GetTarget(range.interactions[i].effectors[j], base.tag);
|
|
if (target != null)
|
|
{
|
|
interactionTarget = target.GetComponent<InteractionTarget>();
|
|
}
|
|
if (!StartInteraction(range.interactions[i].effectors[j], interactionObject, interrupt))
|
|
{
|
|
result = false;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public InteractionTrigger.Range GetClosestInteractionRange()
|
|
{
|
|
if (!IsValid(log: true))
|
|
{
|
|
return null;
|
|
}
|
|
int closestTriggerIndex = GetClosestTriggerIndex();
|
|
if (closestTriggerIndex < 0 || closestTriggerIndex >= triggersInRange.Count)
|
|
{
|
|
return null;
|
|
}
|
|
return triggersInRange[closestTriggerIndex].ranges[bestRangeIndexes[closestTriggerIndex]];
|
|
}
|
|
|
|
public InteractionObject GetClosestInteractionObjectInRange()
|
|
{
|
|
InteractionTrigger.Range closestInteractionRange = GetClosestInteractionRange();
|
|
if (closestInteractionRange == null)
|
|
{
|
|
return null;
|
|
}
|
|
return closestInteractionRange.interactions[0].interactionObject;
|
|
}
|
|
|
|
public InteractionTarget GetClosestInteractionTargetInRange()
|
|
{
|
|
InteractionTrigger.Range closestInteractionRange = GetClosestInteractionRange();
|
|
if (closestInteractionRange == null)
|
|
{
|
|
return null;
|
|
}
|
|
return closestInteractionRange.interactions[0].interactionObject.GetTarget(closestInteractionRange.interactions[0].effectors[0], this);
|
|
}
|
|
|
|
public InteractionObject[] GetClosestInteractionObjectsInRange()
|
|
{
|
|
InteractionTrigger.Range closestInteractionRange = GetClosestInteractionRange();
|
|
if (closestInteractionRange == null)
|
|
{
|
|
return new InteractionObject[0];
|
|
}
|
|
InteractionObject[] array = new InteractionObject[closestInteractionRange.interactions.Length];
|
|
for (int i = 0; i < closestInteractionRange.interactions.Length; i++)
|
|
{
|
|
array[i] = closestInteractionRange.interactions[i].interactionObject;
|
|
}
|
|
return array;
|
|
}
|
|
|
|
public InteractionTarget[] GetClosestInteractionTargetsInRange()
|
|
{
|
|
InteractionTrigger.Range closestInteractionRange = GetClosestInteractionRange();
|
|
if (closestInteractionRange == null)
|
|
{
|
|
return new InteractionTarget[0];
|
|
}
|
|
List<InteractionTarget> list = new List<InteractionTarget>();
|
|
InteractionTrigger.Range.Interaction[] interactions = closestInteractionRange.interactions;
|
|
foreach (InteractionTrigger.Range.Interaction interaction in interactions)
|
|
{
|
|
FullBodyBipedEffector[] effectors = interaction.effectors;
|
|
foreach (FullBodyBipedEffector effectorType in effectors)
|
|
{
|
|
list.Add(interaction.interactionObject.GetTarget(effectorType, this));
|
|
}
|
|
}
|
|
return list.ToArray();
|
|
}
|
|
|
|
public bool TriggerEffectorsReady(int index)
|
|
{
|
|
if (!IsValid(log: true))
|
|
{
|
|
return false;
|
|
}
|
|
if (!TriggerIndexIsValid(index))
|
|
{
|
|
return false;
|
|
}
|
|
for (int i = 0; i < triggersInRange[index].ranges.Length; i++)
|
|
{
|
|
InteractionTrigger.Range range = triggersInRange[index].ranges[i];
|
|
for (int j = 0; j < range.interactions.Length; j++)
|
|
{
|
|
for (int k = 0; k < range.interactions[j].effectors.Length; k++)
|
|
{
|
|
if (IsInInteraction(range.interactions[j].effectors[k]))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
for (int l = 0; l < range.interactions.Length; l++)
|
|
{
|
|
for (int m = 0; m < range.interactions[l].effectors.Length; m++)
|
|
{
|
|
if (!IsPaused(range.interactions[l].effectors[m]))
|
|
{
|
|
continue;
|
|
}
|
|
for (int n = 0; n < range.interactions[l].effectors.Length; n++)
|
|
{
|
|
if (n != m && !IsPaused(range.interactions[l].effectors[n]))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public InteractionTrigger.Range GetTriggerRange(int index)
|
|
{
|
|
if (!IsValid(log: true))
|
|
{
|
|
return null;
|
|
}
|
|
if (index < 0 || index >= bestRangeIndexes.Count)
|
|
{
|
|
Warning.Log("Index out of range.", base.transform);
|
|
return null;
|
|
}
|
|
return triggersInRange[index].ranges[bestRangeIndexes[index]];
|
|
}
|
|
|
|
public int GetClosestTriggerIndex()
|
|
{
|
|
if (!IsValid(log: true))
|
|
{
|
|
return -1;
|
|
}
|
|
if (triggersInRange.Count == 0)
|
|
{
|
|
return -1;
|
|
}
|
|
if (triggersInRange.Count == 1)
|
|
{
|
|
return 0;
|
|
}
|
|
int result = -1;
|
|
float num = float.PositiveInfinity;
|
|
for (int i = 0; i < triggersInRange.Count; i++)
|
|
{
|
|
if (triggersInRange[i] != null)
|
|
{
|
|
float num2 = Vector3.SqrMagnitude(triggersInRange[i].transform.position - base.transform.position);
|
|
if (num2 < num)
|
|
{
|
|
result = i;
|
|
num = num2;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public void StoreDefaults()
|
|
{
|
|
for (int i = 0; i < interactionEffectors.Length; i++)
|
|
{
|
|
interactionEffectors[i].StoreDefaults();
|
|
}
|
|
}
|
|
|
|
public void Start()
|
|
{
|
|
if (fullBody == null)
|
|
{
|
|
fullBody = GetComponent<FullBodyBipedIK>();
|
|
}
|
|
if (fullBody == null)
|
|
{
|
|
Warning.Log("InteractionSystem can not find a FullBodyBipedIK component", base.transform);
|
|
return;
|
|
}
|
|
IKSolverFullBodyBiped solver = fullBody.solver;
|
|
solver.OnPreUpdate = (IKSolver.UpdateDelegate)Delegate.Combine(solver.OnPreUpdate, new IKSolver.UpdateDelegate(OnPreFBBIK));
|
|
IKSolverFullBodyBiped solver2 = fullBody.solver;
|
|
solver2.OnPostUpdate = (IKSolver.UpdateDelegate)Delegate.Combine(solver2.OnPostUpdate, new IKSolver.UpdateDelegate(OnPostFBBIK));
|
|
IKSolverFullBodyBiped solver3 = fullBody.solver;
|
|
solver3.OnFixTransforms = (IKSolver.UpdateDelegate)Delegate.Combine(solver3.OnFixTransforms, new IKSolver.UpdateDelegate(OnFixTransforms));
|
|
OnInteractionStart = (InteractionDelegate)Delegate.Combine(OnInteractionStart, new InteractionDelegate(LookAtInteraction));
|
|
OnInteractionPause = (InteractionDelegate)Delegate.Combine(OnInteractionPause, new InteractionDelegate(InteractionPause));
|
|
OnInteractionResume = (InteractionDelegate)Delegate.Combine(OnInteractionResume, new InteractionDelegate(InteractionResume));
|
|
OnInteractionStop = (InteractionDelegate)Delegate.Combine(OnInteractionStop, new InteractionDelegate(InteractionStop));
|
|
InteractionEffector[] array = interactionEffectors;
|
|
for (int i = 0; i < array.Length; i++)
|
|
{
|
|
array[i].Initiate(this);
|
|
}
|
|
triggersInRange = new List<InteractionTrigger>();
|
|
c = GetComponent<Collider>();
|
|
UpdateTriggerEventBroadcasting();
|
|
initiated = true;
|
|
}
|
|
|
|
private void InteractionPause(FullBodyBipedEffector effector, InteractionObject interactionObject)
|
|
{
|
|
lookAt.isPaused = true;
|
|
}
|
|
|
|
private void InteractionResume(FullBodyBipedEffector effector, InteractionObject interactionObject)
|
|
{
|
|
lookAt.isPaused = false;
|
|
}
|
|
|
|
private void InteractionStop(FullBodyBipedEffector effector, InteractionObject interactionObject)
|
|
{
|
|
lookAt.isPaused = false;
|
|
}
|
|
|
|
private void LookAtInteraction(FullBodyBipedEffector effector, InteractionObject interactionObject)
|
|
{
|
|
lookAt.Look(interactionObject.lookAtTarget, Time.time + interactionObject.length * 0.5f);
|
|
}
|
|
|
|
public void OnTriggerEnter(Collider c)
|
|
{
|
|
if (!(fullBody == null))
|
|
{
|
|
InteractionTrigger component = c.GetComponent<InteractionTrigger>();
|
|
if (!(component == null) && !inContact.Contains(component))
|
|
{
|
|
inContact.Add(component);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void OnTriggerExit(Collider c)
|
|
{
|
|
if (!(fullBody == null))
|
|
{
|
|
InteractionTrigger component = c.GetComponent<InteractionTrigger>();
|
|
if (!(component == null))
|
|
{
|
|
inContact.Remove(component);
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool ContactIsInRange(int index, out int bestRangeIndex)
|
|
{
|
|
bestRangeIndex = -1;
|
|
if (!IsValid(log: true))
|
|
{
|
|
return false;
|
|
}
|
|
if (index < 0 || index >= inContact.Count)
|
|
{
|
|
Warning.Log("Index out of range.", base.transform);
|
|
return false;
|
|
}
|
|
if (inContact[index] == null)
|
|
{
|
|
Warning.Log("The InteractionTrigger in the list 'inContact' has been destroyed", base.transform);
|
|
return false;
|
|
}
|
|
bestRangeIndex = inContact[index].GetBestRangeIndex(base.transform, FPSCamera, raycastHit);
|
|
if (bestRangeIndex == -1)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private void OnDrawGizmosSelected()
|
|
{
|
|
if (!Application.isPlaying)
|
|
{
|
|
if (fullBody == null)
|
|
{
|
|
fullBody = GetComponent<FullBodyBipedIK>();
|
|
}
|
|
if (characterCollider == null)
|
|
{
|
|
characterCollider = GetComponent<Collider>();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Update()
|
|
{
|
|
if (fullBody == null)
|
|
{
|
|
return;
|
|
}
|
|
UpdateTriggerEventBroadcasting();
|
|
Raycasting();
|
|
triggersInRange.Clear();
|
|
bestRangeIndexes.Clear();
|
|
for (int i = 0; i < inContact.Count; i++)
|
|
{
|
|
int bestRangeIndex = -1;
|
|
if (inContact[i] != null && inContact[i].gameObject.activeInHierarchy && ContactIsInRange(i, out bestRangeIndex))
|
|
{
|
|
triggersInRange.Add(inContact[i]);
|
|
bestRangeIndexes.Add(bestRangeIndex);
|
|
}
|
|
}
|
|
lookAt.Update();
|
|
}
|
|
|
|
private void Raycasting()
|
|
{
|
|
if ((int)camRaycastLayers != -1 && !(FPSCamera == null))
|
|
{
|
|
Physics.Raycast(FPSCamera.position, FPSCamera.forward, out raycastHit, camRaycastDistance, camRaycastLayers);
|
|
}
|
|
}
|
|
|
|
private void UpdateTriggerEventBroadcasting()
|
|
{
|
|
if (characterCollider == null)
|
|
{
|
|
characterCollider = c;
|
|
}
|
|
if (characterCollider != null && characterCollider != c)
|
|
{
|
|
if (characterCollider.GetComponent<TriggerEventBroadcaster>() == null)
|
|
{
|
|
characterCollider.gameObject.AddComponent<TriggerEventBroadcaster>().target = base.gameObject;
|
|
}
|
|
if (lastCollider != null && lastCollider != c && lastCollider != characterCollider)
|
|
{
|
|
TriggerEventBroadcaster component = lastCollider.GetComponent<TriggerEventBroadcaster>();
|
|
if (component != null)
|
|
{
|
|
UnityEngine.Object.Destroy(component);
|
|
}
|
|
}
|
|
}
|
|
lastCollider = characterCollider;
|
|
}
|
|
|
|
private void OnEnable()
|
|
{
|
|
lastTime = Time.time;
|
|
}
|
|
|
|
private void UpdateEffectors()
|
|
{
|
|
if (!(fullBody == null))
|
|
{
|
|
float deltaTime = Time.time - lastTime;
|
|
lastTime = Time.time;
|
|
for (int i = 0; i < interactionEffectors.Length; i++)
|
|
{
|
|
interactionEffectors[i].Update(base.transform, speed, deltaTime);
|
|
}
|
|
for (int j = 0; j < interactionEffectors.Length; j++)
|
|
{
|
|
interactionEffectors[j].ResetToDefaults(resetToDefaultsSpeed * speed, deltaTime);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnPreFBBIK()
|
|
{
|
|
if (!(fullBody == null))
|
|
{
|
|
lookAt.SolveSpine();
|
|
UpdateEffectors();
|
|
}
|
|
}
|
|
|
|
private void OnPostFBBIK()
|
|
{
|
|
if (!(fullBody == null))
|
|
{
|
|
for (int i = 0; i < interactionEffectors.Length; i++)
|
|
{
|
|
interactionEffectors[i].OnPostFBBIK();
|
|
}
|
|
lookAt.SolveHead();
|
|
}
|
|
}
|
|
|
|
private void OnFixTransforms()
|
|
{
|
|
lookAt.OnFixTransforms();
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
if (!(fullBody == null))
|
|
{
|
|
IKSolverFullBodyBiped solver = fullBody.solver;
|
|
solver.OnPreUpdate = (IKSolver.UpdateDelegate)Delegate.Remove(solver.OnPreUpdate, new IKSolver.UpdateDelegate(OnPreFBBIK));
|
|
IKSolverFullBodyBiped solver2 = fullBody.solver;
|
|
solver2.OnPostUpdate = (IKSolver.UpdateDelegate)Delegate.Remove(solver2.OnPostUpdate, new IKSolver.UpdateDelegate(OnPostFBBIK));
|
|
IKSolverFullBodyBiped solver3 = fullBody.solver;
|
|
solver3.OnFixTransforms = (IKSolver.UpdateDelegate)Delegate.Remove(solver3.OnFixTransforms, new IKSolver.UpdateDelegate(OnFixTransforms));
|
|
OnInteractionStart = (InteractionDelegate)Delegate.Remove(OnInteractionStart, new InteractionDelegate(LookAtInteraction));
|
|
OnInteractionPause = (InteractionDelegate)Delegate.Remove(OnInteractionPause, new InteractionDelegate(InteractionPause));
|
|
OnInteractionResume = (InteractionDelegate)Delegate.Remove(OnInteractionResume, new InteractionDelegate(InteractionResume));
|
|
OnInteractionStop = (InteractionDelegate)Delegate.Remove(OnInteractionStop, new InteractionDelegate(InteractionStop));
|
|
}
|
|
}
|
|
|
|
private bool IsValid(bool log)
|
|
{
|
|
if (fullBody == null)
|
|
{
|
|
if (log)
|
|
{
|
|
Warning.Log("FBBIK is null. Will not update the InteractionSystem", base.transform);
|
|
}
|
|
return false;
|
|
}
|
|
if (!initiated)
|
|
{
|
|
if (log)
|
|
{
|
|
Warning.Log("The InteractionSystem has not been initiated yet.", base.transform);
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private bool TriggerIndexIsValid(int index)
|
|
{
|
|
if (index < 0 || index >= triggersInRange.Count)
|
|
{
|
|
Warning.Log("Index out of range.", base.transform);
|
|
return false;
|
|
}
|
|
if (triggersInRange[index] == null)
|
|
{
|
|
Warning.Log("The InteractionTrigger in the list 'inContact' has been destroyed", base.transform);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|