Update
This commit is contained in:
736
Assets/Scripts/Player/HeadTrack/Scripts/vHeadTrack.cs
Normal file
736
Assets/Scripts/Player/HeadTrack/Scripts/vHeadTrack.cs
Normal file
@@ -0,0 +1,736 @@
|
||||
using Invector.vEventSystems;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
namespace Invector.vCharacterController
|
||||
{
|
||||
[vClassHeader("HEAD TRACK", iconName = "headTrackIcon")]
|
||||
public class vHeadTrack : vMonoBehaviour
|
||||
{
|
||||
#region variables
|
||||
|
||||
[vEditorToolbar("Settings")]
|
||||
|
||||
[vHelpBox("If your character is not looking up/down, try changing the axis", vHelpBoxAttribute.MessageType.Info)]
|
||||
public Vector3 upDownAxis = Vector3.right;
|
||||
|
||||
[Header("Head & Body Weight")]
|
||||
public float strafeHeadWeight = 0.6f;
|
||||
public float strafeBodyWeight = 0.6f;
|
||||
public float aimingHeadWeight = 0.8f;
|
||||
public float aimingBodyWeight = 0.8f;
|
||||
public float freeHeadWeight = 0.6f;
|
||||
public float freeBodyWeight = 0.6f;
|
||||
|
||||
[SerializeField] protected float smooth = 10f;
|
||||
|
||||
[Header("Default Offsets ")]
|
||||
[SerializeField] protected Vector2 defaultOffsetSpine;
|
||||
[SerializeField] protected Vector2 defaultOffsetHead;
|
||||
|
||||
[vReadOnly(true)]
|
||||
public Vector2 offsetSpine;
|
||||
[vReadOnly(true)]
|
||||
public Vector2 offsetHead;
|
||||
|
||||
[Header("Tracking")]
|
||||
[Tooltip("Follow the Camera Forward")]
|
||||
public bool followCamera = true;
|
||||
public bool _freezeLookPoint = false;
|
||||
[vHideInInspector("followCamera")]
|
||||
[Tooltip("Force to follow camera")]
|
||||
[SerializeField] protected bool _alwaysFollowCamera = false;
|
||||
public virtual bool alwaysFollowCamera { get { return _alwaysFollowCamera; } set { _alwaysFollowCamera = value; } }
|
||||
[Tooltip("Ignore the Limits and continue to follow the camera")]
|
||||
public bool cancelTrackOutOfAngle = true;
|
||||
[Tooltip("Considerer the head animation forward while tracking, try it to see different results")]
|
||||
public bool considerHeadAnimationForward;
|
||||
|
||||
[Header("Limits")]
|
||||
[vMinMax(minLimit = -180f, maxLimit = 180f)] public Vector2 horizontalAngleLimit = new Vector2(-100, 100);
|
||||
[vMinMax(minLimit = -90f, maxLimit = 90f)] public Vector2 verticalAngleLimit = new Vector2(-80, 80);
|
||||
|
||||
[vHelpBox("Animations with vAnimatorTag Behavior will ignore the HeadTrack while is being played")]
|
||||
[Header("Ignore AnimatorTags")]
|
||||
public List<string> animatorIgnoreTags = new List<string>() { "Attack", "LockMovement", "CustomAction", "IsEquipping", "IgnoreHeadtrack" };
|
||||
|
||||
[vEditorToolbar("Bones")]
|
||||
[vHelpBox("Auto Find Bones using Humanoid")]
|
||||
public bool autoFindBones = true;
|
||||
public Transform head;
|
||||
public List<Transform> spine = new List<Transform>();
|
||||
|
||||
[vEditorToolbar("Detection")]
|
||||
public float updateTargetInteraction = 1;
|
||||
public float distanceToDetect = 10f;
|
||||
public LayerMask obstacleLayer = 1 << 0;
|
||||
[vHelpBox("Gameobjects Tags to detect")]
|
||||
public List<string> tagsToDetect = new List<string>() { "LookAt" };
|
||||
|
||||
[vEditorToolbar("HeadTrack Angles")]
|
||||
|
||||
[vHelpBox("Angle between character forward and camera forward")]
|
||||
[SerializeField, vReadOnly(false)]
|
||||
protected Vector2 _desiredlookAngle;
|
||||
[vHelpBox("Angle between head forward and character forward")]
|
||||
[SerializeField, vReadOnly(false)]
|
||||
protected Vector2 _currentLookAngle;
|
||||
[vHelpBox("Angle between head forward and camera forward")]
|
||||
[SerializeField, vReadOnly(false)]
|
||||
protected Vector2 _relativeLookAngle;
|
||||
|
||||
[vSeparator("Optinal Animator paramenters")]
|
||||
[vHelpBox("This is an optional to use and update paramenters in the animator using the look angles of the headtrack")]
|
||||
|
||||
|
||||
|
||||
[Tooltip("When enable this. The headtrack will update the angles relative to the character forward and camera forward")]
|
||||
public bool useDesiredLookAngle;
|
||||
[vHideInInspector("useDesiredLookAngle")]
|
||||
public string desiredLookAngleH = "HorizontalLookAngle";
|
||||
[vHideInInspector("useDesiredLookAngle")]
|
||||
public string desiredLookAngleV = "VerticalLookAngle";
|
||||
|
||||
[Tooltip("When enable this. The headtrack will update the angles relative to the Head forward and Character forward")]
|
||||
public bool useCurrentAngle;
|
||||
[vHideInInspector("useCurrentAngle")]
|
||||
public string currentAngleH = "CurrentHorizontalLookAngle";
|
||||
[vHideInInspector("useCurrentAngle")]
|
||||
public string currentAngleV = "CurrentVerticalLookAngle";
|
||||
|
||||
[Tooltip("When enable this. The headtrack will update the angles relative to the character head forward and camera forward")]
|
||||
public bool useRelativeLookAngle;
|
||||
[vHideInInspector("useRelativeLookAngle")]
|
||||
public string relativeLookAngleH ="HorizontalLookAngleRelative";
|
||||
[vHideInInspector("useRelativeLookAngle")]
|
||||
public string relativeLookAngleV = "VerticalLookAngleRelative";
|
||||
|
||||
|
||||
|
||||
internal UnityEvent onInitUpdate = new UnityEvent();
|
||||
internal UnityEvent onFinishUpdate = new UnityEvent();
|
||||
internal List<vLookTarget> targetsInArea = new List<vLookTarget>();
|
||||
|
||||
public virtual Camera cameraMain { get; set; }
|
||||
public virtual vLookTarget currentLookTarget { get; set; }
|
||||
public virtual vLookTarget lastLookTarget { get; set; }
|
||||
public virtual Quaternion currentLookRotation { get; set; }
|
||||
public virtual bool ignoreSmooth { get; set; }
|
||||
|
||||
protected virtual float yRotation { get; set; }
|
||||
protected virtual float xRotation { get; set; }
|
||||
protected virtual float _currentHeadWeight { get; set; }
|
||||
protected virtual float _currentBodyWeight { get; set; }
|
||||
protected virtual Animator animator { get; set; }
|
||||
protected virtual vIAnimatorStateInfoController animatorStateInfo { get; set; }
|
||||
protected virtual float headHeight { get; set; }
|
||||
protected virtual Transform simpleTarget { get; set; }
|
||||
protected virtual Vector3 temporaryLookPoint { get; set; }
|
||||
protected virtual float temporaryLookTime { get; set; }
|
||||
protected virtual vHeadTrackSensor sensor { get; set; }
|
||||
protected virtual float interaction { get; set; }
|
||||
protected virtual vICharacter vChar { get; set; }
|
||||
protected virtual Transform forwardReference { get; set; }
|
||||
|
||||
protected int currentLookAngleH_Hash = -1;
|
||||
protected int currentLookAngleV_Hash = -1;
|
||||
protected int desiredLookAngleH_Hash = -1;
|
||||
protected int desiredLookAngleV_Hash = -1;
|
||||
protected int relativeLookAngleH_Hash = -1;
|
||||
protected int relativeLookAngleV_Hash = -1;
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
public virtual float Smooth
|
||||
{
|
||||
get
|
||||
{
|
||||
return ignoreSmooth ? 1f : smooth * Time.deltaTime;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual Vector3 _currentLocalLookPosition { get; set; }
|
||||
protected virtual Vector3 _lastLocalLookPosition { get; set; }
|
||||
|
||||
public virtual float currentVerticalLookAngle { get => _currentLookAngle.x; protected set => _currentLookAngle.x = value; }
|
||||
public virtual float currentHorizontalLookAngle { get => _currentLookAngle.y; protected set => _currentLookAngle.y = value; }
|
||||
|
||||
|
||||
public virtual float desiredVerticalLookAngle{ get => _desiredlookAngle.x; protected set => _desiredlookAngle.x = value; }
|
||||
public virtual float desiredHorizontalLookAngle { get => _desiredlookAngle.y; protected set => _desiredlookAngle.y = value; }
|
||||
|
||||
public virtual float relativeVerticalLookAngle{ get => _relativeLookAngle.x; protected set => _relativeLookAngle.x = value; }
|
||||
public virtual float relativeHorizontalLookAngle { get => _relativeLookAngle.y; protected set => _relativeLookAngle.y = value; }
|
||||
|
||||
public virtual bool freezeLookPoint { get => _freezeLookPoint; set => _freezeLookPoint = value; }
|
||||
|
||||
public virtual Vector3 currentLookPosition
|
||||
{
|
||||
get => freezeLookPoint ? transform.TransformPoint(_lastLocalLookPosition) : transform.TransformPoint(_currentLocalLookPosition);
|
||||
protected set
|
||||
{
|
||||
_currentLocalLookPosition = transform.InverseTransformPoint(value);
|
||||
if (!freezeLookPoint)
|
||||
{
|
||||
_lastLocalLookPosition = _currentLocalLookPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
if (!sensor)
|
||||
{
|
||||
var sensorObj = new GameObject("HeadTrackSensor");
|
||||
sensor = sensorObj.AddComponent<vHeadTrackSensor>();
|
||||
}
|
||||
|
||||
// updates the headtrack using the late update of the tpinput so we don't need to create another one
|
||||
var tpInput = GetComponent<vThirdPersonInput>();
|
||||
if (tpInput)
|
||||
{
|
||||
tpInput.onLateUpdate -= UpdateHeadTrack;
|
||||
tpInput.onLateUpdate += UpdateHeadTrack;
|
||||
}
|
||||
|
||||
vChar = GetComponent<vICharacter>();
|
||||
sensor.headTrack = this;
|
||||
cameraMain = Camera.main;
|
||||
var layer = LayerMask.NameToLayer("HeadTrack");
|
||||
sensor.transform.parent = transform;
|
||||
sensor.gameObject.layer = layer;
|
||||
sensor.gameObject.tag = transform.tag;
|
||||
animatorStateInfo = GetComponent<vIAnimatorStateInfoController>();
|
||||
|
||||
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
public virtual void Init()
|
||||
{
|
||||
currentLookPosition = GetLookPoint();
|
||||
_lastLocalLookPosition = _currentLocalLookPosition;
|
||||
if (animator == null)
|
||||
{
|
||||
animator = GetComponentInChildren<Animator>();
|
||||
}
|
||||
if (animator.GetValidParameter(currentAngleH, out AnimatorControllerParameter p)) currentLookAngleH_Hash = p.nameHash;
|
||||
if (animator.GetValidParameter(currentAngleV, out p)) currentLookAngleV_Hash = p.nameHash;
|
||||
|
||||
if (animator.GetValidParameter(desiredLookAngleH, out p)) desiredLookAngleH_Hash = p.nameHash;
|
||||
if (animator.GetValidParameter(desiredLookAngleV, out p)) desiredLookAngleV_Hash = p.nameHash;
|
||||
|
||||
if (animator.GetValidParameter(relativeLookAngleH, out p)) relativeLookAngleH_Hash = p.nameHash;
|
||||
if (animator.GetValidParameter(relativeLookAngleV, out p)) relativeLookAngleV_Hash = p.nameHash;
|
||||
if (autoFindBones)
|
||||
{
|
||||
spine.Clear();
|
||||
head = animator.GetBoneTransform(HumanBodyBones.Head);
|
||||
if (head)
|
||||
{
|
||||
if (!forwardReference)
|
||||
{
|
||||
forwardReference = new GameObject("FWRF").transform;
|
||||
}
|
||||
|
||||
forwardReference.SetParent(head);
|
||||
forwardReference.transform.localPosition = Vector3.zero;
|
||||
forwardReference.transform.rotation = transform.rotation;
|
||||
var hips = animator.GetBoneTransform(HumanBodyBones.Hips);
|
||||
if (hips)
|
||||
{
|
||||
var target = head;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (target.parent && target.parent.gameObject != hips.gameObject)
|
||||
{
|
||||
spine.Add(target.parent);
|
||||
target = target.parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (head)
|
||||
{
|
||||
headHeight = Vector3.Distance(transform.position, head.position);
|
||||
sensor.transform.position = head.transform.position;
|
||||
}
|
||||
else
|
||||
{
|
||||
headHeight = 1f;
|
||||
sensor.transform.position = transform.position;
|
||||
}
|
||||
if (spine.Count == 0)
|
||||
{
|
||||
Debug.Log("Headtrack Spines missing");
|
||||
}
|
||||
|
||||
spine.Reverse();
|
||||
}
|
||||
|
||||
protected virtual Vector3 headPoint { get { return transform.position + (transform.up * headHeight); } }
|
||||
|
||||
public virtual void UpdateHeadTrack()
|
||||
{
|
||||
if (animator == null || !animator.enabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (vChar != null && vChar.currentHealth > 0f && animator != null && !vChar.ragdolled)
|
||||
{
|
||||
onInitUpdate.Invoke();
|
||||
if (!freezeLookPoint)
|
||||
{
|
||||
currentLookPosition = GetLookPoint();
|
||||
}
|
||||
|
||||
SetLookAtPosition(currentLookPosition, _currentHeadWeight, _currentBodyWeight);
|
||||
UpdateAngles();
|
||||
onFinishUpdate.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void SetLookAtPosition(Vector3 point, float headWeight, float spineWeight)
|
||||
{
|
||||
var lookRotation = Quaternion.LookRotation(point - headPoint);
|
||||
currentLookRotation = lookRotation;
|
||||
var euler = lookRotation.eulerAngles - transform.rotation.eulerAngles;
|
||||
var y = NormalizeAngle(euler.y);
|
||||
var x = NormalizeAngle(euler.x);
|
||||
var eulerB = considerHeadAnimationForward ? forwardReference.eulerAngles - transform.eulerAngles : Vector3.zero;
|
||||
currentVerticalLookAngle = Mathf.Clamp(Mathf.Lerp(currentVerticalLookAngle, ((x) - eulerB.NormalizeAngle().x) + Quaternion.Euler(offsetSpine + defaultOffsetSpine).eulerAngles.NormalizeAngle().x, Smooth), verticalAngleLimit.x, verticalAngleLimit.y);
|
||||
currentHorizontalLookAngle = Mathf.Clamp(Mathf.Lerp(currentHorizontalLookAngle, ((y) - eulerB.NormalizeAngle().y) + Quaternion.Euler(offsetSpine + defaultOffsetSpine).eulerAngles.NormalizeAngle().y, Smooth), horizontalAngleLimit.x, horizontalAngleLimit.y);
|
||||
|
||||
var xSpine = NormalizeAngle(currentVerticalLookAngle);
|
||||
var ySpine = NormalizeAngle(currentHorizontalLookAngle);
|
||||
|
||||
foreach (Transform segment in spine)
|
||||
{
|
||||
var rotY = Quaternion.AngleAxis((ySpine * spineWeight) / spine.Count, segment.InverseTransformDirection(transform.up));
|
||||
segment.rotation *= rotY;
|
||||
var rotX = Quaternion.AngleAxis((xSpine * spineWeight) / spine.Count, segment.InverseTransformDirection(transform.TransformDirection(upDownAxis)));
|
||||
segment.rotation *= rotX;
|
||||
}
|
||||
if (head)
|
||||
{
|
||||
var xHead = NormalizeAngle(currentVerticalLookAngle - (xSpine * spineWeight) + Quaternion.Euler(offsetHead + defaultOffsetHead).eulerAngles.NormalizeAngle().x);
|
||||
var yHead = NormalizeAngle(currentHorizontalLookAngle - (ySpine * spineWeight) + Quaternion.Euler(offsetHead + defaultOffsetHead).eulerAngles.NormalizeAngle().y);
|
||||
var _rotY = Quaternion.AngleAxis(yHead * headWeight, head.InverseTransformDirection(transform.up));
|
||||
head.rotation *= _rotY;
|
||||
var _rotX = Quaternion.AngleAxis(xHead * headWeight, head.InverseTransformDirection(transform.TransformDirection(upDownAxis)));
|
||||
head.rotation *= _rotX;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void UpdateAngles()
|
||||
{
|
||||
if (useCurrentAngle)
|
||||
{
|
||||
if (currentLookAngleH_Hash != -1) animator.SetFloat(currentLookAngleH_Hash, currentHorizontalLookAngle);
|
||||
if (currentLookAngleV_Hash != -1) animator.SetFloat(currentLookAngleV_Hash, currentVerticalLookAngle);
|
||||
}
|
||||
|
||||
if (useDesiredLookAngle)
|
||||
{
|
||||
if (desiredLookAngleH_Hash != -1) animator.SetFloat(desiredLookAngleH_Hash, desiredHorizontalLookAngle);
|
||||
|
||||
if (desiredLookAngleV_Hash != -1) animator.SetFloat(desiredLookAngleV_Hash, desiredVerticalLookAngle);
|
||||
}
|
||||
|
||||
if(useRelativeLookAngle)
|
||||
{
|
||||
if (relativeLookAngleH_Hash != -1) animator.SetFloat(relativeLookAngleH_Hash, relativeHorizontalLookAngle);
|
||||
if (relativeLookAngleV_Hash != -1) animator.SetFloat(relativeLookAngleV_Hash, relativeVerticalLookAngle);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotate the spine using angles
|
||||
/// </summary>
|
||||
/// <param name="angleX">Vertical angle</param>
|
||||
/// <param name="angleY">Horizontal angle</param>
|
||||
public virtual void RotateSpine(float angleX, float angleY)
|
||||
{
|
||||
var xSpine = NormalizeAngle(angleX);
|
||||
var ySpine = NormalizeAngle(angleY);
|
||||
|
||||
foreach (Transform segment in spine)
|
||||
{
|
||||
var rotY = Quaternion.AngleAxis((ySpine) / spine.Count, segment.InverseTransformDirection(transform.up));
|
||||
segment.rotation *= rotY;
|
||||
var rotX = Quaternion.AngleAxis((xSpine) / spine.Count, segment.InverseTransformDirection(transform.TransformDirection(upDownAxis)));
|
||||
segment.rotation *= rotX;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual Vector3 desiredLookDirection { get; protected set; }
|
||||
|
||||
public virtual Vector3 LookDirection { get; protected set; }
|
||||
|
||||
protected virtual bool lookConditions
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!cameraMain)
|
||||
{
|
||||
cameraMain = Camera.main;
|
||||
}
|
||||
return head != null && (followCamera && cameraMain != null) || (!followCamera && (currentLookTarget || simpleTarget)) || temporaryLookTime > 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual Vector3 GetLookPoint()
|
||||
{
|
||||
if (animator == null)
|
||||
{
|
||||
return Vector3.zero;
|
||||
}
|
||||
|
||||
var distanceToLook = 100;
|
||||
if (lookConditions && !IgnoreHeadTrack())
|
||||
{
|
||||
desiredLookDirection = transform.forward;
|
||||
if (temporaryLookTime <= 0)
|
||||
{
|
||||
var lookPosition = headPoint + (transform.forward * distanceToLook);
|
||||
if (followCamera)
|
||||
{
|
||||
lookPosition = (cameraMain.transform.position + (cameraMain.transform.forward * distanceToLook));
|
||||
}
|
||||
|
||||
desiredLookDirection = lookPosition - headPoint;
|
||||
|
||||
if ((followCamera && !alwaysFollowCamera) || !followCamera)
|
||||
{
|
||||
|
||||
if (simpleTarget != null)
|
||||
{
|
||||
desiredLookDirection = simpleTarget.position - headPoint;
|
||||
if (currentLookTarget && currentLookTarget == lastLookTarget)
|
||||
{
|
||||
currentLookTarget.ExitLook(this);
|
||||
lastLookTarget = null;
|
||||
}
|
||||
}
|
||||
else if (currentLookTarget != null && (currentLookTarget.ignoreHeadTrackAngle || TargetIsOnRange(currentLookTarget.lookPoint - headPoint)) && currentLookTarget.IsVisible(headPoint, obstacleLayer))
|
||||
{
|
||||
desiredLookDirection = currentLookTarget.lookPoint - headPoint;
|
||||
if (currentLookTarget != lastLookTarget)
|
||||
{
|
||||
currentLookTarget.EnterLook(this);
|
||||
lastLookTarget = currentLookTarget;
|
||||
}
|
||||
}
|
||||
else if (currentLookTarget && currentLookTarget == lastLookTarget)
|
||||
{
|
||||
currentLookTarget.ExitLook(this);
|
||||
lastLookTarget = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
desiredLookDirection = temporaryLookPoint - headPoint;
|
||||
temporaryLookTime -= Time.deltaTime;
|
||||
if (currentLookTarget && currentLookTarget == lastLookTarget)
|
||||
{
|
||||
currentLookTarget.ExitLook(this);
|
||||
lastLookTarget = null;
|
||||
}
|
||||
}
|
||||
|
||||
var angle = GetTargetAngle(desiredLookDirection);
|
||||
if (cancelTrackOutOfAngle && (lastLookTarget == null || !lastLookTarget.ignoreHeadTrackAngle))
|
||||
{
|
||||
if (TargetIsOnRange(desiredLookDirection))
|
||||
{
|
||||
if (animator.GetBool("IsStrafing") && !IsAnimatorTag("Upperbody Pose"))
|
||||
{
|
||||
SmoothValues(strafeHeadWeight, strafeBodyWeight, angle.x, angle.y);
|
||||
}
|
||||
else if (animator.GetBool("IsStrafing") && IsAnimatorTag("Upperbody Pose"))
|
||||
{
|
||||
SmoothValues(aimingHeadWeight, aimingBodyWeight, angle.x, angle.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
SmoothValues(freeHeadWeight, freeBodyWeight, angle.x, angle.y);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SmoothValues();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (animator.GetBool("IsStrafing") && !IsAnimatorTag("Upperbody Pose"))
|
||||
{
|
||||
SmoothValues(strafeHeadWeight, strafeBodyWeight, angle.x, angle.y);
|
||||
}
|
||||
else if (animator.GetBool("IsStrafing") && IsAnimatorTag("Upperbody Pose"))
|
||||
{
|
||||
SmoothValues(aimingHeadWeight, aimingBodyWeight, angle.x, angle.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
SmoothValues(freeHeadWeight, freeBodyWeight, angle.x, angle.y);
|
||||
}
|
||||
}
|
||||
if (targetsInArea.Count > 1)
|
||||
{
|
||||
SortTargets();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SmoothValues();
|
||||
if (targetsInArea.Count > 1)
|
||||
{
|
||||
SortTargets();
|
||||
}
|
||||
}
|
||||
|
||||
var rotA = Quaternion.AngleAxis(yRotation, transform.up);
|
||||
var rotB = Quaternion.AngleAxis(xRotation, transform.right);
|
||||
var finalRotation = (rotA * rotB);
|
||||
var lookDirection = finalRotation * transform.forward;
|
||||
LookDirection = lookDirection;
|
||||
_desiredlookAngle = GetTargetAngle(cameraMain.transform.forward);
|
||||
_relativeLookAngle = -(GetTargetAngle(lookDirection) - _desiredlookAngle);
|
||||
|
||||
|
||||
return headPoint + (lookDirection * distanceToLook);
|
||||
}
|
||||
|
||||
protected virtual Vector2 GetTargetAngle(Vector3 direction)
|
||||
{
|
||||
if (direction.magnitude == 0) return Vector2.zero;
|
||||
var lookRotation = Quaternion.LookRotation(direction, Vector3.up);
|
||||
var angleResult = lookRotation.eulerAngles - transform.eulerAngles;
|
||||
|
||||
return new Vector2(angleResult.NormalizeAngle().x, angleResult.NormalizeAngle().y);
|
||||
}
|
||||
|
||||
protected virtual bool TargetIsOnRange(Vector3 direction)
|
||||
{
|
||||
var angle = GetTargetAngle(direction);
|
||||
return (angle.x >= verticalAngleLimit.x && angle.x <= verticalAngleLimit.y && angle.y >= horizontalAngleLimit.x && angle.y <= horizontalAngleLimit.y);
|
||||
}
|
||||
|
||||
public virtual void SetAlwaysFollowCamera(bool value)
|
||||
{
|
||||
alwaysFollowCamera = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set vLookTarget
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
public virtual void SetLookTarget(vLookTarget target, bool priority = false)
|
||||
{
|
||||
if (!targetsInArea.Contains(target))
|
||||
{
|
||||
targetsInArea.Add(target);
|
||||
}
|
||||
|
||||
if (priority)
|
||||
{
|
||||
currentLookTarget = target;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set Simple target
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
public virtual void SetLookTarget(Transform target)
|
||||
{
|
||||
simpleTarget = target;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a temporary look point to headtrack
|
||||
/// </summary>
|
||||
/// <param name="point">look point</param>
|
||||
/// <param name="time">time to stay looking</param>
|
||||
public virtual void SetTemporaryLookPoint(Vector3 point, float time = 1f)
|
||||
{
|
||||
temporaryLookPoint = point;
|
||||
temporaryLookTime = time;
|
||||
}
|
||||
|
||||
public virtual void RemoveLookTarget(vLookTarget target)
|
||||
{
|
||||
if (targetsInArea.Contains(target))
|
||||
{
|
||||
targetsInArea.Remove(target);
|
||||
}
|
||||
|
||||
if (currentLookTarget == target)
|
||||
{
|
||||
currentLookTarget = null;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void RemoveLookTarget(Transform target)
|
||||
{
|
||||
if (simpleTarget == target)
|
||||
{
|
||||
simpleTarget = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make angle to work with -180 and 180
|
||||
/// </summary>
|
||||
/// <param name="angle"></param>
|
||||
/// <returns></returns>
|
||||
protected virtual float NormalizeAngle(float angle)
|
||||
{
|
||||
if (angle > 180)
|
||||
{
|
||||
angle -= 360;
|
||||
}
|
||||
else if (angle < -180)
|
||||
{
|
||||
angle += 360;
|
||||
}
|
||||
|
||||
return angle;
|
||||
}
|
||||
|
||||
protected virtual void ResetValues()
|
||||
{
|
||||
_currentHeadWeight = 0;
|
||||
_currentBodyWeight = 0;
|
||||
yRotation = 0;
|
||||
xRotation = 0;
|
||||
}
|
||||
|
||||
protected virtual void SmoothValues(float _headWeight = 0, float _bodyWeight = 0, float _x = 0, float _y = 0)
|
||||
{
|
||||
_currentHeadWeight = Mathf.Lerp(_currentHeadWeight, _headWeight, Smooth);
|
||||
_currentBodyWeight = Mathf.Lerp(_currentBodyWeight, _bodyWeight, Smooth);
|
||||
yRotation = Mathf.Lerp(yRotation, _y, Smooth);
|
||||
xRotation = Mathf.Lerp(xRotation, _x, Smooth);
|
||||
yRotation = Mathf.Clamp(yRotation, horizontalAngleLimit.x, horizontalAngleLimit.y);
|
||||
xRotation = Mathf.Clamp(xRotation, verticalAngleLimit.x, verticalAngleLimit.y);
|
||||
}
|
||||
|
||||
protected virtual void SortTargets()
|
||||
{
|
||||
interaction += Time.deltaTime;
|
||||
if (interaction > updateTargetInteraction)
|
||||
{
|
||||
interaction -= updateTargetInteraction;
|
||||
if (targetsInArea == null || targetsInArea.Count < 2)
|
||||
{
|
||||
if (targetsInArea != null && targetsInArea.Count > 0)
|
||||
{
|
||||
currentLookTarget = targetsInArea[0];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = targetsInArea.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (targetsInArea[i] == null)
|
||||
{
|
||||
targetsInArea.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
targetsInArea.Sort(delegate (vLookTarget c1, vLookTarget c2)
|
||||
{
|
||||
return Vector3.Distance(this.transform.position, c1 != null ? c1.transform.position : Vector3.one * Mathf.Infinity).CompareTo
|
||||
((Vector3.Distance(this.transform.position, c2 != null ? c2.transform.position : Vector3.one * Mathf.Infinity)));
|
||||
});
|
||||
if (targetsInArea.Count > 0)
|
||||
{
|
||||
currentLookTarget = targetsInArea[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void OnDetect(Collider other)
|
||||
{
|
||||
if (tagsToDetect.Contains(other.gameObject.tag) && other.GetComponent<vLookTarget>() != null)
|
||||
{
|
||||
currentLookTarget = other.GetComponent<vLookTarget>();
|
||||
var headTrack = other.GetComponentInParent<vHeadTrack>();
|
||||
if (!targetsInArea.Contains(currentLookTarget) && (headTrack == null || headTrack != this))
|
||||
{
|
||||
targetsInArea.Add(currentLookTarget);
|
||||
SortTargets();
|
||||
currentLookTarget = targetsInArea[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void OnLost(Collider other)
|
||||
{
|
||||
if (tagsToDetect.Contains(other.gameObject.tag) && other.GetComponentInParent<vLookTarget>() != null)
|
||||
{
|
||||
var _currentLookTarget = other.GetComponentInParent<vLookTarget>();
|
||||
|
||||
if (targetsInArea.Contains(_currentLookTarget))
|
||||
{
|
||||
targetsInArea.Remove(_currentLookTarget);
|
||||
|
||||
|
||||
if (_currentLookTarget == lastLookTarget)
|
||||
{
|
||||
_currentLookTarget.ExitLook(this);
|
||||
}
|
||||
}
|
||||
SortTargets();
|
||||
if (targetsInArea.Count > 0)
|
||||
{
|
||||
currentLookTarget = targetsInArea[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
currentLookTarget = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool IgnoreHeadTrack()
|
||||
{
|
||||
if (animatorIgnoreTags.Exists(tag => IsAnimatorTag(tag)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual bool IsAnimatorTag(string tag)
|
||||
{
|
||||
if (animator == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (animatorStateInfo.isValid())
|
||||
{
|
||||
if (animatorStateInfo.animatorStateInfos.HasTag(tag))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Assets/Scripts/Player/HeadTrack/Scripts/vHeadTrack.cs.meta
Normal file
12
Assets/Scripts/Player/HeadTrack/Scripts/vHeadTrack.cs.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61a5d2516d5dbbc40b1cfb5cbf17758a
|
||||
timeCreated: 1469474947
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
42
Assets/Scripts/Player/HeadTrack/Scripts/vHeadTrackSensor.cs
Normal file
42
Assets/Scripts/Player/HeadTrack/Scripts/vHeadTrackSensor.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using UnityEngine;
|
||||
namespace Invector.vCharacterController
|
||||
{
|
||||
[RequireComponent(typeof(SphereCollider))]
|
||||
[RequireComponent(typeof(Rigidbody))]
|
||||
public class vHeadTrackSensor : MonoBehaviour
|
||||
{
|
||||
[HideInInspector]
|
||||
public vHeadTrack headTrack;
|
||||
public SphereCollider sphere;
|
||||
|
||||
void OnDrawGizmos()
|
||||
{
|
||||
if (Application.isPlaying && sphere && headTrack)
|
||||
{
|
||||
sphere.radius = headTrack.distanceToDetect;
|
||||
}
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
var _rigidB = GetComponent<Rigidbody>();
|
||||
sphere = GetComponent<SphereCollider>();
|
||||
sphere.isTrigger = true;
|
||||
_rigidB.useGravity = false;
|
||||
_rigidB.isKinematic = true;
|
||||
_rigidB.constraints = RigidbodyConstraints.FreezeAll;
|
||||
if (headTrack) sphere.radius = headTrack.distanceToDetect;
|
||||
}
|
||||
|
||||
void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (headTrack != null) headTrack.OnDetect(other);
|
||||
}
|
||||
|
||||
void OnTriggerExit(Collider other)
|
||||
{
|
||||
if (headTrack != null) headTrack.OnLost(other);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6f8827d96877cdc4bb6f1b8126c504de
|
||||
timeCreated: 1472314528
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
271
Assets/Scripts/Player/HeadTrack/Scripts/vLookTarget.cs
Normal file
271
Assets/Scripts/Player/HeadTrack/Scripts/vLookTarget.cs
Normal file
@@ -0,0 +1,271 @@
|
||||
using UnityEngine;
|
||||
|
||||
using Invector.vCharacterController;
|
||||
|
||||
namespace Invector
|
||||
{
|
||||
public class vLookTarget : MonoBehaviour
|
||||
{
|
||||
public bool ignoreHeadTrackAngle;
|
||||
[Header("Set this to assign a different point to look")]
|
||||
public Transform lookPointTarget;
|
||||
[Header("Area to check if is visible")]
|
||||
public Vector3 centerArea = Vector3.zero;
|
||||
public Vector3 sizeArea = Vector3.one;
|
||||
public bool useLimitToDetect = true;
|
||||
public float minDistanceToDetect = 2f;
|
||||
public VisibleCheckType visibleCheckType;
|
||||
[Tooltip("use this to turn the object undetectable")]
|
||||
public bool HideObject;
|
||||
[System.Serializable]
|
||||
public class OnLookEvent : UnityEngine.Events.UnityEvent<vHeadTrack> { }
|
||||
public OnLookEvent onEnterLook, onExitLook;
|
||||
|
||||
|
||||
public enum VisibleCheckType
|
||||
{
|
||||
None, SingleCast, BoxCast
|
||||
}
|
||||
|
||||
void OnDrawGizmosSelected()
|
||||
{
|
||||
DrawBox();
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
var layer = LayerMask.NameToLayer("HeadTrack");
|
||||
gameObject.layer = layer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Point to look
|
||||
/// </summary>
|
||||
public Vector3 lookPoint
|
||||
{
|
||||
get
|
||||
{
|
||||
if (lookPointTarget)
|
||||
{
|
||||
return lookPointTarget.position;
|
||||
}
|
||||
else
|
||||
return transform.TransformPoint(centerArea);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawBox()
|
||||
{
|
||||
Gizmos.color = new Color(1, 0, 0, 1f);
|
||||
Gizmos.DrawSphere(lookPoint, 0.05f);
|
||||
if (visibleCheckType == VisibleCheckType.BoxCast)
|
||||
{
|
||||
var sizeX = transform.lossyScale.x * sizeArea.x;
|
||||
var sizeY = transform.lossyScale.y * sizeArea.y;
|
||||
var sizeZ = transform.lossyScale.z * sizeArea.z;
|
||||
var centerX = transform.lossyScale.x * centerArea.x;
|
||||
var centerY = transform.lossyScale.y * centerArea.y;
|
||||
var centerZ = transform.lossyScale.z * centerArea.z;
|
||||
Matrix4x4 rotationMatrix = Matrix4x4.TRS(transform.position + new Vector3(centerX, centerY, centerZ), transform.rotation, new Vector3(sizeX, sizeY, sizeZ) * 2f);
|
||||
Gizmos.matrix = rotationMatrix;
|
||||
Gizmos.color = new Color(0, 1, 0, 0.2f);
|
||||
Gizmos.DrawCube(Vector3.zero, Vector3.one);
|
||||
Gizmos.color = new Color(0, 1, 0, 1f);
|
||||
Gizmos.DrawWireCube(Vector3.zero, Vector3.one);
|
||||
|
||||
}
|
||||
else if (visibleCheckType == VisibleCheckType.SingleCast)
|
||||
{
|
||||
var point = transform.TransformPoint(centerArea);
|
||||
Gizmos.color = new Color(0, 1, 0, 1f);
|
||||
Gizmos.DrawSphere(point, 0.05f);
|
||||
}
|
||||
}
|
||||
|
||||
internal void EnterLook(vHeadTrack vHeadTrack)
|
||||
{
|
||||
onEnterLook.Invoke(vHeadTrack);
|
||||
}
|
||||
|
||||
internal void ExitLook(vHeadTrack vHeadTrack)
|
||||
{
|
||||
onExitLook.Invoke(vHeadTrack);
|
||||
}
|
||||
}
|
||||
|
||||
#region Helper
|
||||
public static class vLookTargetHelper
|
||||
{
|
||||
struct LookPoints
|
||||
{
|
||||
public Vector3 frontTopLeft;
|
||||
public Vector3 frontTopRight;
|
||||
public Vector3 frontBottomLeft;
|
||||
public Vector3 frontBottomRight;
|
||||
public Vector3 backTopLeft;
|
||||
public Vector3 backTopRight;
|
||||
public Vector3 backBottomLeft;
|
||||
public Vector3 backBottomRight;
|
||||
}
|
||||
|
||||
static LookPoints GetLookPoints(vLookTarget lookTarget)
|
||||
{
|
||||
LookPoints points = new LookPoints();
|
||||
var centerArea = lookTarget.centerArea;
|
||||
var sizeArea = lookTarget.sizeArea;
|
||||
var lookTransform = lookTarget.transform;
|
||||
points.frontTopLeft = new Vector3(centerArea.x - sizeArea.x, centerArea.y + sizeArea.y, centerArea.z - sizeArea.z);
|
||||
points.frontTopRight = new Vector3(centerArea.x + sizeArea.x, centerArea.y + sizeArea.y, centerArea.z - sizeArea.z);
|
||||
points.frontBottomLeft = new Vector3(centerArea.x - sizeArea.x, centerArea.y - sizeArea.y, centerArea.z - sizeArea.z);
|
||||
points.frontBottomRight = new Vector3(centerArea.x + sizeArea.x, centerArea.y - sizeArea.y, centerArea.z - sizeArea.z);
|
||||
points.backTopLeft = new Vector3(centerArea.x - sizeArea.x, centerArea.y + sizeArea.y, centerArea.z + sizeArea.z);
|
||||
points.backTopRight = new Vector3(centerArea.x + sizeArea.x, centerArea.y + sizeArea.y, centerArea.z + sizeArea.z);
|
||||
points.backBottomLeft = new Vector3(centerArea.x - sizeArea.x, centerArea.y - sizeArea.y, centerArea.z + sizeArea.z);
|
||||
points.backBottomRight = new Vector3(centerArea.x + sizeArea.x, centerArea.y - sizeArea.y, centerArea.z + sizeArea.z);
|
||||
|
||||
points.frontTopLeft = lookTransform.TransformPoint(points.frontTopLeft);
|
||||
points.frontTopRight = lookTransform.TransformPoint(points.frontTopRight);
|
||||
points.frontBottomLeft = lookTransform.TransformPoint(points.frontBottomLeft);
|
||||
points.frontBottomRight = lookTransform.TransformPoint(points.frontBottomRight);
|
||||
points.backTopLeft = lookTransform.TransformPoint(points.backTopLeft);
|
||||
points.backTopRight = lookTransform.TransformPoint(points.backTopRight);
|
||||
points.backBottomLeft = lookTransform.TransformPoint(points.backBottomLeft);
|
||||
points.backBottomRight = lookTransform.TransformPoint(points.backBottomRight);
|
||||
return points;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if anny corner points of LookTarget area is visible from observer
|
||||
/// </summary>
|
||||
/// <param name="lookTarget">principal transform of lookTarget</param>
|
||||
/// <param name="from">observer point</param>
|
||||
/// <param name="layerMask">Layer to check</param>
|
||||
/// <param name="debug">Draw lines </param>
|
||||
/// <returns></returns>
|
||||
public static bool IsVisible(this vLookTarget lookTarget, Vector3 from, LayerMask layerMask, bool debug = false)
|
||||
{
|
||||
|
||||
if (lookTarget.HideObject) return false;
|
||||
|
||||
if (lookTarget.visibleCheckType == vLookTarget.VisibleCheckType.None)
|
||||
{
|
||||
if (lookTarget.useLimitToDetect && Vector3.Distance(from, lookTarget.transform.position) > lookTarget.minDistanceToDetect) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (lookTarget.visibleCheckType == vLookTarget.VisibleCheckType.SingleCast)
|
||||
{
|
||||
if (lookTarget.useLimitToDetect && Vector3.Distance(from, lookTarget.centerArea) > lookTarget.minDistanceToDetect) return false;
|
||||
if (CastPoint(from, lookTarget.transform.TransformPoint(lookTarget.centerArea), lookTarget.transform, layerMask, debug)) return true; else return false;
|
||||
}
|
||||
else if (lookTarget.visibleCheckType == vLookTarget.VisibleCheckType.BoxCast)
|
||||
{
|
||||
if (lookTarget.useLimitToDetect && Vector3.Distance(from, lookTarget.transform.position) > lookTarget.minDistanceToDetect) return false;
|
||||
LookPoints points = GetLookPoints(lookTarget);
|
||||
|
||||
if (CastPoint(from, points.frontTopLeft, lookTarget.transform, layerMask, debug)) return true;
|
||||
|
||||
if (CastPoint(from, points.frontTopRight, lookTarget.transform, layerMask, debug)) return true;
|
||||
|
||||
if (CastPoint(from, points.frontBottomLeft, lookTarget.transform, layerMask, debug)) return true;
|
||||
|
||||
if (CastPoint(from, points.frontBottomRight, lookTarget.transform, layerMask, debug)) return true;
|
||||
|
||||
if (CastPoint(from, points.backTopLeft, lookTarget.transform, layerMask, debug)) return true;
|
||||
|
||||
if (CastPoint(from, points.backTopRight, lookTarget.transform, layerMask, debug)) return true;
|
||||
|
||||
if (CastPoint(from, points.backBottomLeft, lookTarget.transform, layerMask, debug)) return true;
|
||||
|
||||
if (CastPoint(from, points.backBottomRight, lookTarget.transform, layerMask, debug)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if anny corner points of LookTarget area is visible from observer
|
||||
/// </summary>
|
||||
/// <param name="lookTarget">principal transform of lookTarget</param>
|
||||
/// <param name="from">observer point</param>
|
||||
/// <param name="debug">Draw lines </param>
|
||||
/// <returns></returns>
|
||||
public static bool IsVisible(this vLookTarget lookTarget, Vector3 from, bool debug = false)
|
||||
{
|
||||
if (lookTarget.HideObject) return false;
|
||||
LookPoints points = GetLookPoints(lookTarget);
|
||||
if (lookTarget.visibleCheckType == vLookTarget.VisibleCheckType.None)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (lookTarget.visibleCheckType == vLookTarget.VisibleCheckType.SingleCast)
|
||||
{
|
||||
if (CastPoint(from, lookTarget.transform.TransformPoint(lookTarget.centerArea), lookTarget.transform, debug)) return true; else return false;
|
||||
}
|
||||
else if (lookTarget.visibleCheckType == vLookTarget.VisibleCheckType.BoxCast)
|
||||
{
|
||||
if (CastPoint(from, points.frontTopLeft, lookTarget.transform, debug)) return true;
|
||||
|
||||
if (CastPoint(from, points.frontTopRight, lookTarget.transform, debug)) return true;
|
||||
|
||||
if (CastPoint(from, points.frontBottomLeft, lookTarget.transform, debug)) return true;
|
||||
|
||||
if (CastPoint(from, points.frontBottomRight, lookTarget.transform, debug)) return true;
|
||||
|
||||
if (CastPoint(from, points.backTopLeft, lookTarget.transform, debug)) return true;
|
||||
|
||||
if (CastPoint(from, points.backTopRight, lookTarget.transform, debug)) return true;
|
||||
|
||||
if (CastPoint(from, points.backBottomLeft, lookTarget.transform, debug)) return true;
|
||||
|
||||
if (CastPoint(from, points.backBottomRight, lookTarget.transform, debug)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool CastPoint(Vector3 from, Vector3 point, Transform lookTarget, LayerMask layerMask, bool debug = false)
|
||||
{
|
||||
RaycastHit hit;
|
||||
|
||||
if (Physics.Linecast(from, point, out hit, layerMask))
|
||||
{
|
||||
if (hit.transform != lookTarget.transform)
|
||||
{
|
||||
if (debug) Debug.DrawLine(from, hit.point, Color.red);
|
||||
return false;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (debug) Debug.DrawLine(from, hit.point, Color.green);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (debug) Debug.DrawLine(from, point, Color.green);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool CastPoint(Vector3 from, Vector3 point, Transform lookTarget, bool debug = false)
|
||||
{
|
||||
RaycastHit hit;
|
||||
|
||||
if (Physics.Linecast(from, point, out hit))
|
||||
{
|
||||
if (hit.transform != lookTarget.transform)
|
||||
{
|
||||
if (debug) Debug.DrawLine(from, hit.point, Color.red);
|
||||
return false;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (debug) Debug.DrawLine(from, hit.point, Color.green);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (debug) Debug.DrawLine(from, point, Color.green);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
12
Assets/Scripts/Player/HeadTrack/Scripts/vLookTarget.cs.meta
Normal file
12
Assets/Scripts/Player/HeadTrack/Scripts/vLookTarget.cs.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 079af0928a59a2a489c3eb00c58cd2f4
|
||||
timeCreated: 1469630605
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user