BITFALL/Assets/Plugins/Character Controller Pro/Demo/Scripts/Platforms/NodeBasedPlatform.cs

311 lines
7.6 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Lightbug.CharacterControllerPro.Core;
using Lightbug.Utilities;
namespace Lightbug.CharacterControllerPro.Demo
{
/// <summary>
/// A "KinematicPlatform" implementation whose movement and rotation are purely based on nodes. Use this component to create platforms that moves and
/// rotate precisely following a predefined path.
/// </summary>
[AddComponentMenu("Character Controller Pro/Demo/Dynamic Platform/Node Based Platform")]
public class NodeBasedPlatform : Platform
{
public enum SequenceType
{
Rewind,
Loop,
OneWay
}
enum ActionState
{
Idle,
Ready,
Waiting,
Working,
Done
}
//[Header("Debug Options")]
[SerializeField] bool drawHandles = true;
public bool DrawHandles
{
get
{
return drawHandles;
}
}
//[Header("Actions")]
public bool move = true;
public bool rotate = false;
[SerializeField]
List<PlatformNode> actionsList = new List<PlatformNode>();
public List<PlatformNode> ActionsList
{
get
{
return actionsList;
}
}
public SequenceType sequenceType;
public bool positiveSequenceDirection = true;
[Range(0.1f, 50)]
[SerializeField]
float globalSpeedModifier = 1;
ActionState actionState;
Vector3 targetPosition;
Vector3 targetRotation;
Vector3 startingPosition;
Vector3 startingRotation;
bool updateInitialPosition = true;
public bool UpdateInitialPosition
{
get
{
return updateInitialPosition;
}
}
Vector3 initialPosition;
public Vector3 InitialPosition
{
get
{
return initialPosition;
}
}
float time = 0;
PlatformNode currentAction = null;
int currentActionIndex = 0;
public int CurrentActionIndex
{
get
{
return currentActionIndex;
}
}
protected override void Awake()
{
base.Awake();
updateInitialPosition = false;
initialPosition = transform.position;
actionState = ActionState.Ready;
currentActionIndex = 0;
currentAction = actionsList[0];
}
void FixedUpdate()
{
float dt = Time.deltaTime;
switch (actionState)
{
case ActionState.Idle:
break;
case ActionState.Ready:
SetTargets();
actionState = ActionState.Working;
break;
case ActionState.Working:
time += dt * globalSpeedModifier;
if (time >= currentAction.targetTime)
{
actionState = ActionState.Done;
time = 0;
}
else
{
if (move)
RigidbodyComponent.Move(CalculatePosition());
Quaternion rotation = RigidbodyComponent.Rotation;
if (rotate)
RigidbodyComponent.Rotate(CalculateRotation());
}
break;
case ActionState.Done:
time = 0;
if (positiveSequenceDirection)
{
if (currentActionIndex != (actionsList.Count - 1))
{
currentActionIndex++;
actionState = ActionState.Ready;
}
else
{
switch (sequenceType)
{
case SequenceType.Loop:
currentActionIndex = 0;
actionState = ActionState.Ready;
break;
case SequenceType.Rewind:
currentActionIndex--;
positiveSequenceDirection = false;
actionState = ActionState.Ready;
break;
case SequenceType.OneWay:
actionState = ActionState.Idle;
break;
}
}
}
else
{
if (currentActionIndex != 0)
{
currentActionIndex--;
actionState = ActionState.Ready;
}
else
{
switch (sequenceType)
{
case SequenceType.Loop:
currentActionIndex = actionsList.Count - 1;
actionState = ActionState.Ready;
break;
case SequenceType.Rewind:
currentActionIndex++;
positiveSequenceDirection = true;
actionState = ActionState.Ready;
break;
case SequenceType.OneWay:
actionState = ActionState.Idle;
break;
}
}
}
currentAction = actionsList[currentActionIndex];
break;
}
}
public override string ToString()
{
return "Current Index = " + currentActionIndex + '\n' +
"State = " + actionState;
}
void SetTargets()
{
startingPosition = transform.position;
startingRotation = transform.eulerAngles;
targetPosition = initialPosition + currentAction.position;
targetRotation = currentAction.eulerAngles;
}
Vector3 CalculatePosition()
{
float curveTime = time / currentAction.targetTime;
Vector3 position = Vector3.Lerp(
startingPosition,
this.targetPosition,
currentAction.movementCurve.Evaluate(curveTime)
);
return position;
}
Quaternion CalculateRotation()
{
float curveTime = time / currentAction.targetTime;
float curveResult = currentAction.rotationCurve.Evaluate(curveTime);
Vector3 finalAngle;
finalAngle.x = Mathf.LerpAngle(startingRotation.x, this.targetRotation.x, curveResult);
finalAngle.y = Mathf.LerpAngle(startingRotation.y, this.targetRotation.y, curveResult);
finalAngle.z = Mathf.LerpAngle(startingRotation.z, this.targetRotation.z, curveResult);
Quaternion rotation = Quaternion.Euler(finalAngle);
return rotation;
}
}
}