Initial Commit
This commit is contained in:
commit
ee5c2f922d
2255 changed files with 547750 additions and 0 deletions
258
Assets/Scripts/Systems/Player/PlayerMoveSystem.cs
Normal file
258
Assets/Scripts/Systems/Player/PlayerMoveSystem.cs
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
using DefaultNamespace;
|
||||
using Polycrime;
|
||||
using System;
|
||||
using Trive.Core;
|
||||
using Trive.Mono.Utils;
|
||||
using Tween;
|
||||
using Unity.Entities;
|
||||
using UnityEngine;
|
||||
using Zenject;
|
||||
|
||||
[UpdateInGroup(typeof(SimulationSystemGroup)), UpdateAfter(typeof(PlayerActionMapSystem))]
|
||||
public class PlayerMoveSystem : InjectableComponentSystem, IInitializable
|
||||
{
|
||||
[Serializable]
|
||||
public class Settings
|
||||
{
|
||||
public float FallGravityMultiply = 2.5f;
|
||||
public float GroundSnapForce;
|
||||
public float JumpDirForcePercent = 1;
|
||||
public float JumpHeight;
|
||||
public ParticleSystem JumpParticles;
|
||||
public float LowJumpGravityMultiply = 2.5f;
|
||||
public float MaxAirForce = 1;
|
||||
public float MaxForce = 1;
|
||||
public float MaxGroundAngle = 45;
|
||||
public float MaxGroundSnapDistance;
|
||||
public float moveForce = 1;
|
||||
public PIDFloat movePid;
|
||||
public PIDFloat movePidVertical;
|
||||
public float ObsticleJumpTime = 0.2f;
|
||||
public AnimationCurve SlopeMoveForce;
|
||||
public LayerMask StepAssistMask;
|
||||
public float StepAssistMaxHeight;
|
||||
|
||||
[Tooltip("The maximum angle the player can vault from")] public float VaultFromAngleMax;
|
||||
|
||||
public float VaultMaxAngle;
|
||||
public Vector2 VaultObsicleRange;
|
||||
}
|
||||
|
||||
[Inject] private readonly AudioListener audioListener;
|
||||
[Inject] private readonly PlayerFacade playerFacade;
|
||||
[Inject] private readonly Settings settings;
|
||||
private Transform head;
|
||||
private float lastDir;
|
||||
private float lastStepSign;
|
||||
private float stepTimer;
|
||||
|
||||
[Inject] private TweenSystem tweenSystem;
|
||||
|
||||
private float DeltaTime => Time.fixedDeltaTime;
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
head = playerFacade.FindChildGlobal<Transform>("$Head");
|
||||
}
|
||||
|
||||
protected override void OnSystemUpdate()
|
||||
{
|
||||
Entities.WithAllReadOnly<ActorBoundsData, Rotation2D>()
|
||||
.ForEach(
|
||||
(
|
||||
Entity entity,
|
||||
Rigidbody2D rigidbody,
|
||||
ref PlayerData player,
|
||||
ref ActorData actor,
|
||||
ref AnimatorStateData animationState,
|
||||
ref PlayerInput input,
|
||||
ref ActorAnimationData animation) =>
|
||||
{
|
||||
var bounds = EntityManager.GetComponentData<ActorBoundsData>(entity);
|
||||
var rotation = EntityManager.GetComponentData<Rotation2D>(entity);
|
||||
|
||||
if (actor.Grounded)
|
||||
{
|
||||
player.AirControlAmount = 1;
|
||||
}
|
||||
|
||||
audioListener.transform.position = head.transform.position;
|
||||
|
||||
UpdateVelocity(rigidbody, actor, input, animationState, ref animation, rotation, player);
|
||||
|
||||
if (Mathf.Abs(input.HorizontalInput) > 0)
|
||||
{
|
||||
lastDir = Mathf.Sign(input.HorizontalInput);
|
||||
}
|
||||
|
||||
float snapMultiply = 1;
|
||||
|
||||
ManageVaulting(entity, rigidbody, bounds, actor, rotation, ref animation, ref input, ref snapMultiply, ref player);
|
||||
|
||||
ManageJumping(ref input, rigidbody, bounds, ref actor, ref animation);
|
||||
|
||||
SnapToGround(rigidbody, actor, snapMultiply);
|
||||
});
|
||||
}
|
||||
|
||||
private void ManageJumping(
|
||||
ref PlayerInput input,
|
||||
Rigidbody2D rigidbody,
|
||||
ActorBoundsData bounds,
|
||||
ref ActorData actor,
|
||||
ref ActorAnimationData animation)
|
||||
{
|
||||
if (actor.Grounded)
|
||||
{
|
||||
if (input.JumpPressed)
|
||||
{
|
||||
var boundsSize = bounds.Rect.size;
|
||||
var boundsCenter = bounds.Rect.center;
|
||||
|
||||
var rayStart = boundsCenter + Vector2.up * boundsSize.y * 0.5f;
|
||||
var hit = Physics2D.CircleCast(rayStart, boundsSize.x * 0.5f, Vector2.up, settings.JumpHeight, settings.StepAssistMask);
|
||||
|
||||
var maxJumpHeight = Mathf.Min(settings.JumpHeight, hit.collider != null ? hit.distance + boundsSize.x : settings.JumpHeight);
|
||||
var jumpVelY = Mathf.Sqrt(0 - 2 * Physics2D.gravity.y * maxJumpHeight);
|
||||
Vector3 jumpForce = Vector2.up * jumpVelY + new Vector2(input.HorizontalInput, 0) * settings.JumpDirForcePercent * jumpVelY;
|
||||
rigidbody.AddForce(jumpForce * rigidbody.mass, ForceMode2D.Impulse);
|
||||
actor.Grounded = false;
|
||||
settings.JumpParticles.Emit(new ParticleSystem.EmitParams { position = rigidbody.position }, 1);
|
||||
animation.Triggers |= AnimationTriggerType.Jump;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private float CalculateSlopeSpeed(Vector2 slopeNormal, float input, float rotationAxis)
|
||||
{
|
||||
var slotDer = Mathf.Sign(Vector2.SignedAngle(slopeNormal, Vector2.up));
|
||||
var slopeAngle = Vector2.Angle(slopeNormal, Vector2.up);
|
||||
|
||||
//must be looking in the same direction as the input for it to go negative
|
||||
return settings.SlopeMoveForce.Evaluate(
|
||||
slopeAngle / settings.MaxGroundAngle * (Mathf.Sign(input) == slotDer ? Mathf.Sign(rotationAxis) != Mathf.Sign(input) ? -1 : 1 : 1));
|
||||
}
|
||||
|
||||
private void UpdateVelocity(
|
||||
Rigidbody2D rigidbody,
|
||||
ActorData actor,
|
||||
PlayerInput input,
|
||||
AnimatorStateData animationState,
|
||||
ref ActorAnimationData animation,
|
||||
Rotation2D rotation,
|
||||
PlayerData playerData)
|
||||
{
|
||||
var slopeSpeedMultiply = CalculateSlopeSpeed(actor.GroundUp, input.HorizontalInput, rotation.Axis);
|
||||
var walkMultiply = Mathf.Min(Mathf.Abs(input.HorizontalInput), Mathf.Abs(rigidbody.velocity.x));
|
||||
animation.WalkMultiply = walkMultiply * slopeSpeedMultiply;
|
||||
|
||||
rigidbody.gravityScale = actor.Grounded ? 1 :
|
||||
rigidbody.velocity.y > 0 ? input.Jump ? 1 : settings.LowJumpGravityMultiply : settings.FallGravityMultiply;
|
||||
var desiredMoveForce = input.HorizontalInput *
|
||||
settings.moveForce *
|
||||
(animationState.State.IsTag("Interactive") || animationState.State.IsTag("CanMove") ? 1 : 0);
|
||||
var force = -Vector2.Perpendicular(actor.GroundUp) * desiredMoveForce * slopeSpeedMultiply;
|
||||
var groundOrientation = Vector2.SignedAngle(actor.GroundUp, Vector2.up);
|
||||
var rotatedVelocity = rigidbody.velocity.Rotate(groundOrientation);
|
||||
var actualLocalForce = rigidbody.velocity.x;
|
||||
var actualLocalVerticalForce = rigidbody.velocity.y;
|
||||
var maxForce = Mathf.Lerp(settings.MaxAirForce, settings.MaxForce, actor.Grounded ? 1 : 0) * playerData.AirControlAmount;
|
||||
var forceDelta = settings.movePid.Update(force.x, actualLocalForce, DeltaTime);
|
||||
var forceDeltaVertical = settings.movePidVertical.Update(force.y, actualLocalVerticalForce, DeltaTime);
|
||||
forceDelta = Mathf.Clamp(forceDelta, -maxForce, maxForce);
|
||||
forceDeltaVertical = Mathf.Clamp(forceDeltaVertical, -settings.MaxForce, settings.MaxForce) *
|
||||
(actor.GroundDinstance >= 0 ? 1 - Mathf.Clamp01(actor.GroundDinstance / settings.MaxGroundSnapDistance) : 0);
|
||||
rigidbody.AddForce(Vector2.right * forceDelta);
|
||||
rigidbody.AddForce(Vector2.up * forceDeltaVertical);
|
||||
}
|
||||
|
||||
private void SnapToGround(Rigidbody2D rigidbody, ActorData actor, float snapMultiply)
|
||||
{
|
||||
if (actor.GroundDinstance > 0 && actor.Grounded)
|
||||
{
|
||||
var inverseGroundDistance = 1 - Mathf.Clamp01(actor.GroundDinstance / settings.MaxGroundSnapDistance);
|
||||
rigidbody.AddForce(-actor.GroundUp * settings.GroundSnapForce * snapMultiply);
|
||||
}
|
||||
}
|
||||
|
||||
private void ManageVaulting(
|
||||
Entity entity,
|
||||
Rigidbody2D rigidbody,
|
||||
ActorBoundsData bounds,
|
||||
ActorData actor,
|
||||
Rotation2D rotation,
|
||||
ref ActorAnimationData animation,
|
||||
ref PlayerInput playerInput,
|
||||
ref float snapMultiply,
|
||||
ref PlayerData playerData)
|
||||
{
|
||||
var boundsSize = bounds.Rect.size;
|
||||
var boundsCenter = bounds.Rect.center;
|
||||
|
||||
var floorAxis = Mathf.FloorToInt(Mathf.Abs(playerInput.HorizontalInput));
|
||||
var axisSign = (int)Mathf.Sign(playerInput.HorizontalInput);
|
||||
var axisAndLookAreSame = Mathf.Sign(playerInput.HorizontalInput) != rotation.Axis;
|
||||
var forwardTop = boundsCenter +
|
||||
Vector2.left * rotation.Axis * boundsSize.x * (axisSign * floorAxis * -rotation.Axis * (axisAndLookAreSame ? 1 : 0)) +
|
||||
Vector2.up * boundsSize.y * 0.5f;
|
||||
|
||||
RaycastHit2D topHit, bottomHit;
|
||||
|
||||
topHit = Physics2D.CircleCast(forwardTop, boundsSize.x * 0.5f, Vector2.up, boundsSize.y, settings.StepAssistMask);
|
||||
bottomHit = Physics2D.CircleCast(
|
||||
forwardTop,
|
||||
boundsSize.x * 0.5f,
|
||||
Vector2.down,
|
||||
boundsSize.y + settings.VaultObsicleRange.y,
|
||||
settings.StepAssistMask);
|
||||
|
||||
var topDistance = topHit.collider != null ? topHit.distance + boundsSize.x * 0.5f : boundsSize.y;
|
||||
var bottomDistance = bottomHit.collider != null ? bottomHit.distance + boundsSize.x * 0.5f : boundsSize.y;
|
||||
var groundAngle = Vector2.Angle(bottomHit.normal, Vector2.up);
|
||||
var currentAngle = Vector2.Angle(actor.GroundUp, Vector2.up);
|
||||
|
||||
var totalSize = topDistance + bottomDistance;
|
||||
var obsticleHeight = boundsSize.y - Mathf.Min(bottomDistance, boundsSize.y);
|
||||
var obsticleDepth = Mathf.Max(bottomDistance - boundsSize.y, 0);
|
||||
|
||||
//Debug.DrawLine(forwardTop + Vector2.up * Vector2.up, forwardTop + Vector2.down * bottomDistance, Color.red);
|
||||
Debug.DrawLine(forwardTop + Vector2.down * boundsSize.y, forwardTop + Vector2.down * boundsSize.y + Vector2.up * obsticleHeight, Color.green);
|
||||
|
||||
if (groundAngle <= settings.VaultMaxAngle &&
|
||||
currentAngle <= settings.VaultFromAngleMax &&
|
||||
totalSize > boundsSize.y &&
|
||||
!tweenSystem.HasTween(entity))
|
||||
{
|
||||
if (obsticleHeight <= settings.StepAssistMaxHeight)
|
||||
{
|
||||
rigidbody.AddForce(Vector2.up * obsticleHeight * rigidbody.mass * 2, ForceMode2D.Impulse);
|
||||
snapMultiply = 0;
|
||||
}
|
||||
else if (true)
|
||||
{
|
||||
var target = Vector2.zero;
|
||||
var jumpedFlag = false;
|
||||
|
||||
if (obsticleHeight >= settings.VaultObsicleRange.x && obsticleHeight <= settings.VaultObsicleRange.y && actor.Grounded)
|
||||
{
|
||||
target = forwardTop + Vector2.down * Mathf.Min(bottomDistance, boundsSize.y);
|
||||
jumpedFlag = true;
|
||||
}
|
||||
|
||||
if (jumpedFlag)
|
||||
{
|
||||
var vel = TrajectoryMath.CalculateVelocityWithHeight(
|
||||
rigidbody.position,
|
||||
target,
|
||||
Mathf.Abs(rigidbody.position.y - target.y) + 0.5f,
|
||||
settings.FallGravityMultiply);
|
||||
//var vel = TrajectoryMath.CalculateVelocity(rigidbody.position, target,settings.ObsticleJumpTime, settings.FallGravityMultiply);
|
||||
var velDelta = vel - rigidbody.velocity;
|
||||
rigidbody.AddForce(velDelta * rigidbody.mass, ForceMode2D.Impulse);
|
||||
//PostUpdateCommands.StartTween(entity,0.5f,EaseType.linear,TweenFollowPath.Build(new []{rigidbody.position,rigidbody.position + new Vector2(0,target.y - rigidbody.position.y),target},Space.World));
|
||||
animation.Triggers |= AnimationTriggerType.JumpObsticle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue