1
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Lightbug.CharacterControllerPro.Implementation;
|
||||
using Lightbug.Utilities;
|
||||
|
||||
namespace Lightbug.CharacterControllerPro.Demo
|
||||
{
|
||||
|
||||
public class RopeClimbing : CharacterState
|
||||
{
|
||||
[Header("Movement")]
|
||||
|
||||
[SerializeField]
|
||||
protected float climbSpeed = 3f;
|
||||
|
||||
[SerializeField]
|
||||
protected float angularSpeed = 120f;
|
||||
|
||||
[SerializeField]
|
||||
protected float jumpVelocity = 10f;
|
||||
|
||||
[SerializeField]
|
||||
protected float verticalAcceleration = 10f;
|
||||
|
||||
[SerializeField]
|
||||
protected float angularAcceleration = 10f;
|
||||
|
||||
[Header("Offset")]
|
||||
|
||||
[SerializeField]
|
||||
protected float forwardOffset = -0.25f;
|
||||
|
||||
[Header("Animation")]
|
||||
|
||||
[SerializeField]
|
||||
protected string verticalVelocityParameter = "VerticalVelocity";
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
||||
// ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
protected Rope currentRope = null;
|
||||
|
||||
protected Dictionary<Transform, Rope> ropes = new Dictionary<Transform, Rope>();
|
||||
|
||||
protected Vector3 verticalVelocity;
|
||||
protected Vector3 angularVelocity;
|
||||
|
||||
|
||||
Vector3 ReferencePosition => CharacterActor.Top;
|
||||
|
||||
Vector3 ClosestVectorToRope
|
||||
{
|
||||
get
|
||||
{
|
||||
Vector3 characterToTop = currentRope.TopPosition - CharacterActor.Position;
|
||||
return Vector3.ProjectOnPlane(characterToTop, currentRope.BottomToTop);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
|
||||
#if UNITY_2023_1_OR_NEWER
|
||||
Rope[] ropesArray = FindObjectsByType<Rope>(FindObjectsSortMode.None);
|
||||
#else
|
||||
Rope[] ropesArray = FindObjectsOfType<Rope>();
|
||||
#endif
|
||||
for (int i = 0; i < ropesArray.Length; i++)
|
||||
ropes.Add(ropesArray[i].transform, ropesArray[i]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override void CheckExitTransition()
|
||||
{
|
||||
if (!currentRope.IsInRange(ReferencePosition) || CharacterActions.jump.Started)
|
||||
CharacterStateController.EnqueueTransition<NormalMovement>();
|
||||
}
|
||||
|
||||
public override bool CheckEnterTransition(CharacterState fromState)
|
||||
{
|
||||
for (int i = 0; i < CharacterActor.Triggers.Count; i++)
|
||||
{
|
||||
Trigger trigger = CharacterActor.Triggers[i];
|
||||
if (!trigger.firstContact)
|
||||
continue;
|
||||
|
||||
Rope rope = ropes.GetOrRegisterValue(trigger.transform);
|
||||
if (rope != null)
|
||||
{
|
||||
if (!rope.IsInRange(ReferencePosition))
|
||||
return false;
|
||||
|
||||
currentRope = rope;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override void EnterBehaviour(float dt, CharacterState fromState)
|
||||
{
|
||||
CharacterActor.IsKinematic = false;
|
||||
CharacterActor.alwaysNotGrounded = true;
|
||||
CharacterActor.UseRootMotion = false;
|
||||
CharacterActor.Velocity = Vector3.zero;
|
||||
|
||||
Vector3 closestVectorToRope = ClosestVectorToRope;
|
||||
|
||||
CharacterActor.SetYaw(closestVectorToRope);
|
||||
CharacterActor.Position = CharacterActor.Position + closestVectorToRope + CharacterActor.Forward * forwardOffset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public override void ExitBehaviour(float dt, CharacterState toState)
|
||||
{
|
||||
|
||||
CharacterActor.alwaysNotGrounded = false;
|
||||
currentRope = null;
|
||||
|
||||
if (CharacterActions.jump.Started)
|
||||
{
|
||||
if (CharacterActions.movement.Detected)
|
||||
CharacterActor.Velocity = CharacterStateController.InputMovementReference * jumpVelocity;
|
||||
else
|
||||
CharacterActor.Velocity = CharacterStateController.MovementReferenceForward * jumpVelocity;
|
||||
|
||||
CharacterActor.SetYaw(Vector3.Normalize(CharacterActor.Velocity));
|
||||
}
|
||||
else
|
||||
{
|
||||
CharacterActor.Velocity = Vector3.zero;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public override void UpdateBehaviour(float dt)
|
||||
{
|
||||
Vector3 characterPosition = CharacterActor.Position;
|
||||
|
||||
float targetAngularSpeed = CharacterActions.movement.value.x * angularSpeed;
|
||||
|
||||
|
||||
characterPosition = CustomUtilities.RotatePointAround(
|
||||
characterPosition,
|
||||
characterPosition + ClosestVectorToRope,
|
||||
targetAngularSpeed * dt,
|
||||
Vector3.Normalize(currentRope.BottomToTop)
|
||||
);
|
||||
|
||||
Vector3 targetAngularVelocity = (characterPosition - CharacterActor.Position) / dt;
|
||||
angularVelocity = Vector3.MoveTowards(angularVelocity, targetAngularVelocity, angularAcceleration * dt);
|
||||
|
||||
|
||||
Vector3 targetVerticalVelocity = CharacterActions.movement.value.y * climbSpeed * CharacterActor.Up;
|
||||
verticalVelocity = Vector3.MoveTowards(verticalVelocity, targetVerticalVelocity, verticalAcceleration * dt);
|
||||
|
||||
CharacterActor.Velocity = verticalVelocity + angularVelocity;
|
||||
|
||||
}
|
||||
|
||||
public override void PostUpdateBehaviour(float dt)
|
||||
{
|
||||
// Always look towards the rope.
|
||||
CharacterActor.SetYaw(ClosestVectorToRope);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override void PostCharacterSimulation(float dt)
|
||||
{
|
||||
if (!CharacterActor.IsAnimatorValid())
|
||||
return;
|
||||
|
||||
CharacterActor.Animator.SetFloat(verticalVelocityParameter, CharacterActor.LocalVelocity.y);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
Reference in New Issue
Block a user