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#
343 lines
13 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|