822 lines
26 KiB
C#
822 lines
26 KiB
C#
using UnityEngine;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System;
|
|
using PixelCrushers;
|
|
using UnityEngine.AI;
|
|
using Random = UnityEngine.Random;
|
|
using UnityEngine.Events;
|
|
|
|
namespace Beyond {
|
|
|
|
public class AnimSequencer : Saver
|
|
{
|
|
[Serializable]
|
|
public class SaveData
|
|
{
|
|
public State state;
|
|
public int currentPoint;
|
|
public int selectedIndex;
|
|
public int targetIndex;
|
|
public float timer;
|
|
public Vector3 position;
|
|
public Quaternion rotation;
|
|
}
|
|
|
|
public const float SEG_LENGTH = 10f;
|
|
public enum State { IDLE, MOVING };
|
|
public State mState = State.IDLE;
|
|
[HideInInspector]
|
|
public float mSeqTimer = 0f;
|
|
[HideInInspector]
|
|
public float mSpeed = 0.0f;
|
|
public float mAcc = 1f;
|
|
public float mMaxSpeed = 15f;
|
|
|
|
float mSegmentDist = 0f;
|
|
// public int points = 20;
|
|
|
|
public float m_randomMotionFreq = 1.5f;
|
|
public float m_randomMotionScale = 0.2f;
|
|
public float m_followRate = 1.5f;
|
|
// public float m_maxPlayerDist = 5f;
|
|
// public float m_minPlayerDist = 2f;
|
|
public float m_minTargetDistFromPlayer = 1f;
|
|
public bool m_WaitForPlayer = true;
|
|
public float m_maxDistanceFromPlayer = 10f;
|
|
|
|
Vector3 m_randShift = Vector3.zero;
|
|
|
|
public Transform m_objectToMove;
|
|
bool m_forward = true;
|
|
private Transform m_PlayerTransform;
|
|
|
|
//[HideInInspector]
|
|
//public Point[] mPoints;
|
|
[HideInInspector]
|
|
public SeqPoint[] mSeqPoints;
|
|
|
|
[HideInInspector]
|
|
public bool autoStart;
|
|
public float mTargetDistanceTh = 0.1f;
|
|
float mTimer = 0f;
|
|
// Vector3 mDestPos;
|
|
private int mSelectedIndex = -1;
|
|
private bool m_IsInfrontOfPlayer = true;
|
|
public int mTargetIndex = -1;
|
|
int mCurrentPoint = -1;
|
|
const int MAX_SEG = 100;
|
|
const int MIN_SEG = 10;
|
|
public float mMaxPlayerDistance = 100f;
|
|
|
|
[Serializable]
|
|
public class SeqPoint
|
|
{
|
|
public enum PointType { MOVING, STOP};
|
|
|
|
public SeqPoint(Vector3 pos)
|
|
{
|
|
speed = 5f;
|
|
acc = 3f;
|
|
angularSpeed = 10f;
|
|
animTime = 2f;
|
|
|
|
this.pos = pos;
|
|
length = -1.0f;
|
|
totalLength = -1.0f;
|
|
numSegments = 0;
|
|
rot = Quaternion.identity;
|
|
}
|
|
|
|
|
|
public SeqPoint(SeqPoint point, Vector3 shift)
|
|
{
|
|
speed = 5f;
|
|
acc = 3f;
|
|
angularSpeed = 10f;
|
|
animTime = 2f;
|
|
|
|
pos = point.pos + shift;
|
|
rot = point.rot;
|
|
length = point.length;
|
|
totalLength = point.totalLength;
|
|
numSegments = point.numSegments;
|
|
|
|
}
|
|
|
|
public void OnReached()
|
|
{
|
|
if (!eventFired)
|
|
{
|
|
eventFired = true;
|
|
onReached?.Invoke();
|
|
}
|
|
}
|
|
|
|
[SerializeField]
|
|
public float speed;
|
|
[SerializeField]
|
|
public float acc;
|
|
[SerializeField]
|
|
public float angularSpeed;
|
|
[SerializeField]
|
|
public float animTime;
|
|
//[SerializeField]
|
|
//public int targetPointIdx;
|
|
public UnityEvent onReached;
|
|
public PointType type = PointType.MOVING;
|
|
public Vector3 pos;
|
|
public Quaternion rot;
|
|
public float length; //length of segment starting at this point
|
|
public float totalLength; //total length excluding this segment
|
|
public int numSegments;
|
|
private bool eventFired = false;
|
|
}
|
|
|
|
IEnumerator GenerateRandomShift()
|
|
{
|
|
while (true)
|
|
{
|
|
m_randShift.x = Random.Range(-m_randomMotionScale, m_randomMotionScale);
|
|
m_randShift.y = Random.Range(-m_randomMotionScale, m_randomMotionScale);
|
|
m_randShift.z = Random.Range(-m_randomMotionScale, m_randomMotionScale);
|
|
|
|
yield return new WaitForSeconds(m_randomMotionFreq);
|
|
}
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
Debug.Log("Disabling AnimSequencer.");
|
|
}
|
|
|
|
public override string RecordData()
|
|
{
|
|
SaveData d = new SaveData();
|
|
d.position = transform.position;
|
|
d.rotation = transform.rotation;
|
|
d.state = mState;
|
|
d.timer = mTimer;
|
|
d.currentPoint = mCurrentPoint;
|
|
d.selectedIndex = mSelectedIndex;
|
|
d.targetIndex = mTargetIndex;
|
|
return SaveSystem.Serialize(d);
|
|
|
|
}
|
|
|
|
public override void ApplyData(string s)
|
|
{
|
|
if (String.IsNullOrEmpty(s))
|
|
return;
|
|
SaveData d = SaveSystem.Deserialize<SaveData>(s);
|
|
if (d == null)
|
|
return;
|
|
transform.position = d.position;
|
|
transform.rotation = d.rotation;
|
|
mState = d.state;
|
|
mTimer = d.timer;
|
|
mCurrentPoint = d.currentPoint;
|
|
mSelectedIndex = d.selectedIndex;
|
|
mTargetIndex = d.targetIndex;
|
|
}
|
|
|
|
void MoveTowardsRandom()
|
|
{
|
|
m_objectToMove.localPosition = Vector3.Lerp(m_randShift, m_objectToMove.localPosition, Mathf.Exp(-Time.deltaTime * m_followRate));
|
|
|
|
}
|
|
|
|
public int selectedIndex
|
|
{
|
|
get { return mSelectedIndex; }
|
|
set { mSelectedIndex = value; }
|
|
}
|
|
|
|
// Use this for initialization
|
|
void Reset()
|
|
{
|
|
// mPoints = new Point[2];
|
|
// mPoints[0] = new Point(transform.position);
|
|
// mPoints[1] = new Point(transform.position + new Vector3(0f, 0f, 1f));
|
|
mSeqPoints = new SeqPoint[1];
|
|
mSeqPoints[0] = new SeqPoint(transform.position);
|
|
mSelectedIndex = -1;
|
|
}
|
|
void SetState(State state)
|
|
{
|
|
if (mState == state)
|
|
return;
|
|
mTimer = 0f;
|
|
switch (state)
|
|
{
|
|
case State.IDLE:
|
|
break;
|
|
case State.MOVING:
|
|
break;
|
|
};
|
|
mState = state;
|
|
}
|
|
|
|
IEnumerator FindClosestPointToPlayer()
|
|
{
|
|
int idx = -1;
|
|
float minDist = -1f;
|
|
float dist = 0f;
|
|
|
|
while (true)
|
|
{
|
|
if (m_PlayerTransform == null)
|
|
break;
|
|
yield return new WaitForSeconds(0.5f);
|
|
minDist = float.PositiveInfinity;
|
|
Vector3 pos = m_PlayerTransform.position;
|
|
for (int i=0; i<mSeqPoints.Length; i++)
|
|
{
|
|
dist = (pos - mSeqPoints[i].pos).magnitude;
|
|
if (dist > m_minTargetDistFromPlayer && minDist > dist)
|
|
{
|
|
mTargetIndex = i;
|
|
minDist = dist;
|
|
}
|
|
}
|
|
|
|
}
|
|
yield return null;
|
|
}
|
|
|
|
private float CalcDistToPoint(int id)
|
|
{
|
|
Vector3 vec = m_PlayerTransform.position - mSeqPoints[id].pos;
|
|
vec.y = 0f;
|
|
return vec.magnitude;
|
|
}
|
|
|
|
private int FindClosestStopPoint(int currPoint, out float dist)
|
|
{
|
|
float minDist = float.PositiveInfinity; ;
|
|
dist = 0f;
|
|
int id = 0;
|
|
for (int i = 0; i < mSeqPoints.Length; i++)
|
|
{
|
|
if (mSeqPoints[i].type != SeqPoint.PointType.STOP)
|
|
continue;
|
|
if (i > currPoint + 1)
|
|
break;
|
|
if (i < currPoint - 1)
|
|
continue;
|
|
dist = CalcDistToPoint(i);
|
|
if (minDist > dist)
|
|
{
|
|
minDist = dist;
|
|
id = i;
|
|
}
|
|
}
|
|
return id;
|
|
}
|
|
|
|
|
|
IEnumerator FindNextClosestPointToPlayer()
|
|
{
|
|
float[] dists = { float.PositiveInfinity , float.PositiveInfinity , float.PositiveInfinity };
|
|
int[] ids = {0,0,0};
|
|
Vector3[] dirVecs = { Vector3.zero, Vector3.zero, Vector3.zero };
|
|
//int closestID = 0;
|
|
//float closestDist = 0f;
|
|
while (true)
|
|
{
|
|
if (m_PlayerTransform == null)
|
|
break;
|
|
yield return new WaitForSeconds(0.5f);
|
|
|
|
|
|
ids[1] = mTargetIndex;
|
|
if (ids[1] < 0)
|
|
ids[1] = 0;
|
|
|
|
//closestID = FindClosestStopPoint(ids[1], out closestDist);
|
|
|
|
//find previous and next point to current point
|
|
if (ids[1] > 0)
|
|
{
|
|
for (int i = ids[1] - 1; i >= 0; i--)
|
|
if (mSeqPoints[i].type == SeqPoint.PointType.STOP)
|
|
{
|
|
ids[0] = i;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ids[0] = 0;
|
|
}
|
|
|
|
if (ids[1] < mSeqPoints.Length - 1)
|
|
{
|
|
for (int i = ids[1] + 1; i < mSeqPoints.Length; i++)
|
|
if (mSeqPoints[i].type == SeqPoint.PointType.STOP)
|
|
{
|
|
ids[2] = i;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ids[2] = ids[1];
|
|
}
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
dirVecs[i] = mSeqPoints[ids[i]].pos - m_PlayerTransform.position;
|
|
dists[i] = dirVecs[i].magnitude;
|
|
}
|
|
//check if player if infront or behind me
|
|
var fromPlayer = transform.position - m_PlayerTransform.position;
|
|
var forward = mSeqPoints[ids[1]].pos - mSeqPoints[ids[0]].pos;
|
|
// var forward = mSeqPoints[ids[2]].pos - mSeqPoints[ids[1]].pos;
|
|
m_IsInfrontOfPlayer = Vector3.Dot(fromPlayer, forward) > 0f;
|
|
|
|
//check if previous point meets conditions, if yes, set it as a target
|
|
if (dists[0] < dists[1] && dists[0] > m_minTargetDistFromPlayer && Vector3.Dot(dirVecs[0], dirVecs[1]) > 0f)
|
|
{
|
|
//move to the previous point
|
|
mTargetIndex = ids[0];
|
|
continue;
|
|
}
|
|
//check if next point meets conditions, if yes, set it as a target
|
|
//if current & next points are infront of the player...
|
|
if (Vector3.Dot(dirVecs[1], dirVecs[2]) > 0f)
|
|
{
|
|
//if player is too close, move to the next point
|
|
if (dists[1] < m_minTargetDistFromPlayer || dists[2] < dists[1])
|
|
{
|
|
mTargetIndex = ids[2];
|
|
continue;
|
|
}
|
|
}
|
|
else //jump to the next
|
|
{
|
|
mTargetIndex = ids[2];
|
|
continue;
|
|
//Debug.Log("FindNextClosestPointToPlayer: need breakpoint");
|
|
}
|
|
|
|
}
|
|
yield return null;
|
|
}
|
|
|
|
IEnumerator FindNextPointToPlayer()
|
|
{
|
|
int idx = -1;
|
|
float minDist = -1f;
|
|
float dist = 0f;
|
|
|
|
while (true)
|
|
{
|
|
if (m_PlayerTransform == null)
|
|
break;
|
|
yield return new WaitForSeconds(0.5f);
|
|
minDist = float.PositiveInfinity;
|
|
Vector3 pos = m_PlayerTransform.position;
|
|
Vector3 pForward = m_PlayerTransform.forward;
|
|
for (int i = 0; i < mSeqPoints.Length; i++)
|
|
{
|
|
if (mSeqPoints[i].type != SeqPoint.PointType.STOP)
|
|
continue;
|
|
Vector3 vec = mSeqPoints[i].pos - pos;
|
|
vec.y = 0f;
|
|
if (Vector3.Dot(vec, pForward) < 0f)
|
|
continue;
|
|
dist = (vec).magnitude;
|
|
if (dist > m_minTargetDistFromPlayer && minDist > dist)
|
|
{
|
|
mTargetIndex = i;
|
|
minDist = dist;
|
|
}
|
|
}
|
|
Debug.LogError("Target point: "+mTargetIndex);
|
|
|
|
|
|
}
|
|
yield return null;
|
|
}
|
|
void Start()
|
|
{
|
|
var p = Player.Instance;
|
|
if (p)
|
|
{
|
|
m_PlayerTransform = p.transform;
|
|
//StartCoroutine(FindClosestPointToPlayer());
|
|
// StartCoroutine(FindNextPointToPlayer());
|
|
StartCoroutine(FindNextClosestPointToPlayer());
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("Player not found!");
|
|
}
|
|
UpdatePointsList();
|
|
if (mSeqPoints.Length > 1)
|
|
{
|
|
transform.position = mSeqPoints[0].pos;
|
|
//selectedIndex = 0;
|
|
}
|
|
//if (mState == State.MOVING)
|
|
{
|
|
NextSequencePoint();
|
|
}
|
|
if (m_objectToMove)
|
|
StartCoroutine(GenerateRandomShift());
|
|
}
|
|
|
|
public int Count
|
|
{
|
|
get
|
|
{
|
|
return mSeqPoints.Length;
|
|
}
|
|
}
|
|
|
|
public SeqPoint this[int i]
|
|
{
|
|
get
|
|
{
|
|
return mSeqPoints[i];
|
|
}
|
|
set
|
|
{
|
|
mSeqPoints[i] = value;
|
|
}
|
|
}
|
|
|
|
|
|
public Vector3 GetInterpolated(int idx, float t)
|
|
{
|
|
Vector3 p0, p3;
|
|
if (idx == 0)
|
|
p0 = mSeqPoints[idx].pos;
|
|
else
|
|
p0 = mSeqPoints[idx - 1].pos;
|
|
|
|
if (idx + 2 < mSeqPoints.Length)
|
|
p3 = mSeqPoints[idx + 2].pos;
|
|
else
|
|
p3 = mSeqPoints[idx + 1].pos;
|
|
//return transform.TransformPoint(CatmullRom(p0, mPoints[idx].pos, mPoints[idx + 1].pos, p3, t));
|
|
return CatmullRom(p0, mSeqPoints[idx].pos, mSeqPoints[idx + 1].pos, p3, t);
|
|
}
|
|
public float GetLength(int startIdx, float t0, float t1)
|
|
{
|
|
const float maxDist = .5f;
|
|
Vector3 p0 = GetInterpolated(startIdx, t0);
|
|
Vector3 p1 = GetInterpolated(startIdx, t1);
|
|
float d = (p1 - p0).magnitude;
|
|
if (d < maxDist)
|
|
return d;
|
|
else
|
|
return GetLength(startIdx, t0, (t0 + t1) * 0.5f) + GetLength(startIdx, (t0 + t1) * 0.5f, t1);
|
|
}
|
|
|
|
public void UpdatePointsList()
|
|
{
|
|
int numPoints = mSeqPoints.Length;
|
|
|
|
int cnt = 0;
|
|
mSeqPoints[cnt].pos = transform.position;
|
|
|
|
for (int i = 0; i < numPoints - 1; i++)
|
|
{
|
|
mSeqPoints[i].length = GetLength(i, 0f, 1f);
|
|
mSeqPoints[i].totalLength = i == 0 ? 0f : mSeqPoints[i - 1].totalLength + mSeqPoints[i - 1].length;
|
|
}
|
|
}
|
|
|
|
public void SetPointType(int selectedIndex, SeqPoint.PointType pointType)
|
|
{
|
|
mSeqPoints[selectedIndex].type = pointType;
|
|
}
|
|
|
|
public Quaternion GetInterpolatedRot(int idx, float t)
|
|
{
|
|
Quaternion p0, p3;
|
|
if (idx == 0)
|
|
p0 = mSeqPoints[idx].rot;
|
|
else
|
|
p0 = mSeqPoints[idx - 1].rot;
|
|
|
|
if (idx + 2 < mSeqPoints.Length)
|
|
p3 = mSeqPoints[idx + 2].rot;
|
|
else
|
|
p3 = mSeqPoints[idx].rot;
|
|
return CatmullRom(p0, mSeqPoints[idx].rot, mSeqPoints[idx + 1].rot, p3, t);
|
|
}
|
|
|
|
|
|
public void AddSeqPoint()
|
|
{
|
|
if (mSelectedIndex < 0)
|
|
mSelectedIndex = mSeqPoints.Length - 1;
|
|
SeqPoint[] arr = mSeqPoints;
|
|
mSeqPoints = new SeqPoint[arr.Length + 1];
|
|
for (int i = 0; i <= mSelectedIndex; i++)
|
|
{
|
|
mSeqPoints[i] = arr[i];
|
|
}
|
|
|
|
|
|
Vector3 prevPoint = arr.Length > 0 ? arr[mSelectedIndex].pos : transform.position;
|
|
|
|
if (mSelectedIndex == arr.Length - 1) //this is the last point
|
|
{
|
|
mSeqPoints[mSelectedIndex + 1] = new SeqPoint(prevPoint + transform.forward);
|
|
}
|
|
else
|
|
{
|
|
mSeqPoints[mSelectedIndex + 1] = new SeqPoint((prevPoint + arr[mSelectedIndex+1].pos)*0.5f);
|
|
for (int i= mSelectedIndex + 2; i<mSeqPoints.Length; i++)
|
|
{
|
|
mSeqPoints[i] = arr[i - 1];
|
|
}
|
|
}
|
|
mSelectedIndex++;
|
|
}
|
|
|
|
public void RemoveSelected()
|
|
{
|
|
if (mSelectedIndex > -1)
|
|
{
|
|
SeqPoint[] arr = mSeqPoints;
|
|
int cnt = 0;
|
|
mSeqPoints = new SeqPoint[arr.Length - 1];
|
|
for (int i = 0; i < arr.Length; i++)
|
|
{
|
|
if (i != mSelectedIndex)
|
|
{
|
|
mSeqPoints[cnt++] = arr[i];
|
|
}
|
|
}
|
|
|
|
if (mSeqPoints.Length == mSelectedIndex)
|
|
{
|
|
mSelectedIndex--;
|
|
}
|
|
}
|
|
|
|
UpdatePointsList();
|
|
}
|
|
|
|
|
|
public void MoveSelectedUp()
|
|
{
|
|
|
|
if (mSelectedIndex > 0)
|
|
{
|
|
SeqPoint p = mSeqPoints[mSelectedIndex];
|
|
mSeqPoints[mSelectedIndex] = mSeqPoints[mSelectedIndex - 1];
|
|
mSeqPoints[mSelectedIndex - 1] = p;
|
|
}
|
|
UpdatePointsList();
|
|
}
|
|
|
|
public void MoveSelectedDown()
|
|
{
|
|
if (mSelectedIndex < mSeqPoints.Length - 1)
|
|
{
|
|
SeqPoint p = mSeqPoints[mSelectedIndex];
|
|
mSeqPoints[mSelectedIndex] = mSeqPoints[mSelectedIndex + 1];
|
|
mSeqPoints[mSelectedIndex + 1] = p;
|
|
}
|
|
UpdatePointsList();
|
|
}
|
|
|
|
Vector3 CatmullRom(Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4, float s)
|
|
{
|
|
Vector3 res;
|
|
float s2, s3;
|
|
s2 = s * s;
|
|
s3 = s2 * s;
|
|
res = p1 * (-s3 + 2.0f * s2 - s) + p2 * (3.0f * s3 - 5.0f * s2 + 2.0f) + p3 * (-3.0f * s3 + 4.0f * s2 + s) + p4 * (s3 - s2);
|
|
res /= 2.0f;
|
|
return res;
|
|
}
|
|
|
|
Quaternion CatmullRom(Quaternion p1, Quaternion p2, Quaternion p3, Quaternion p4, float s)
|
|
{
|
|
Quaternion res;
|
|
float s2, s3;
|
|
s2 = s * s;
|
|
s3 = s2 * s;
|
|
res = p1.Mul(-s3 + 2.0f * s2 - s).Add(p2.Mul(3.0f * s3 - 5.0f * s2 + 2.0f).Add(p3.Mul(-3.0f * s3 + 4.0f * s2 + s).Add(p4.Mul(s3 - s2))));
|
|
res.Mul(0.5f);
|
|
return res;
|
|
}
|
|
|
|
public Vector3 GetWorldPos(int idx)
|
|
{
|
|
// return transform.TransformPoint(mPoints[idx].pos);
|
|
return mSeqPoints[idx].pos;
|
|
}
|
|
|
|
void NextSequencePoint()
|
|
{
|
|
mTimer = 0f;
|
|
mSelectedIndex++;
|
|
if (mSelectedIndex >= mSeqPoints.Length-1)
|
|
{
|
|
//SetState(State.IDLE);
|
|
return;
|
|
}
|
|
SeqPoint point = mSeqPoints[mSelectedIndex];
|
|
//mDestPos = point.pos;
|
|
mSegmentDist = 0f;
|
|
}
|
|
|
|
void PrevSequencePoint()
|
|
{
|
|
mTimer = 0f;
|
|
mSelectedIndex--;
|
|
if (mSelectedIndex < 0)
|
|
{
|
|
//SetState(State.IDLE);
|
|
return;
|
|
}
|
|
SeqPoint point = mSeqPoints[mSelectedIndex];
|
|
//mDestPos = point.pos;
|
|
mSegmentDist = 1f;
|
|
}
|
|
void OnGUI()
|
|
{
|
|
|
|
}
|
|
|
|
// Project vector on plane
|
|
Vector3 ProjectVectorOnPlane(Vector3 planeNormal, Vector3 vector)
|
|
{
|
|
return vector - (Vector3.Dot(vector, planeNormal) * planeNormal);
|
|
}
|
|
|
|
// Get signed vector angle
|
|
float SignedVectorAngle(Vector3 referenceVector, Vector3 otherVector, Vector3 normal)
|
|
{
|
|
Vector3 perpVector;
|
|
float angle;
|
|
|
|
perpVector = Vector3.Cross(normal, referenceVector);
|
|
angle = Vector3.Angle(referenceVector, otherVector);
|
|
angle *= Mathf.Sign(Vector3.Dot(perpVector, otherVector));
|
|
|
|
return angle;
|
|
}
|
|
|
|
|
|
float DistanceLeft(int pointID)
|
|
{
|
|
float dist = 0f;
|
|
if (m_forward)
|
|
{
|
|
if (mSelectedIndex < mSeqPoints.Length - 1 && mSelectedIndex >= 0 && pointID > mSelectedIndex)
|
|
{
|
|
dist = (1f - mSegmentDist) * mSeqPoints[mSelectedIndex].length;
|
|
for (int i = mSelectedIndex + 1; i < pointID; i++)
|
|
{
|
|
dist += mSeqPoints[i].length;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (mSelectedIndex >= 0 && mSelectedIndex < mSeqPoints.Length - 1 && pointID <= mSelectedIndex)
|
|
{
|
|
dist = mSeqPoints[mSelectedIndex].length * mSegmentDist;
|
|
for (int i = pointID; i < mSelectedIndex; i++)
|
|
{
|
|
dist += mSeqPoints[i].length;
|
|
}
|
|
}
|
|
}
|
|
return dist;
|
|
}
|
|
|
|
|
|
void MoveBy(float val)
|
|
{
|
|
const float th = 0.005f;
|
|
float shift = Mathf.Abs(val);
|
|
float direction = Mathf.Sign(val);
|
|
int itter = 0;
|
|
do
|
|
{
|
|
itter++;
|
|
Vector3 currPos = transform.position;
|
|
SeqPoint point;
|
|
point = mSeqPoints[mSelectedIndex];
|
|
|
|
mSegmentDist += direction * shift / point.length;
|
|
|
|
if (mSegmentDist > 1f)
|
|
{
|
|
float d = mSegmentDist - 1f;
|
|
var tmp = d * point.length;
|
|
NextSequencePoint();
|
|
mSegmentDist += tmp / point.length;
|
|
}
|
|
else if (mSegmentDist < 0f)
|
|
{
|
|
float d = mSegmentDist;
|
|
var tmp = d * point.length;
|
|
PrevSequencePoint();
|
|
mSegmentDist -= tmp / point.length;
|
|
}
|
|
|
|
currPos = GetInterpolated(mSelectedIndex, mSegmentDist);
|
|
float dist = (currPos - transform.position).magnitude;
|
|
if (dist < shift)
|
|
{
|
|
shift -= dist;
|
|
}
|
|
else
|
|
{
|
|
shift = dist - shift;
|
|
direction *= -1f;
|
|
}
|
|
|
|
transform.position = currPos;
|
|
//transform.position += (currPos - transform.position).normalized * Mathf.Abs(val);
|
|
} while (shift > th && itter < 3);
|
|
//Debug.Log("MoveBy iterrs: "+itter+" final shift: "+shift);
|
|
}
|
|
void Update()
|
|
{
|
|
if (mState != State.MOVING && autoStart)
|
|
{
|
|
SetState(State.MOVING);
|
|
autoStart = false;
|
|
}
|
|
|
|
|
|
switch (mState)
|
|
{
|
|
case State.MOVING:
|
|
if (mSelectedIndex < mTargetIndex)
|
|
{
|
|
m_forward = true;
|
|
}
|
|
else
|
|
{
|
|
m_forward = false;
|
|
}
|
|
var dist = DistanceLeft(mTargetIndex);
|
|
//Debug.Log("AniSeq, moving, dist: "+dist+" target point: "+mTargetIndex+" sel idx: "+mSelectedIndex+" player: "+m_PlayerTransform.ToString());
|
|
if (dist < mTargetDistanceTh)
|
|
{
|
|
mCurrentPoint = mTargetIndex;
|
|
mSeqPoints[mCurrentPoint].OnReached();
|
|
SetState(State.IDLE);
|
|
break;
|
|
}
|
|
|
|
var breakingDist = mSpeed * mSpeed / (2f * mAcc);
|
|
|
|
|
|
if (dist > breakingDist)
|
|
{
|
|
if (mSpeed < mMaxSpeed)
|
|
{
|
|
mSpeed += mAcc * Time.deltaTime;
|
|
mSpeed = Mathf.Clamp(mSpeed, 0f, mMaxSpeed);
|
|
}
|
|
//slow down and wait for player
|
|
if (m_WaitForPlayer && m_IsInfrontOfPlayer && m_forward && m_PlayerTransform != null)
|
|
{
|
|
var d = (transform.position - m_PlayerTransform.position).magnitude;
|
|
float a = (d - m_minTargetDistFromPlayer) / m_maxDistanceFromPlayer;
|
|
mSpeed *= 1f - Mathf.Clamp01(a);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mSpeed -= mAcc * Time.deltaTime;
|
|
mSpeed = Mathf.Clamp(mSpeed, 0f, mMaxSpeed);
|
|
}
|
|
float shift = mSpeed * Time.deltaTime;
|
|
if (!m_forward)
|
|
shift *= -1f;
|
|
MoveBy(shift);
|
|
|
|
|
|
break;
|
|
case State.IDLE:
|
|
if (mCurrentPoint >= 0 & mCurrentPoint < mSeqPoints.Length)
|
|
transform.position = Vector3.Lerp(transform.position, mSeqPoints[mCurrentPoint].pos, Mathf.Exp(-Time.deltaTime * m_followRate));
|
|
if (mCurrentPoint != mTargetIndex && mTimer > 3f)
|
|
{
|
|
SetState(State.MOVING);
|
|
}
|
|
break;
|
|
}
|
|
mTimer += Time.deltaTime;
|
|
MoveTowardsRandom();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|