You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

343 lines
13 KiB
C#

3 weeks ago
using System;
using UnityEngine;
namespace Fusion.Addons.SimpleKCC
{
internal static class StepUpProcessor
{
private static bool _clearDynamicVelocityOnEnd = true;
private static KCCOverlapInfo _overlapInfo = new KCCOverlapInfo();
private static KCCShapeCastInfo _shapeCastInfo = new KCCShapeCastInfo();
public static void AfterMoveStep(KCC kcc, KCCData data, KCCOverlapInfo baseOverlapInfo)
{
KCCSettings settings = kcc.Settings;
if (settings.StepHeight <= 0f)
{
return;
}
if (data.JumpFrames > 0 || data.HasTeleported)
{
ProcessStepUpResult(kcc, data, isSteppingUp: false);
return;
}
bool flag = false;
if (HasCollisionsWithinExtent(baseOverlapInfo, (ECollisionType)14))
{
flag = true;
}
else
{
float magnitude = (data.DesiredPosition - data.BasePosition).magnitude;
if (magnitude > 0.001f && (data.TargetPosition - data.BasePosition).magnitude / magnitude < settings.StepMinPushBack)
{
flag = true;
}
}
if (!flag)
{
ProcessStepUpResult(kcc, data, isSteppingUp: false);
return;
}
Vector3 basePosition = data.BasePosition;
Vector3 desiredPosition = data.DesiredPosition;
Vector3 vector = data.TargetPosition;
Vector3 vector2 = desiredPosition - basePosition;
Vector3 vector3 = Vector3.Normalize(vector2);
if (vector3 == default(Vector3))
{
ProcessStepUpResult(kcc, data, isSteppingUp: false);
return;
}
if (Vector3.Dot(vector3, Vector3.down) >= 0.9f)
{
ProcessStepUpResult(kcc, data, isSteppingUp: false);
return;
}
Vector3 vector4 = vector - desiredPosition;
float magnitude2 = vector4.magnitude;
Vector3 vector5 = ((magnitude2 > 0.001f) ? (vector4 / magnitude2) : (-vector3));
if (Vector3.Dot(vector3, vector5) >= 0f)
{
ProcessStepUpResult(kcc, data, isSteppingUp: false);
return;
}
Vector3 vector6 = Vector3.Normalize(vector3.OnlyXZ());
Vector3 vector7 = Vector3.Normalize(-vector5.OnlyXZ());
Vector3 vector8 = Vector3.Normalize(vector6 + vector7);
if (Vector3.Dot(vector6, vector7) < 0.1f)
{
ProcessStepUpResult(kcc, data, isSteppingUp: false);
return;
}
if (!vector5.IsZero() && !HasCollisionsWithinExtent(baseOverlapInfo, ECollisionType.Slope))
{
Ray ray = new Ray(basePosition - vector2 * 2f, vector3);
if (new Plane(vector5, vector).Raycast(ray, out var enter))
{
vector = ray.GetPoint(enter);
}
}
float num = kcc.Settings.Radius - kcc.Settings.Extent;
Vector3 vector9 = vector + new Vector3(0f, settings.StepHeight, 0f);
if (kcc.CapsuleOverlap(_overlapInfo, vector9, num, kcc.Settings.Height, QueryTriggerInteraction.Ignore))
{
ProcessStepUpResult(kcc, data, isSteppingUp: false);
return;
}
vector9 += vector8 * settings.StepDepth;
if (kcc.CapsuleOverlap(_overlapInfo, vector9, num, kcc.Settings.Height, QueryTriggerInteraction.Ignore))
{
ProcessStepUpResult(kcc, data, isSteppingUp: false);
return;
}
float num2 = settings.StepHeight;
bool flag2 = false;
Vector3 lhs = default(Vector3);
if (settings.StepGroundCheckRadiusScale < 1f)
{
num = kcc.Settings.Radius * settings.StepGroundCheckRadiusScale;
vector9 += vector8 * (kcc.Settings.Radius - kcc.Settings.Extent - num);
}
if (kcc.SphereCast(_shapeCastInfo, vector9 + new Vector3(0f, kcc.Settings.Radius, 0f), num, Vector3.down, num2 + kcc.Settings.Radius, QueryTriggerInteraction.Ignore, trackInitialOverlaps: false))
{
Vector3 vector10 = new Vector3(0f, float.MinValue, 0f);
int i = 0;
for (int colliderHitCount = _shapeCastInfo.ColliderHitCount; i < colliderHitCount; i++)
{
RaycastHit raycastHit = _shapeCastInfo.ColliderHits[i].RaycastHit;
Vector3 point = raycastHit.point;
if (point.y > vector.y && point.y > vector10.y)
{
vector10 = point;
lhs = raycastHit.normal;
flag2 = true;
}
}
if (flag2)
{
num2 = Mathf.Clamp(vector10.y - vector.y, 0f, settings.StepHeight);
}
}
if (settings.StepRequireGroundTarget && !data.IsSteppingUp && !data.WasSteppingUp && flag2)
{
float num3 = Mathf.Cos(Mathf.Clamp(data.MaxGroundAngle, 0f, 90f) * (MathF.PI / 180f));
if (Vector3.Dot(lhs, Vector3.up) < num3)
{
ProcessStepUpResult(kcc, data, isSteppingUp: false);
return;
}
}
float num4 = Vector3.Distance(basePosition, desiredPosition);
float num5 = Vector3.Distance(basePosition, vector);
float num6 = Mathf.Clamp((num4 - num5) * settings.StepSpeed, 0f, num2);
num6 *= Mathf.Clamp01(Vector3.Dot(vector3, -vector5));
data.TargetPosition = vector + new Vector3(0f, num6, 0f);
data.IsGrounded = true;
data.GroundNormal = Vector3.up;
data.GroundDistance = kcc.Settings.Extent;
data.GroundPosition = data.TargetPosition;
data.GroundTangent = data.TransformDirection;
ProcessStepUpResult(kcc, data, isSteppingUp: true);
kcc.UpdateHits(baseOverlapInfo, EKCCHitsOverlapQuery.Default);
}
private static void ProcessStepUpResult(KCC kcc, KCCData data, bool isSteppingUp)
{
data.IsSteppingUp = isSteppingUp;
if (!data.IsSteppingUp && data.WasSteppingUp && _clearDynamicVelocityOnEnd)
{
data.DynamicVelocity = default(Vector3);
}
}
public static void AfterMoveStep(KCCOffline kcc, KCCData data, KCCOverlapInfo baseOverlapInfo)
{
KCCSettings settings = kcc.Settings;
if (settings.StepHeight <= 0f)
{
return;
}
if (data.JumpFrames > 0 || data.HasTeleported)
{
ProcessStepUpResult(kcc, data, isSteppingUp: false);
return;
}
bool flag = false;
if (HasCollisionsWithinExtent(baseOverlapInfo, (ECollisionType)14))
{
flag = true;
}
else
{
float magnitude = (data.DesiredPosition - data.BasePosition).magnitude;
if (magnitude > 0.001f && (data.TargetPosition - data.BasePosition).magnitude / magnitude < settings.StepMinPushBack)
{
flag = true;
}
}
if (!flag)
{
ProcessStepUpResult(kcc, data, isSteppingUp: false);
return;
}
Vector3 basePosition = data.BasePosition;
Vector3 desiredPosition = data.DesiredPosition;
Vector3 vector = data.TargetPosition;
Vector3 vector2 = desiredPosition - basePosition;
Vector3 vector3 = Vector3.Normalize(vector2);
if (vector3 == default(Vector3))
{
ProcessStepUpResult(kcc, data, isSteppingUp: false);
return;
}
if (Vector3.Dot(vector3, Vector3.down) >= 0.9f)
{
ProcessStepUpResult(kcc, data, isSteppingUp: false);
return;
}
Vector3 vector4 = vector - desiredPosition;
float magnitude2 = vector4.magnitude;
Vector3 vector5 = ((magnitude2 > 0.001f) ? (vector4 / magnitude2) : (-vector3));
if (Vector3.Dot(vector3, vector5) >= 0f)
{
ProcessStepUpResult(kcc, data, isSteppingUp: false);
return;
}
Vector3 vector6 = Vector3.Normalize(vector3.OnlyXZ());
Vector3 vector7 = Vector3.Normalize(-vector5.OnlyXZ());
Vector3 vector8 = Vector3.Normalize(vector6 + vector7);
if (Vector3.Dot(vector6, vector7) < 0.1f)
{
ProcessStepUpResult(kcc, data, isSteppingUp: false);
return;
}
if (!vector5.IsZero() && !HasCollisionsWithinExtent(baseOverlapInfo, ECollisionType.Slope))
{
Ray ray = new Ray(basePosition - vector2 * 2f, vector3);
if (new Plane(vector5, vector).Raycast(ray, out var enter))
{
vector = ray.GetPoint(enter);
}
}
float num = kcc.Settings.Radius - kcc.Settings.Extent;
Vector3 vector9 = vector + new Vector3(0f, settings.StepHeight, 0f);
if (kcc.CapsuleOverlap(_overlapInfo, vector9, num, kcc.Settings.Height, QueryTriggerInteraction.Ignore))
{
ProcessStepUpResult(kcc, data, isSteppingUp: false);
return;
}
vector9 += vector8 * settings.StepDepth;
if (kcc.CapsuleOverlap(_overlapInfo, vector9, num, kcc.Settings.Height, QueryTriggerInteraction.Ignore))
{
ProcessStepUpResult(kcc, data, isSteppingUp: false);
return;
}
float num2 = settings.StepHeight;
bool flag2 = false;
Vector3 lhs = default(Vector3);
if (settings.StepGroundCheckRadiusScale < 1f)
{
num = kcc.Settings.Radius * settings.StepGroundCheckRadiusScale;
vector9 += vector8 * (kcc.Settings.Radius - kcc.Settings.Extent - num);
}
if (kcc.SphereCast(_shapeCastInfo, vector9 + new Vector3(0f, kcc.Settings.Radius, 0f), num, Vector3.down, num2 + kcc.Settings.Radius, QueryTriggerInteraction.Ignore, trackInitialOverlaps: false))
{
Vector3 vector10 = new Vector3(0f, float.MinValue, 0f);
int i = 0;
for (int colliderHitCount = _shapeCastInfo.ColliderHitCount; i < colliderHitCount; i++)
{
RaycastHit raycastHit = _shapeCastInfo.ColliderHits[i].RaycastHit;
Vector3 point = raycastHit.point;
if (point.y > vector.y && point.y > vector10.y)
{
vector10 = point;
lhs = raycastHit.normal;
flag2 = true;
}
}
if (flag2)
{
num2 = Mathf.Clamp(vector10.y - vector.y, 0f, settings.StepHeight);
}
}
if (settings.StepRequireGroundTarget && !data.IsSteppingUp && !data.WasSteppingUp && flag2)
{
float num3 = Mathf.Cos(Mathf.Clamp(data.MaxGroundAngle, 0f, 90f) * (MathF.PI / 180f));
if (Vector3.Dot(lhs, Vector3.up) < num3)
{
ProcessStepUpResult(kcc, data, isSteppingUp: false);
return;
}
}
float num4 = Vector3.Distance(basePosition, desiredPosition);
float num5 = Vector3.Distance(basePosition, vector);
float num6 = Mathf.Clamp((num4 - num5) * settings.StepSpeed, 0f, num2);
num6 *= Mathf.Clamp01(Vector3.Dot(vector3, -vector5));
data.TargetPosition = vector + new Vector3(0f, num6, 0f);
data.IsGrounded = true;
data.GroundNormal = Vector3.up;
data.GroundDistance = kcc.Settings.Extent;
data.GroundPosition = data.TargetPosition;
data.GroundTangent = data.TransformDirection;
ProcessStepUpResult(kcc, data, isSteppingUp: true);
kcc.UpdateHits(baseOverlapInfo, EKCCHitsOverlapQuery.Default);
}
private static void ProcessStepUpResult(KCCOffline kcc, KCCData data, bool isSteppingUp)
{
data.IsSteppingUp = isSteppingUp;
if (!data.IsSteppingUp && data.WasSteppingUp && _clearDynamicVelocityOnEnd)
{
data.DynamicVelocity = default(Vector3);
}
}
private static bool HasCollisionsWithinExtent(KCCOverlapInfo overlapInfo, ECollisionType collisionTypes)
{
for (int i = 0; i < overlapInfo.ColliderHitCount; i++)
{
KCCOverlapHit kCCOverlapHit = overlapInfo.ColliderHits[i];
if (kCCOverlapHit.IsWithinExtent && (collisionTypes & kCCOverlapHit.CollisionType) != 0)
{
return true;
}
}
return false;
}
}
}