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.
2221 lines
86 KiB
C#
2221 lines
86 KiB
C#
2 weeks ago
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Runtime.CompilerServices;
|
||
|
using Unity.Profiling;
|
||
|
using UnityEngine;
|
||
|
|
||
|
namespace Fusion.Addons.SimpleKCC
|
||
|
{
|
||
|
[DisallowMultipleComponent]
|
||
|
[RequireComponent(typeof(Rigidbody))]
|
||
|
public sealed class KCC : NetworkTRSP, IAfterSpawned, IAfterClientPredictionReset, IBeforeTick, IAfterTick
|
||
|
{
|
||
|
internal const int CACHE_SIZE = 64;
|
||
|
|
||
|
internal const int HISTORY_SIZE = 60;
|
||
|
|
||
|
[SerializeField]
|
||
|
private KCCSettings _settings = new KCCSettings();
|
||
|
|
||
|
private Transform _transform;
|
||
|
|
||
|
private Rigidbody _rigidbody;
|
||
|
|
||
|
private bool _isSpawned;
|
||
|
|
||
|
private bool _isInFixedUpdate;
|
||
|
|
||
|
private KCCCollider _collider = new KCCCollider();
|
||
|
|
||
|
private KCCData _fixedData = new KCCData();
|
||
|
|
||
|
private KCCData _renderData = new KCCData();
|
||
|
|
||
|
private KCCData[] _historyData = new KCCData[60];
|
||
|
|
||
|
private KCCSettings _defaultSettings = new KCCSettings();
|
||
|
|
||
|
private KCCOverlapInfo _extendedOverlapInfo = new KCCOverlapInfo(64);
|
||
|
|
||
|
private KCCOverlapInfo _trackOverlapInfo = new KCCOverlapInfo(64);
|
||
|
|
||
|
private List<Collider> _childColliders = new List<Collider>();
|
||
|
|
||
|
private RaycastHit[] _raycastHits = new RaycastHit[64];
|
||
|
|
||
|
private Collider[] _hitColliders = new Collider[64];
|
||
|
|
||
|
private Collider[] _addColliders = new Collider[64];
|
||
|
|
||
|
private Collider[] _removeColliders = new Collider[64];
|
||
|
|
||
|
private KCCResolver _resolver = new KCCResolver(64);
|
||
|
|
||
|
private float _lastRenderTime;
|
||
|
|
||
|
private Vector3 _lastRenderPosition;
|
||
|
|
||
|
private Vector3 _lastAntiJitterPosition;
|
||
|
|
||
|
private Vector3 _predictionError;
|
||
|
|
||
|
private static ProfilerMarker _fixedUpdateMarker = new ProfilerMarker("KCC.FixedUpdate");
|
||
|
|
||
|
private static ProfilerMarker _renderUpdateMarker = new ProfilerMarker("KCC.RenderUpdate");
|
||
|
|
||
|
private static ProfilerMarker _restoreStateMarker = new ProfilerMarker("KCC.RestoreState");
|
||
|
|
||
|
private static ProfilerMarker _afterTickMarker = new ProfilerMarker("KCC.AfterTick");
|
||
|
|
||
|
public Func<KCC, Collider, bool> ResolveCollision;
|
||
|
|
||
|
private KCCNetworkContext _networkContext;
|
||
|
|
||
|
private IKCCNetworkProperty[] _networkProperties;
|
||
|
|
||
|
private int _interpolationTick;
|
||
|
|
||
|
private int _interpolationAttempts;
|
||
|
|
||
|
public override int? DynamicWordCount => GetNetworkDataWordCount();
|
||
|
|
||
|
internal bool IsSpawned => _isSpawned;
|
||
|
|
||
|
public bool IsActive => Data.IsActive;
|
||
|
|
||
|
public Vector3 Position => Data.TargetPosition;
|
||
|
|
||
|
public Quaternion LookRotation => Data.LookRotation;
|
||
|
|
||
|
public Vector3 LookDirection => Data.LookDirection;
|
||
|
|
||
|
public Quaternion TransformRotation => Data.TransformRotation;
|
||
|
|
||
|
public Vector3 TransformDirection => Data.TransformDirection;
|
||
|
|
||
|
public float RealSpeed => Data.RealSpeed;
|
||
|
|
||
|
public Vector3 RealVelocity => Data.RealVelocity;
|
||
|
|
||
|
public bool HasJumped => Data.HasJumped;
|
||
|
|
||
|
public bool IsGrounded => Data.IsGrounded;
|
||
|
|
||
|
public Vector3 GroundNormal => Data.GroundNormal;
|
||
|
|
||
|
internal new KCCData Data
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
if (!IsInFixedUpdate)
|
||
|
{
|
||
|
return _renderData;
|
||
|
}
|
||
|
|
||
|
return _fixedData;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal KCCData FixedData => _fixedData;
|
||
|
|
||
|
internal KCCData RenderData => _renderData;
|
||
|
|
||
|
public KCCSettings Settings => _settings;
|
||
|
|
||
|
public Transform Transform => _transform;
|
||
|
|
||
|
public CapsuleCollider Collider => _collider.Collider;
|
||
|
|
||
|
public Rigidbody Rigidbody => _rigidbody;
|
||
|
|
||
|
internal bool IsInFixedUpdate
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
if (!_isInFixedUpdate)
|
||
|
{
|
||
|
if (_isSpawned)
|
||
|
{
|
||
|
return base.Runner.Stage != (SimulationStages)0;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal bool IsInForwardUpdate
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
if (_isSpawned && base.Runner.Stage != 0)
|
||
|
{
|
||
|
return base.Runner.IsForward;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal bool IsInResimulationUpdate
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
if (_isSpawned && base.Runner.Stage != 0)
|
||
|
{
|
||
|
return base.Runner.IsResimulation;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal Vector3 PredictionError => _predictionError;
|
||
|
|
||
|
private event Action<KCC> _onSpawn;
|
||
|
|
||
|
internal void SynchronizeTransform(bool synchronizePosition, bool synchronizeRotation, bool allowAntiJitter = true)
|
||
|
{
|
||
|
if (IsInFixedUpdate)
|
||
|
{
|
||
|
allowAntiJitter = false;
|
||
|
}
|
||
|
|
||
|
SynchronizeTransform(Data, synchronizePosition, synchronizeRotation, allowAntiJitter);
|
||
|
}
|
||
|
|
||
|
public void RefreshChildColliders()
|
||
|
{
|
||
|
_childColliders.Clear();
|
||
|
GetComponentsInChildren(includeInactive: true, _childColliders);
|
||
|
int num = 0;
|
||
|
int num2 = _childColliders.Count - 1;
|
||
|
while (num <= num2)
|
||
|
{
|
||
|
Collider collider = _childColliders[num];
|
||
|
if (collider.isTrigger || collider == _collider.Collider)
|
||
|
{
|
||
|
_childColliders[num] = _childColliders[num2];
|
||
|
_childColliders.RemoveAt(num2);
|
||
|
num2--;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
num++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal KCCData GetHistoryData(int tick)
|
||
|
{
|
||
|
if (tick < 0)
|
||
|
{
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
KCCData kCCData = _historyData[tick % 60];
|
||
|
if (kCCData != null && kCCData.Tick == tick)
|
||
|
{
|
||
|
return kCCData;
|
||
|
}
|
||
|
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
internal void InvokeOnSpawn(Action<KCC> callback)
|
||
|
{
|
||
|
if (_isSpawned)
|
||
|
{
|
||
|
callback(this);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
_onSpawn -= callback;
|
||
|
_onSpawn += callback;
|
||
|
}
|
||
|
|
||
|
internal void ManualFixedUpdate()
|
||
|
{
|
||
|
if (_isSpawned)
|
||
|
{
|
||
|
_fixedUpdateMarker.Begin();
|
||
|
OnFixedUpdateInternal();
|
||
|
_fixedUpdateMarker.End();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void Awake()
|
||
|
{
|
||
|
_transform = base.transform;
|
||
|
_rigidbody = GetComponent<Rigidbody>();
|
||
|
_rigidbody.isKinematic = true;
|
||
|
RefreshCollider();
|
||
|
}
|
||
|
|
||
|
private void OnDestroy()
|
||
|
{
|
||
|
SetDefaults(cleanup: true);
|
||
|
}
|
||
|
|
||
|
private void OnDrawGizmosSelected()
|
||
|
{
|
||
|
if (_settings != null)
|
||
|
{
|
||
|
float num = Mathf.Max(0.01f, _settings.Radius);
|
||
|
float num2 = Mathf.Max(num * 2f, _settings.Height);
|
||
|
Vector3 position = base.transform.position;
|
||
|
Color color = Gizmos.color;
|
||
|
Vector3 vector = position + Vector3.up * num;
|
||
|
Vector3 vector2 = position + Vector3.up * (num2 - num);
|
||
|
Vector3 vector3 = Vector3.forward * num;
|
||
|
Vector3 vector4 = Vector3.back * num;
|
||
|
Vector3 vector5 = Vector3.left * num;
|
||
|
Vector3 vector6 = Vector3.right * num;
|
||
|
Gizmos.color = Color.green;
|
||
|
Gizmos.DrawWireSphere(vector, num);
|
||
|
Gizmos.DrawWireSphere(vector2, num);
|
||
|
Gizmos.DrawLine(vector + vector3, vector2 + vector3);
|
||
|
Gizmos.DrawLine(vector + vector4, vector2 + vector4);
|
||
|
Gizmos.DrawLine(vector + vector5, vector2 + vector5);
|
||
|
Gizmos.DrawLine(vector + vector6, vector2 + vector6);
|
||
|
if (_settings.Extent > 0f)
|
||
|
{
|
||
|
float radius = num + _settings.Extent;
|
||
|
Gizmos.color = Color.yellow;
|
||
|
Gizmos.DrawWireSphere(vector, radius);
|
||
|
Gizmos.DrawWireSphere(vector2, radius);
|
||
|
}
|
||
|
|
||
|
Gizmos.color = color;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override void Spawned()
|
||
|
{
|
||
|
if (_isSpawned)
|
||
|
{
|
||
|
throw new InvalidOperationException("[" + base.name + "] KCC is already spawned!");
|
||
|
}
|
||
|
|
||
|
_defaultSettings.CopyFromOther(_settings);
|
||
|
SetDefaults(cleanup: false);
|
||
|
_isSpawned = true;
|
||
|
_isInFixedUpdate = true;
|
||
|
KCCUtility.GetClampedLookRotationAngles(_transform.rotation, out var pitch, out var yaw);
|
||
|
_fixedData = new KCCData();
|
||
|
_fixedData.Frame = Time.frameCount;
|
||
|
_fixedData.Tick = base.Runner.Tick.Raw;
|
||
|
_fixedData.Time = base.Runner.SimulationTime;
|
||
|
_fixedData.DeltaTime = base.Runner.DeltaTime;
|
||
|
_fixedData.UpdateDeltaTime = _fixedData.DeltaTime;
|
||
|
_fixedData.Gravity = Physics.gravity;
|
||
|
_fixedData.MaxGroundAngle = 60f;
|
||
|
_fixedData.MaxWallAngle = 5f;
|
||
|
_fixedData.MaxHangAngle = 30f;
|
||
|
_fixedData.BasePosition = _transform.position;
|
||
|
_fixedData.DesiredPosition = _transform.position;
|
||
|
_fixedData.TargetPosition = _transform.position;
|
||
|
_fixedData.LookPitch = pitch;
|
||
|
_fixedData.LookYaw = yaw;
|
||
|
if (!base.Object.HasStateAuthority)
|
||
|
{
|
||
|
ReadNetworkData();
|
||
|
SynchronizeTransform(_fixedData, synchronizePosition: true, synchronizeRotation: true, allowAntiJitter: false);
|
||
|
}
|
||
|
|
||
|
_renderData = new KCCData();
|
||
|
_renderData.CopyFromOther(_fixedData);
|
||
|
_lastRenderPosition = _renderData.TargetPosition;
|
||
|
_lastAntiJitterPosition = _renderData.TargetPosition;
|
||
|
RefreshCollider();
|
||
|
RefreshChildColliders();
|
||
|
if (this._onSpawn != null)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
this._onSpawn(this);
|
||
|
}
|
||
|
catch (Exception exception)
|
||
|
{
|
||
|
Debug.LogException(exception);
|
||
|
}
|
||
|
|
||
|
this._onSpawn = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override void Despawned(NetworkRunner runner, bool hasState)
|
||
|
{
|
||
|
if (_isSpawned)
|
||
|
{
|
||
|
SetDefaults(cleanup: true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override void Render()
|
||
|
{
|
||
|
_renderUpdateMarker.Begin();
|
||
|
OnRenderUpdateInternal();
|
||
|
_renderUpdateMarker.End();
|
||
|
}
|
||
|
|
||
|
void IAfterSpawned.AfterSpawned()
|
||
|
{
|
||
|
_renderData.CopyFromOther(_fixedData);
|
||
|
if (base.Object.IsInSimulation)
|
||
|
{
|
||
|
WriteNetworkData();
|
||
|
}
|
||
|
|
||
|
_isInFixedUpdate = false;
|
||
|
}
|
||
|
|
||
|
void IAfterClientPredictionReset.AfterClientPredictionReset()
|
||
|
{
|
||
|
int num = base.Runner.LatestServerTick;
|
||
|
_restoreStateMarker.Begin();
|
||
|
KCCData kCCData = _historyData[num % 60];
|
||
|
if (kCCData != null && kCCData.Tick == num)
|
||
|
{
|
||
|
_fixedData.CopyFromOther(kCCData);
|
||
|
_fixedData.Frame = Time.frameCount;
|
||
|
}
|
||
|
|
||
|
ReadNetworkData();
|
||
|
if (kCCData != null)
|
||
|
{
|
||
|
RestoreHistoryData(kCCData);
|
||
|
}
|
||
|
|
||
|
RefreshCollider();
|
||
|
if (_fixedData.IsActive)
|
||
|
{
|
||
|
SynchronizeTransform(_fixedData, synchronizePosition: true, synchronizeRotation: true, allowAntiJitter: false);
|
||
|
}
|
||
|
|
||
|
_restoreStateMarker.End();
|
||
|
}
|
||
|
|
||
|
void IBeforeTick.BeforeTick()
|
||
|
{
|
||
|
_isInFixedUpdate = true;
|
||
|
_fixedData.Frame = Time.frameCount;
|
||
|
_fixedData.Tick = base.Runner.Tick.Raw;
|
||
|
_fixedData.Alpha = 0f;
|
||
|
_fixedData.Time = base.Runner.SimulationTime;
|
||
|
_fixedData.DeltaTime = base.Runner.DeltaTime;
|
||
|
_fixedData.UpdateDeltaTime = _fixedData.DeltaTime;
|
||
|
}
|
||
|
|
||
|
void IAfterTick.AfterTick()
|
||
|
{
|
||
|
_afterTickMarker.Begin();
|
||
|
PublishFixedData();
|
||
|
WriteNetworkData();
|
||
|
_isInFixedUpdate = false;
|
||
|
_afterTickMarker.End();
|
||
|
}
|
||
|
|
||
|
private void OnFixedUpdateInternal()
|
||
|
{
|
||
|
if (!IsInFixedUpdate)
|
||
|
{
|
||
|
throw new InvalidOperationException("[" + base.name + "] KCC fixed update called from render update! This is not allowed.");
|
||
|
}
|
||
|
|
||
|
RefreshCollider();
|
||
|
MovePredicted(_fixedData);
|
||
|
if (_fixedData.IsActive)
|
||
|
{
|
||
|
SynchronizeTransform(_fixedData, synchronizePosition: true, synchronizeRotation: true, allowAntiJitter: false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void OnRenderUpdateInternal()
|
||
|
{
|
||
|
if (IsInFixedUpdate)
|
||
|
{
|
||
|
throw new InvalidOperationException("[" + base.name + "] KCC render update called from fixed update! This is not allowed.");
|
||
|
}
|
||
|
|
||
|
int frameCount = Time.frameCount;
|
||
|
float deltaTime = base.Runner.DeltaTime;
|
||
|
_renderData.Frame = frameCount;
|
||
|
if (base.Object.IsInSimulation)
|
||
|
{
|
||
|
_renderData.Tick = base.Runner.Tick;
|
||
|
_renderData.Alpha = base.Runner.LocalAlpha;
|
||
|
float num = _renderData.Time;
|
||
|
_renderData.Time = base.Runner.SimulationTime + _renderData.Alpha * deltaTime;
|
||
|
_renderData.Tick--;
|
||
|
_renderData.Time -= deltaTime;
|
||
|
if (_renderData.Frame == _fixedData.Frame)
|
||
|
{
|
||
|
num -= deltaTime;
|
||
|
}
|
||
|
|
||
|
_renderData.DeltaTime = _renderData.Time - num;
|
||
|
_renderData.UpdateDeltaTime = _renderData.DeltaTime;
|
||
|
UpdatePredictionError();
|
||
|
MoveInterpolated(_renderData);
|
||
|
if (_renderData.IsActive)
|
||
|
{
|
||
|
SynchronizeTransform(_renderData, synchronizePosition: true, synchronizeRotation: true, allowAntiJitter: true);
|
||
|
}
|
||
|
}
|
||
|
else if (_settings.ProxyInterpolationMode == EKCCInterpolationMode.Transform)
|
||
|
{
|
||
|
InterpolateNetworkTransform();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_fixedData.Frame = frameCount;
|
||
|
_fixedData.Tick = base.Object.LastReceiveTick;
|
||
|
_fixedData.Alpha = 1f;
|
||
|
_fixedData.Time = (float)_fixedData.Tick * deltaTime;
|
||
|
_fixedData.DeltaTime = deltaTime;
|
||
|
_fixedData.UpdateDeltaTime = deltaTime;
|
||
|
ReadNetworkData();
|
||
|
InterpolateNetworkData(RenderSource.Interpolated, RenderTimeframe.Remote);
|
||
|
if (_renderData.IsActive)
|
||
|
{
|
||
|
RefreshCollider();
|
||
|
SynchronizeTransform(_renderData, synchronizePosition: true, synchronizeRotation: true, allowAntiJitter: false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
_lastRenderPosition = _renderData.TargetPosition;
|
||
|
_lastRenderTime = _renderData.Time;
|
||
|
}
|
||
|
|
||
|
private void UpdatePredictionError()
|
||
|
{
|
||
|
if (_renderData.Frame == _fixedData.Frame)
|
||
|
{
|
||
|
KCCData kCCData = GetHistoryData(_renderData.Tick);
|
||
|
if (kCCData != null && _lastRenderTime <= kCCData.Time)
|
||
|
{
|
||
|
for (int i = 0; i < 5; i++)
|
||
|
{
|
||
|
KCCData historyData = GetHistoryData(kCCData.Tick - 1);
|
||
|
if (historyData == null)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (_lastRenderTime >= historyData.Time)
|
||
|
{
|
||
|
if (kCCData.HasTeleported || historyData.HasTeleported)
|
||
|
{
|
||
|
_predictionError = default(Vector3);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
float num = kCCData.Time - historyData.Time;
|
||
|
if (num <= 1E-06f)
|
||
|
{
|
||
|
_predictionError = default(Vector3);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
float t = (_lastRenderTime - historyData.Time) / num;
|
||
|
Vector3 vector = Vector3.Lerp(historyData.TargetPosition, kCCData.TargetPosition, t);
|
||
|
_predictionError = _lastRenderPosition - vector;
|
||
|
if (_predictionError.sqrMagnitude >= _settings.TeleportThreshold * _settings.TeleportThreshold)
|
||
|
{
|
||
|
_predictionError = default(Vector3);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
_predictionError = Vector3.Lerp(_predictionError, Vector3.zero, _settings.PredictionCorrectionSpeed * Time.deltaTime);
|
||
|
_renderData.BasePosition += _predictionError;
|
||
|
_renderData.DesiredPosition += _predictionError;
|
||
|
_renderData.TargetPosition += _predictionError;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
kCCData = historyData;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (_predictionError.IsAlmostZero(1E-06f))
|
||
|
{
|
||
|
_predictionError = default(Vector3);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
_renderData.BasePosition -= _predictionError;
|
||
|
_renderData.DesiredPosition -= _predictionError;
|
||
|
_renderData.TargetPosition -= _predictionError;
|
||
|
_predictionError = Vector3.Lerp(_predictionError, Vector3.zero, _settings.PredictionCorrectionSpeed * Time.deltaTime);
|
||
|
_renderData.BasePosition += _predictionError;
|
||
|
_renderData.DesiredPosition += _predictionError;
|
||
|
_renderData.TargetPosition += _predictionError;
|
||
|
}
|
||
|
|
||
|
private void MovePredicted(KCCData data)
|
||
|
{
|
||
|
float time = data.Time;
|
||
|
float deltaTime = data.DeltaTime;
|
||
|
Vector3 targetPosition = data.TargetPosition;
|
||
|
Vector3 targetPosition2 = data.TargetPosition;
|
||
|
bool isGrounded = data.IsGrounded;
|
||
|
bool isSteppingUp = data.IsSteppingUp;
|
||
|
bool isSnappingToGround = data.IsSnappingToGround;
|
||
|
data.DeltaTime = deltaTime;
|
||
|
data.BasePosition = targetPosition;
|
||
|
data.DesiredPosition = targetPosition2;
|
||
|
if (!data.IsActive)
|
||
|
{
|
||
|
data.ClearTransientProperties();
|
||
|
ForceRemoveAllHits(data);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
SetBaseProperties(data);
|
||
|
if (!data.IsActive)
|
||
|
{
|
||
|
data.ClearTransientProperties();
|
||
|
ForceRemoveAllHits(data);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
deltaTime = data.DeltaTime;
|
||
|
targetPosition = data.BasePosition;
|
||
|
if (deltaTime < KCCSettings.ExtrapolationDeltaTimeThreshold)
|
||
|
{
|
||
|
Vector3 vector = data.DesiredVelocity;
|
||
|
if (data.RealVelocity.sqrMagnitude <= vector.sqrMagnitude)
|
||
|
{
|
||
|
vector = data.RealVelocity;
|
||
|
}
|
||
|
|
||
|
targetPosition2 = targetPosition + vector * deltaTime;
|
||
|
data.BasePosition = targetPosition;
|
||
|
data.DesiredPosition = targetPosition2;
|
||
|
data.TargetPosition = targetPosition2;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
EnvironmentProcessor.SetDynamicVelocity(this, data);
|
||
|
ForceRemoveAllHits(data);
|
||
|
float num = Mathf.Clamp01(deltaTime);
|
||
|
Vector3 vector2 = data.DesiredVelocity * num + data.ExternalDelta;
|
||
|
targetPosition2 = (data.DesiredPosition = data.BasePosition + vector2);
|
||
|
data.TargetPosition = data.BasePosition;
|
||
|
data.ExternalDelta = default(Vector3);
|
||
|
bool flag = false;
|
||
|
float num2 = Mathf.Clamp(_settings.CCDRadiusMultiplier, 0.25f, 0.75f);
|
||
|
float num3 = _settings.Radius * (num2 + 0.1f);
|
||
|
float num4 = _settings.Radius * num2;
|
||
|
Vector3 targetPosition3 = data.TargetPosition;
|
||
|
while (!flag && !data.HasTeleported)
|
||
|
{
|
||
|
data.BasePosition = data.TargetPosition;
|
||
|
float num5 = num;
|
||
|
Vector3 vector3 = vector2;
|
||
|
float magnitude = vector3.magnitude;
|
||
|
if (magnitude > num3)
|
||
|
{
|
||
|
float num6 = num4 / magnitude;
|
||
|
num5 *= num6;
|
||
|
vector3 *= num6;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
flag = true;
|
||
|
}
|
||
|
|
||
|
num -= num5;
|
||
|
vector2 -= vector3;
|
||
|
if (num <= 0f)
|
||
|
{
|
||
|
num = 0f;
|
||
|
}
|
||
|
|
||
|
data.Time = time - num;
|
||
|
data.DeltaTime = num5;
|
||
|
data.DesiredPosition = data.BasePosition + vector3;
|
||
|
data.TargetPosition = data.DesiredPosition;
|
||
|
data.WasGrounded = data.IsGrounded;
|
||
|
data.WasSteppingUp = data.IsSteppingUp;
|
||
|
data.WasSnappingToGround = data.IsSnappingToGround;
|
||
|
ProcessMoveStep(data);
|
||
|
if (!data.HasTeleported)
|
||
|
{
|
||
|
targetPosition3 = data.TargetPosition;
|
||
|
}
|
||
|
|
||
|
if (data.HasTeleported)
|
||
|
{
|
||
|
UpdateHits(data, null, EKCCHitsOverlapQuery.New);
|
||
|
}
|
||
|
|
||
|
if (flag && !data.ExternalDelta.IsZero())
|
||
|
{
|
||
|
vector2 += data.ExternalDelta;
|
||
|
data.ExternalDelta = default(Vector3);
|
||
|
flag = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
data.Time = time;
|
||
|
data.DeltaTime = deltaTime;
|
||
|
data.BasePosition = targetPosition;
|
||
|
data.DesiredPosition = targetPosition2;
|
||
|
data.WasGrounded = isGrounded;
|
||
|
data.WasSteppingUp = isSteppingUp;
|
||
|
data.WasSnappingToGround = isSnappingToGround;
|
||
|
data.RealVelocity = (targetPosition3 - data.BasePosition) / data.DeltaTime;
|
||
|
data.RealSpeed = data.RealVelocity.magnitude;
|
||
|
Vector3 targetPosition4 = data.TargetPosition;
|
||
|
if (!data.TargetPosition.IsEqual(targetPosition4))
|
||
|
{
|
||
|
UpdateHits(data, null, EKCCHitsOverlapQuery.New);
|
||
|
}
|
||
|
|
||
|
targetPosition4 = data.TargetPosition;
|
||
|
if (!data.TargetPosition.IsEqual(targetPosition4))
|
||
|
{
|
||
|
UpdateHits(data, null, EKCCHitsOverlapQuery.New);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void MoveInterpolated(KCCData data)
|
||
|
{
|
||
|
if (!data.IsActive)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
KCCData fixedData = _fixedData;
|
||
|
if (fixedData.HasTeleported)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
KCCData historyData = GetHistoryData(fixedData.Tick - 1);
|
||
|
if (historyData != null)
|
||
|
{
|
||
|
float alpha = data.Alpha;
|
||
|
data.BasePosition = Vector3.Lerp(historyData.BasePosition, fixedData.BasePosition, alpha) + _predictionError;
|
||
|
data.DesiredPosition = Vector3.Lerp(historyData.DesiredPosition, fixedData.DesiredPosition, alpha) + _predictionError;
|
||
|
data.TargetPosition = Vector3.Lerp(historyData.TargetPosition, fixedData.TargetPosition, alpha) + _predictionError;
|
||
|
data.RealVelocity = Vector3.Lerp(historyData.RealVelocity, fixedData.RealVelocity, alpha);
|
||
|
data.RealSpeed = Mathf.Lerp(historyData.RealSpeed, fixedData.RealSpeed, alpha);
|
||
|
if (!_settings.ForcePredictedLookRotation)
|
||
|
{
|
||
|
data.LookPitch = Mathf.Lerp(historyData.LookPitch, fixedData.LookPitch, alpha);
|
||
|
data.LookYaw = KCCUtility.InterpolateRange(historyData.LookYaw, fixedData.LookYaw, -180f, 180f, alpha);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void SetBaseProperties(KCCData data)
|
||
|
{
|
||
|
data.HasTeleported = false;
|
||
|
data.MaxPenetrationSteps = _settings.MaxPenetrationSteps;
|
||
|
if (data.Frame == _fixedData.Frame)
|
||
|
{
|
||
|
data.JumpFrames = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void ProcessMoveStep(KCCData data)
|
||
|
{
|
||
|
data.IsGrounded = false;
|
||
|
data.IsSteppingUp = false;
|
||
|
data.IsSnappingToGround = false;
|
||
|
data.GroundNormal = default(Vector3);
|
||
|
data.GroundTangent = default(Vector3);
|
||
|
data.GroundPosition = default(Vector3);
|
||
|
data.GroundDistance = 0f;
|
||
|
data.GroundAngle = 0f;
|
||
|
ForceRemoveAllHits(data);
|
||
|
bool flag = data.JumpFrames > 0;
|
||
|
if ((int)_settings.CollisionLayerMask != 0 && _collider.IsSpawned)
|
||
|
{
|
||
|
float radius = _settings.Radius;
|
||
|
EKCCHitsOverlapQuery overlapQuery = EKCCHitsOverlapQuery.Default;
|
||
|
CapsuleOverlap(_extendedOverlapInfo, data, data.TargetPosition, _settings.Radius, _settings.Height, radius, _settings.CollisionLayerMask, QueryTriggerInteraction.Collide);
|
||
|
data.TargetPosition = ResolvePenetration(_extendedOverlapInfo, data, data.BasePosition, data.TargetPosition, !flag, data.MaxPenetrationSteps, 3, resolveTriggers: true);
|
||
|
UpdateHits(data, _extendedOverlapInfo, overlapQuery);
|
||
|
}
|
||
|
|
||
|
if (flag)
|
||
|
{
|
||
|
data.IsGrounded = false;
|
||
|
}
|
||
|
|
||
|
EnvironmentProcessor.AfterMoveStep(this, data);
|
||
|
StepUpProcessor.AfterMoveStep(this, data, _extendedOverlapInfo);
|
||
|
GroundSnapProcessor.AfterMoveStep(this, data, _extendedOverlapInfo);
|
||
|
}
|
||
|
|
||
|
private void SynchronizeTransform(KCCData data, bool synchronizePosition, bool synchronizeRotation, bool allowAntiJitter)
|
||
|
{
|
||
|
if (synchronizePosition)
|
||
|
{
|
||
|
Vector3 vector = data.TargetPosition;
|
||
|
_rigidbody.position = vector;
|
||
|
if (allowAntiJitter && !_settings.AntiJitterDistance.IsZero())
|
||
|
{
|
||
|
Vector3 vector2 = vector - _lastAntiJitterPosition;
|
||
|
if (vector2.sqrMagnitude < _settings.TeleportThreshold * _settings.TeleportThreshold)
|
||
|
{
|
||
|
vector = _lastAntiJitterPosition;
|
||
|
float num = Mathf.Abs(vector2.y);
|
||
|
if (num > 1E-06f)
|
||
|
{
|
||
|
vector.y += vector2.y * Mathf.Clamp01((num - _settings.AntiJitterDistance.y) / num);
|
||
|
}
|
||
|
|
||
|
Vector3 vector3 = vector2.OnlyXZ();
|
||
|
float num2 = Vector3.Magnitude(vector3);
|
||
|
if (num2 > 1E-06f)
|
||
|
{
|
||
|
vector += vector3 * Mathf.Clamp01((num2 - _settings.AntiJitterDistance.x) / num2);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
_lastAntiJitterPosition = vector;
|
||
|
}
|
||
|
|
||
|
if (synchronizeRotation)
|
||
|
{
|
||
|
_transform.SetPositionAndRotation(vector, data.TransformRotation);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_transform.position = vector;
|
||
|
}
|
||
|
}
|
||
|
else if (synchronizeRotation)
|
||
|
{
|
||
|
_transform.rotation = data.TransformRotation;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void RefreshCollider()
|
||
|
{
|
||
|
if (_settings.Shape == EKCCShape.None)
|
||
|
{
|
||
|
_collider.Destroy();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
_settings.Radius = Mathf.Max(0.01f, _settings.Radius);
|
||
|
_settings.Height = Mathf.Max(_settings.Radius * 2f, _settings.Height);
|
||
|
_settings.Extent = Mathf.Max(0f, _settings.Extent);
|
||
|
_collider.Update(this);
|
||
|
}
|
||
|
|
||
|
private void SetDefaults(bool cleanup)
|
||
|
{
|
||
|
_fixedData.Clear();
|
||
|
_renderData.Clear();
|
||
|
_historyData.Clear();
|
||
|
_extendedOverlapInfo.Reset(deep: true);
|
||
|
_trackOverlapInfo.Reset(deep: true);
|
||
|
_childColliders.Clear();
|
||
|
_raycastHits.Clear();
|
||
|
_hitColliders.Clear();
|
||
|
_addColliders.Clear();
|
||
|
_removeColliders.Clear();
|
||
|
_rigidbody.isKinematic = true;
|
||
|
_lastRenderTime = 0f;
|
||
|
_lastRenderPosition = default(Vector3);
|
||
|
_lastAntiJitterPosition = default(Vector3);
|
||
|
_predictionError = default(Vector3);
|
||
|
if (cleanup)
|
||
|
{
|
||
|
_isSpawned = false;
|
||
|
_isInFixedUpdate = false;
|
||
|
_settings.CopyFromOther(_defaultSettings);
|
||
|
_collider.Destroy();
|
||
|
this._onSpawn = null;
|
||
|
ResolveCollision = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void PublishFixedData()
|
||
|
{
|
||
|
_renderData.CopyFromOther(_fixedData);
|
||
|
KCCData kCCData = _historyData[_fixedData.Tick % 60];
|
||
|
if (kCCData == null)
|
||
|
{
|
||
|
kCCData = new KCCData();
|
||
|
_historyData[_fixedData.Tick % 60] = kCCData;
|
||
|
}
|
||
|
|
||
|
kCCData.CopyFromOther(_fixedData);
|
||
|
}
|
||
|
|
||
|
public void Log(params object[] messages)
|
||
|
{
|
||
|
KCCUtility.Log(this, null, EKCCLogType.Info, messages);
|
||
|
}
|
||
|
|
||
|
internal void LogWarning(params object[] messages)
|
||
|
{
|
||
|
KCCUtility.Log(this, null, EKCCLogType.Warning, messages);
|
||
|
}
|
||
|
|
||
|
internal void LogError(params object[] messages)
|
||
|
{
|
||
|
KCCUtility.Log(this, null, EKCCLogType.Error, messages);
|
||
|
}
|
||
|
|
||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||
|
private bool CheckSpawned()
|
||
|
{
|
||
|
if (!_isSpawned)
|
||
|
{
|
||
|
LogError("KCC.Spawned() has not been called yet! Use KCC.InvokeOnSpawn() to register a callback.", this);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
internal Vector3 ResolvePenetration(KCCOverlapInfo overlapInfo, KCCData data, Vector3 basePosition, Vector3 targetPosition, bool probeGrounding, int maxSteps, int resolverIterations, bool resolveTriggers)
|
||
|
{
|
||
|
if (_settings.SuppressConvexMeshColliders)
|
||
|
{
|
||
|
overlapInfo.ToggleConvexMeshColliders(convex: false);
|
||
|
}
|
||
|
|
||
|
if (overlapInfo.ColliderHitCount == 1)
|
||
|
{
|
||
|
targetPosition = DepenetrateSingle(overlapInfo, data, basePosition, targetPosition, probeGrounding, maxSteps);
|
||
|
}
|
||
|
else if (overlapInfo.ColliderHitCount > 1)
|
||
|
{
|
||
|
targetPosition = DepenetrateMultiple(overlapInfo, data, basePosition, targetPosition, probeGrounding, maxSteps, resolverIterations);
|
||
|
}
|
||
|
|
||
|
RecalculateGroundProperties(data);
|
||
|
if (resolveTriggers)
|
||
|
{
|
||
|
for (int i = 0; i < overlapInfo.TriggerHitCount; i++)
|
||
|
{
|
||
|
KCCOverlapHit kCCOverlapHit = overlapInfo.TriggerHits[i];
|
||
|
kCCOverlapHit.Transform.GetPositionAndRotation(out kCCOverlapHit.CachedPosition, out kCCOverlapHit.CachedRotation);
|
||
|
kCCOverlapHit.CollisionType = ((kCCOverlapHit.IsWithinExtent = (kCCOverlapHit.HasPenetration = Physics.ComputePenetration(_collider.Collider, data.TargetPosition, Quaternion.identity, kCCOverlapHit.Collider, kCCOverlapHit.CachedPosition, kCCOverlapHit.CachedRotation, out var _, out var distance))) ? ECollisionType.Trigger : ECollisionType.None);
|
||
|
if (distance > kCCOverlapHit.MaxPenetration)
|
||
|
{
|
||
|
kCCOverlapHit.MaxPenetration = distance;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (_settings.SuppressConvexMeshColliders)
|
||
|
{
|
||
|
overlapInfo.ToggleConvexMeshColliders(convex: true);
|
||
|
}
|
||
|
|
||
|
return targetPosition;
|
||
|
}
|
||
|
|
||
|
private Vector3 DepenetrateSingle(KCCOverlapInfo overlapInfo, KCCData data, Vector3 basePosition, Vector3 targetPosition, bool probeGrounding, int maxSteps)
|
||
|
{
|
||
|
float num = Mathf.Cos(Mathf.Clamp(data.MaxGroundAngle, 0f, 90f) * (MathF.PI / 180f));
|
||
|
float num2 = 0f - Mathf.Cos(Mathf.Clamp(90f - data.MaxWallAngle, 0f, 90f) * (MathF.PI / 180f));
|
||
|
float num3 = 0f - Mathf.Cos(Mathf.Clamp(90f - data.MaxHangAngle, 0f, 90f) * (MathF.PI / 180f));
|
||
|
Vector3 vector = Vector3.up;
|
||
|
float num4 = 0f;
|
||
|
KCCOverlapHit kCCOverlapHit = overlapInfo.ColliderHits[0];
|
||
|
kCCOverlapHit.UpDirectionDot = float.MinValue;
|
||
|
kCCOverlapHit.Transform.GetPositionAndRotation(out kCCOverlapHit.CachedPosition, out kCCOverlapHit.CachedRotation);
|
||
|
if (maxSteps > 1)
|
||
|
{
|
||
|
float num5 = 0.001f;
|
||
|
float num6 = Vector3.Distance(basePosition, targetPosition);
|
||
|
if (num6 < (float)maxSteps * num5)
|
||
|
{
|
||
|
maxSteps = Mathf.Max(1, (int)(num6 / num5));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (maxSteps <= 1)
|
||
|
{
|
||
|
kCCOverlapHit.HasPenetration = Physics.ComputePenetration(_collider.Collider, targetPosition, Quaternion.identity, kCCOverlapHit.Collider, kCCOverlapHit.CachedPosition, kCCOverlapHit.CachedRotation, out var direction, out var distance);
|
||
|
if (kCCOverlapHit.HasPenetration)
|
||
|
{
|
||
|
kCCOverlapHit.IsWithinExtent = true;
|
||
|
if (distance > kCCOverlapHit.MaxPenetration)
|
||
|
{
|
||
|
kCCOverlapHit.MaxPenetration = distance;
|
||
|
}
|
||
|
|
||
|
float num7 = Vector3.Dot(direction, Vector3.up);
|
||
|
if (num7 > kCCOverlapHit.UpDirectionDot)
|
||
|
{
|
||
|
kCCOverlapHit.UpDirectionDot = num7;
|
||
|
if (num7 >= num)
|
||
|
{
|
||
|
kCCOverlapHit.CollisionType = ECollisionType.Ground;
|
||
|
data.IsGrounded = true;
|
||
|
vector = direction;
|
||
|
}
|
||
|
else if (num7 > 0f - num2)
|
||
|
{
|
||
|
kCCOverlapHit.CollisionType = ECollisionType.Slope;
|
||
|
}
|
||
|
else if (num7 >= num2)
|
||
|
{
|
||
|
kCCOverlapHit.CollisionType = ECollisionType.Wall;
|
||
|
}
|
||
|
else if (num7 >= num3)
|
||
|
{
|
||
|
kCCOverlapHit.CollisionType = ECollisionType.Hang;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
kCCOverlapHit.CollisionType = ECollisionType.Top;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (num7 > 0f && num7 < num && distance >= 1E-06f && data.DynamicVelocity.y <= 0f && Vector3.Dot((targetPosition - basePosition).OnlyXZ(), direction.OnlyXZ()) < 0f)
|
||
|
{
|
||
|
KCCPhysicsUtility.ProjectVerticalPenetration(ref direction, ref distance);
|
||
|
}
|
||
|
|
||
|
targetPosition += direction * distance;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Vector3 vector2 = (targetPosition - basePosition) / maxSteps;
|
||
|
Vector3 vector3 = basePosition;
|
||
|
int num8 = maxSteps;
|
||
|
while (num8 > 0)
|
||
|
{
|
||
|
num8--;
|
||
|
vector3 += vector2;
|
||
|
kCCOverlapHit.HasPenetration = Physics.ComputePenetration(_collider.Collider, vector3, Quaternion.identity, kCCOverlapHit.Collider, kCCOverlapHit.CachedPosition, kCCOverlapHit.CachedRotation, out var direction2, out var distance2);
|
||
|
if (!kCCOverlapHit.HasPenetration)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
kCCOverlapHit.IsWithinExtent = true;
|
||
|
if (distance2 > kCCOverlapHit.MaxPenetration)
|
||
|
{
|
||
|
kCCOverlapHit.MaxPenetration = distance2;
|
||
|
}
|
||
|
|
||
|
float num9 = Vector3.Dot(direction2, Vector3.up);
|
||
|
if (num9 > kCCOverlapHit.UpDirectionDot)
|
||
|
{
|
||
|
kCCOverlapHit.UpDirectionDot = num9;
|
||
|
if (num9 >= num)
|
||
|
{
|
||
|
kCCOverlapHit.CollisionType = ECollisionType.Ground;
|
||
|
data.IsGrounded = true;
|
||
|
vector = direction2;
|
||
|
}
|
||
|
else if (num9 > 0f - num2)
|
||
|
{
|
||
|
kCCOverlapHit.CollisionType = ECollisionType.Slope;
|
||
|
}
|
||
|
else if (num9 >= num2)
|
||
|
{
|
||
|
kCCOverlapHit.CollisionType = ECollisionType.Wall;
|
||
|
}
|
||
|
else if (num9 >= num3)
|
||
|
{
|
||
|
kCCOverlapHit.CollisionType = ECollisionType.Hang;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
kCCOverlapHit.CollisionType = ECollisionType.Top;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (num9 > 0f && num9 < num && distance2 >= 1E-06f && data.DynamicVelocity.y <= 0f && Vector3.Dot(vector2.OnlyXZ(), direction2.OnlyXZ()) < 0f)
|
||
|
{
|
||
|
KCCPhysicsUtility.ProjectVerticalPenetration(ref direction2, ref distance2);
|
||
|
}
|
||
|
|
||
|
vector3 += direction2 * distance2;
|
||
|
}
|
||
|
|
||
|
targetPosition = vector3;
|
||
|
}
|
||
|
|
||
|
if (kCCOverlapHit.UpDirectionDot == float.MinValue)
|
||
|
{
|
||
|
kCCOverlapHit.UpDirectionDot = 0f;
|
||
|
}
|
||
|
|
||
|
if (probeGrounding && !data.IsGrounded)
|
||
|
{
|
||
|
if (KCCPhysicsUtility.CheckGround(_collider.Collider, targetPosition, kCCOverlapHit.Collider, kCCOverlapHit.CachedPosition, kCCOverlapHit.CachedRotation, _settings.Radius, _settings.Height, _settings.Extent, num, out var groundNormal, out var groundDistance, out var isWithinExtent))
|
||
|
{
|
||
|
data.IsGrounded = true;
|
||
|
vector = groundNormal;
|
||
|
num4 = groundDistance;
|
||
|
kCCOverlapHit.IsWithinExtent = true;
|
||
|
kCCOverlapHit.CollisionType = ECollisionType.Ground;
|
||
|
}
|
||
|
else if (isWithinExtent)
|
||
|
{
|
||
|
kCCOverlapHit.IsWithinExtent = true;
|
||
|
if (kCCOverlapHit.CollisionType == ECollisionType.None)
|
||
|
{
|
||
|
kCCOverlapHit.CollisionType = ECollisionType.Slope;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (data.IsGrounded)
|
||
|
{
|
||
|
data.GroundNormal = vector;
|
||
|
data.GroundAngle = Vector3.Angle(vector, Vector3.up);
|
||
|
data.GroundPosition = targetPosition + new Vector3(0f, _settings.Radius, 0f) - vector * (_settings.Radius + num4);
|
||
|
data.GroundDistance = num4;
|
||
|
}
|
||
|
|
||
|
return targetPosition;
|
||
|
}
|
||
|
|
||
|
private Vector3 DepenetrateMultiple(KCCOverlapInfo overlapInfo, KCCData data, Vector3 basePosition, Vector3 targetPosition, bool probeGrounding, int maxSteps, int resolverIterations)
|
||
|
{
|
||
|
float num = Mathf.Cos(Mathf.Clamp(data.MaxGroundAngle, 0f, 90f) * (MathF.PI / 180f));
|
||
|
float num2 = 0f - Mathf.Cos(Mathf.Clamp(90f - data.MaxWallAngle, 0f, 90f) * (MathF.PI / 180f));
|
||
|
float num3 = 0f - Mathf.Cos(Mathf.Clamp(90f - data.MaxHangAngle, 0f, 90f) * (MathF.PI / 180f));
|
||
|
float num4 = 0f;
|
||
|
float num5 = 0f;
|
||
|
Vector3 other = default(Vector3);
|
||
|
Vector3 vector = default(Vector3);
|
||
|
Vector3 lhs = (targetPosition - basePosition).OnlyXZ();
|
||
|
for (int i = 0; i < overlapInfo.ColliderHitCount; i++)
|
||
|
{
|
||
|
KCCOverlapHit kCCOverlapHit = overlapInfo.ColliderHits[i];
|
||
|
kCCOverlapHit.UpDirectionDot = float.MinValue;
|
||
|
kCCOverlapHit.Transform.GetPositionAndRotation(out kCCOverlapHit.CachedPosition, out kCCOverlapHit.CachedRotation);
|
||
|
}
|
||
|
|
||
|
if (maxSteps > 1)
|
||
|
{
|
||
|
float num6 = 0.001f;
|
||
|
float num7 = Vector3.Distance(basePosition, targetPosition);
|
||
|
if (num7 < (float)maxSteps * num6)
|
||
|
{
|
||
|
maxSteps = Mathf.Max(1, (int)(num7 / num6));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (maxSteps <= 1)
|
||
|
{
|
||
|
_resolver.Reset();
|
||
|
for (int j = 0; j < overlapInfo.ColliderHitCount; j++)
|
||
|
{
|
||
|
KCCOverlapHit kCCOverlapHit2 = overlapInfo.ColliderHits[j];
|
||
|
kCCOverlapHit2.HasPenetration = Physics.ComputePenetration(_collider.Collider, targetPosition, Quaternion.identity, kCCOverlapHit2.Collider, kCCOverlapHit2.CachedPosition, kCCOverlapHit2.CachedRotation, out var direction, out var distance);
|
||
|
if (!kCCOverlapHit2.HasPenetration)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
kCCOverlapHit2.IsWithinExtent = true;
|
||
|
if (distance > kCCOverlapHit2.MaxPenetration)
|
||
|
{
|
||
|
kCCOverlapHit2.MaxPenetration = distance;
|
||
|
}
|
||
|
|
||
|
float num8 = Vector3.Dot(direction, Vector3.up);
|
||
|
if (num8 > kCCOverlapHit2.UpDirectionDot)
|
||
|
{
|
||
|
kCCOverlapHit2.UpDirectionDot = num8;
|
||
|
if (num8 >= num)
|
||
|
{
|
||
|
kCCOverlapHit2.CollisionType = ECollisionType.Ground;
|
||
|
data.IsGrounded = true;
|
||
|
if (num8 >= num5)
|
||
|
{
|
||
|
num5 = num8;
|
||
|
other = direction;
|
||
|
}
|
||
|
|
||
|
vector += direction * num8;
|
||
|
}
|
||
|
else if (num8 > 0f - num2)
|
||
|
{
|
||
|
kCCOverlapHit2.CollisionType = ECollisionType.Slope;
|
||
|
}
|
||
|
else if (num8 >= num2)
|
||
|
{
|
||
|
kCCOverlapHit2.CollisionType = ECollisionType.Wall;
|
||
|
}
|
||
|
else if (num8 >= num3)
|
||
|
{
|
||
|
kCCOverlapHit2.CollisionType = ECollisionType.Hang;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
kCCOverlapHit2.CollisionType = ECollisionType.Top;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (num8 > 0f && num8 < num && distance >= 1E-06f && data.DynamicVelocity.y <= 0f && Vector3.Dot(lhs, direction.OnlyXZ()) < 0f)
|
||
|
{
|
||
|
KCCPhysicsUtility.ProjectVerticalPenetration(ref direction, ref distance);
|
||
|
}
|
||
|
|
||
|
_resolver.AddCorrection(direction, distance);
|
||
|
}
|
||
|
|
||
|
int num9 = Mathf.Max(0, resolverIterations);
|
||
|
float num10 = 1f - (float)Mathf.Min(num9, 2) * 0.25f;
|
||
|
if (_resolver.Size == 2)
|
||
|
{
|
||
|
_resolver.GetCorrection(0, out var direction2);
|
||
|
_resolver.GetCorrection(1, out var direction3);
|
||
|
if (Vector3.Dot(direction2, direction3) >= 0f)
|
||
|
{
|
||
|
targetPosition += _resolver.CalculateMinMax() * num10;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
targetPosition += _resolver.CalculateBinary() * num10;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
targetPosition += _resolver.CalculateGradientDescent(12, 0.0001f) * num10;
|
||
|
}
|
||
|
|
||
|
while (num9 > 0)
|
||
|
{
|
||
|
num9--;
|
||
|
_resolver.Reset();
|
||
|
for (int k = 0; k < overlapInfo.ColliderHitCount; k++)
|
||
|
{
|
||
|
KCCOverlapHit kCCOverlapHit3 = overlapInfo.ColliderHits[k];
|
||
|
if (!Physics.ComputePenetration(_collider.Collider, targetPosition, Quaternion.identity, kCCOverlapHit3.Collider, kCCOverlapHit3.CachedPosition, kCCOverlapHit3.CachedRotation, out var direction4, out var distance2))
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
kCCOverlapHit3.IsWithinExtent = true;
|
||
|
kCCOverlapHit3.HasPenetration = true;
|
||
|
if (distance2 > kCCOverlapHit3.MaxPenetration)
|
||
|
{
|
||
|
kCCOverlapHit3.MaxPenetration = distance2;
|
||
|
}
|
||
|
|
||
|
float num11 = Vector3.Dot(direction4, Vector3.up);
|
||
|
if (num11 > kCCOverlapHit3.UpDirectionDot)
|
||
|
{
|
||
|
kCCOverlapHit3.UpDirectionDot = num11;
|
||
|
if (num11 >= num)
|
||
|
{
|
||
|
kCCOverlapHit3.CollisionType = ECollisionType.Ground;
|
||
|
data.IsGrounded = true;
|
||
|
if (num11 >= num5)
|
||
|
{
|
||
|
num5 = num11;
|
||
|
other = direction4;
|
||
|
}
|
||
|
|
||
|
vector += direction4 * num11;
|
||
|
}
|
||
|
else if (num11 > 0f - num2)
|
||
|
{
|
||
|
kCCOverlapHit3.CollisionType = ECollisionType.Slope;
|
||
|
}
|
||
|
else if (num11 >= num2)
|
||
|
{
|
||
|
kCCOverlapHit3.CollisionType = ECollisionType.Wall;
|
||
|
}
|
||
|
else if (num11 >= num3)
|
||
|
{
|
||
|
kCCOverlapHit3.CollisionType = ECollisionType.Hang;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
kCCOverlapHit3.CollisionType = ECollisionType.Top;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (num11 > 0f && num11 < num && distance2 >= 1E-06f && data.DynamicVelocity.y <= 0f && Vector3.Dot(lhs, direction4.OnlyXZ()) < 0f)
|
||
|
{
|
||
|
KCCPhysicsUtility.ProjectVerticalPenetration(ref direction4, ref distance2);
|
||
|
}
|
||
|
|
||
|
_resolver.AddCorrection(direction4, distance2);
|
||
|
}
|
||
|
|
||
|
if (_resolver.Size == 0)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
switch (num9)
|
||
|
{
|
||
|
case 0:
|
||
|
if (_resolver.Size == 2)
|
||
|
{
|
||
|
_resolver.GetCorrection(0, out var direction5);
|
||
|
_resolver.GetCorrection(1, out var direction6);
|
||
|
if (Vector3.Dot(direction5, direction6) >= 0f)
|
||
|
{
|
||
|
targetPosition += _resolver.CalculateGradientDescent(12, 0.0001f);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
targetPosition += _resolver.CalculateBinary();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
targetPosition += _resolver.CalculateGradientDescent(12, 0.0001f);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
case 1:
|
||
|
targetPosition += _resolver.CalculateMinMax() * 0.75f;
|
||
|
break;
|
||
|
default:
|
||
|
targetPosition += _resolver.CalculateMinMax() * 0.5f;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Vector3 vector2 = (targetPosition - basePosition) / maxSteps;
|
||
|
Vector3 vector3 = basePosition;
|
||
|
int num12 = maxSteps;
|
||
|
while (num12 > 1)
|
||
|
{
|
||
|
num12--;
|
||
|
vector3 += vector2;
|
||
|
_resolver.Reset();
|
||
|
for (int l = 0; l < overlapInfo.ColliderHitCount; l++)
|
||
|
{
|
||
|
KCCOverlapHit kCCOverlapHit4 = overlapInfo.ColliderHits[l];
|
||
|
kCCOverlapHit4.HasPenetration = Physics.ComputePenetration(_collider.Collider, vector3, Quaternion.identity, kCCOverlapHit4.Collider, kCCOverlapHit4.CachedPosition, kCCOverlapHit4.CachedRotation, out var direction7, out var distance3);
|
||
|
if (!kCCOverlapHit4.HasPenetration)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
kCCOverlapHit4.IsWithinExtent = true;
|
||
|
if (distance3 > kCCOverlapHit4.MaxPenetration)
|
||
|
{
|
||
|
kCCOverlapHit4.MaxPenetration = distance3;
|
||
|
}
|
||
|
|
||
|
float num13 = Vector3.Dot(direction7, Vector3.up);
|
||
|
if (num13 > kCCOverlapHit4.UpDirectionDot)
|
||
|
{
|
||
|
kCCOverlapHit4.UpDirectionDot = num13;
|
||
|
if (num13 >= num)
|
||
|
{
|
||
|
kCCOverlapHit4.CollisionType = ECollisionType.Ground;
|
||
|
data.IsGrounded = true;
|
||
|
if (num13 >= num5)
|
||
|
{
|
||
|
num5 = num13;
|
||
|
other = direction7;
|
||
|
}
|
||
|
|
||
|
vector += direction7 * num13;
|
||
|
}
|
||
|
else if (num13 > 0f - num2)
|
||
|
{
|
||
|
kCCOverlapHit4.CollisionType = ECollisionType.Slope;
|
||
|
}
|
||
|
else if (num13 >= num2)
|
||
|
{
|
||
|
kCCOverlapHit4.CollisionType = ECollisionType.Wall;
|
||
|
}
|
||
|
else if (num13 >= num3)
|
||
|
{
|
||
|
kCCOverlapHit4.CollisionType = ECollisionType.Hang;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
kCCOverlapHit4.CollisionType = ECollisionType.Top;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (num13 > 0f && num13 < num && distance3 >= 1E-06f && data.DynamicVelocity.y <= 0f && Vector3.Dot(vector2.OnlyXZ(), direction7.OnlyXZ()) < 0f)
|
||
|
{
|
||
|
KCCPhysicsUtility.ProjectVerticalPenetration(ref direction7, ref distance3);
|
||
|
}
|
||
|
|
||
|
_resolver.AddCorrection(direction7, distance3);
|
||
|
}
|
||
|
|
||
|
if (_resolver.Size == 2)
|
||
|
{
|
||
|
_resolver.GetCorrection(0, out var direction8);
|
||
|
_resolver.GetCorrection(1, out var direction9);
|
||
|
if (Vector3.Dot(direction8, direction9) >= 0f)
|
||
|
{
|
||
|
vector3 += _resolver.CalculateMinMax();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
vector3 += _resolver.CalculateBinary();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
vector3 += _resolver.CalculateMinMax();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
num12--;
|
||
|
vector3 += vector2;
|
||
|
_resolver.Reset();
|
||
|
for (int m = 0; m < overlapInfo.ColliderHitCount; m++)
|
||
|
{
|
||
|
KCCOverlapHit kCCOverlapHit5 = overlapInfo.ColliderHits[m];
|
||
|
kCCOverlapHit5.HasPenetration = Physics.ComputePenetration(_collider.Collider, vector3, Quaternion.identity, kCCOverlapHit5.Collider, kCCOverlapHit5.CachedPosition, kCCOverlapHit5.CachedRotation, out var direction10, out var distance4);
|
||
|
if (!kCCOverlapHit5.HasPenetration)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
kCCOverlapHit5.IsWithinExtent = true;
|
||
|
if (distance4 > kCCOverlapHit5.MaxPenetration)
|
||
|
{
|
||
|
kCCOverlapHit5.MaxPenetration = distance4;
|
||
|
}
|
||
|
|
||
|
float num14 = Vector3.Dot(direction10, Vector3.up);
|
||
|
if (num14 > kCCOverlapHit5.UpDirectionDot)
|
||
|
{
|
||
|
kCCOverlapHit5.UpDirectionDot = num14;
|
||
|
if (num14 >= num)
|
||
|
{
|
||
|
kCCOverlapHit5.CollisionType = ECollisionType.Ground;
|
||
|
data.IsGrounded = true;
|
||
|
if (num14 >= num5)
|
||
|
{
|
||
|
num5 = num14;
|
||
|
other = direction10;
|
||
|
}
|
||
|
|
||
|
vector += direction10 * num14;
|
||
|
}
|
||
|
else if (num14 > 0f - num2)
|
||
|
{
|
||
|
kCCOverlapHit5.CollisionType = ECollisionType.Slope;
|
||
|
}
|
||
|
else if (num14 >= num2)
|
||
|
{
|
||
|
kCCOverlapHit5.CollisionType = ECollisionType.Wall;
|
||
|
}
|
||
|
else if (num14 >= num3)
|
||
|
{
|
||
|
kCCOverlapHit5.CollisionType = ECollisionType.Hang;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
kCCOverlapHit5.CollisionType = ECollisionType.Top;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (num14 > 0f && num14 < num && distance4 >= 1E-06f && data.DynamicVelocity.y <= 0f && Vector3.Dot(vector2.OnlyXZ(), direction10.OnlyXZ()) < 0f)
|
||
|
{
|
||
|
KCCPhysicsUtility.ProjectVerticalPenetration(ref direction10, ref distance4);
|
||
|
}
|
||
|
|
||
|
_resolver.AddCorrection(direction10, distance4);
|
||
|
}
|
||
|
|
||
|
if (_resolver.Size == 2)
|
||
|
{
|
||
|
_resolver.GetCorrection(0, out var direction11);
|
||
|
_resolver.GetCorrection(1, out var direction12);
|
||
|
if (Vector3.Dot(direction11, direction12) >= 0f)
|
||
|
{
|
||
|
vector3 += _resolver.CalculateMinMax();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
vector3 += _resolver.CalculateBinary();
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
vector3 += _resolver.CalculateGradientDescent(12, 0.0001f);
|
||
|
}
|
||
|
|
||
|
targetPosition = vector3;
|
||
|
}
|
||
|
|
||
|
for (int n = 0; n < overlapInfo.ColliderHitCount; n++)
|
||
|
{
|
||
|
KCCOverlapHit kCCOverlapHit6 = overlapInfo.ColliderHits[n];
|
||
|
if (kCCOverlapHit6.UpDirectionDot == float.MinValue)
|
||
|
{
|
||
|
kCCOverlapHit6.UpDirectionDot = 0f;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (probeGrounding && !data.IsGrounded)
|
||
|
{
|
||
|
Vector3 vector4 = Vector3.up;
|
||
|
float num15 = 1000f;
|
||
|
for (int num16 = 0; num16 < overlapInfo.ColliderHitCount; num16++)
|
||
|
{
|
||
|
KCCOverlapHit kCCOverlapHit7 = overlapInfo.ColliderHits[num16];
|
||
|
if (KCCPhysicsUtility.CheckGround(_collider.Collider, targetPosition, kCCOverlapHit7.Collider, kCCOverlapHit7.CachedPosition, kCCOverlapHit7.CachedRotation, _settings.Radius, _settings.Height, _settings.Extent, num, out var groundNormal, out var groundDistance, out var isWithinExtent))
|
||
|
{
|
||
|
data.IsGrounded = true;
|
||
|
if (groundDistance < num15)
|
||
|
{
|
||
|
vector4 = groundNormal;
|
||
|
num15 = groundDistance;
|
||
|
}
|
||
|
|
||
|
kCCOverlapHit7.IsWithinExtent = true;
|
||
|
kCCOverlapHit7.CollisionType = ECollisionType.Ground;
|
||
|
}
|
||
|
else if (isWithinExtent)
|
||
|
{
|
||
|
kCCOverlapHit7.IsWithinExtent = true;
|
||
|
if (kCCOverlapHit7.CollisionType == ECollisionType.None)
|
||
|
{
|
||
|
kCCOverlapHit7.CollisionType = ECollisionType.Slope;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (data.IsGrounded)
|
||
|
{
|
||
|
other = vector4;
|
||
|
vector = vector4;
|
||
|
num4 = num15;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (data.IsGrounded)
|
||
|
{
|
||
|
if (!vector.IsEqual(other))
|
||
|
{
|
||
|
vector.Normalize();
|
||
|
}
|
||
|
|
||
|
data.GroundNormal = vector;
|
||
|
data.GroundAngle = Vector3.Angle(data.GroundNormal, Vector3.up);
|
||
|
data.GroundPosition = targetPosition + new Vector3(0f, _settings.Radius, 0f) - data.GroundNormal * (_settings.Radius + num4);
|
||
|
data.GroundDistance = num4;
|
||
|
}
|
||
|
|
||
|
return targetPosition;
|
||
|
}
|
||
|
|
||
|
private static void RecalculateGroundProperties(KCCData data)
|
||
|
{
|
||
|
if (data.IsGrounded)
|
||
|
{
|
||
|
Vector3 projectedVector2;
|
||
|
if (KCCPhysicsUtility.ProjectOnGround(data.GroundNormal, data.GroundNormal.OnlyXZ(), out var projectedVector))
|
||
|
{
|
||
|
data.GroundTangent = projectedVector.normalized;
|
||
|
}
|
||
|
else if (KCCPhysicsUtility.ProjectOnGround(data.GroundNormal, data.DesiredVelocity.OnlyXZ(), out projectedVector2))
|
||
|
{
|
||
|
data.GroundTangent = projectedVector2.normalized;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
data.GroundTangent = data.TransformDirection;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void SetActive(bool isActive)
|
||
|
{
|
||
|
if (CheckSpawned())
|
||
|
{
|
||
|
_renderData.IsActive = isActive;
|
||
|
if (IsInFixedUpdate)
|
||
|
{
|
||
|
_fixedData.IsActive = isActive;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public Vector2 GetLookRotation(bool pitch = true, bool yaw = true)
|
||
|
{
|
||
|
return Data.GetLookRotation(pitch, yaw);
|
||
|
}
|
||
|
|
||
|
public void AddLookRotation(float pitchDelta, float yawDelta)
|
||
|
{
|
||
|
KCCData kCCData = _renderData;
|
||
|
kCCData.AddLookRotation(pitchDelta, yawDelta);
|
||
|
if (IsInFixedUpdate)
|
||
|
{
|
||
|
kCCData = _fixedData;
|
||
|
kCCData.AddLookRotation(pitchDelta, yawDelta);
|
||
|
}
|
||
|
|
||
|
SynchronizeTransform(kCCData, synchronizePosition: false, synchronizeRotation: true, allowAntiJitter: false);
|
||
|
}
|
||
|
|
||
|
public void AddLookRotation(float pitchDelta, float yawDelta, float minPitch, float maxPitch)
|
||
|
{
|
||
|
KCCData kCCData = _renderData;
|
||
|
kCCData.AddLookRotation(pitchDelta, yawDelta, minPitch, maxPitch);
|
||
|
if (IsInFixedUpdate)
|
||
|
{
|
||
|
kCCData = _fixedData;
|
||
|
kCCData.AddLookRotation(pitchDelta, yawDelta, minPitch, maxPitch);
|
||
|
}
|
||
|
|
||
|
SynchronizeTransform(kCCData, synchronizePosition: false, synchronizeRotation: true, allowAntiJitter: false);
|
||
|
}
|
||
|
|
||
|
public void AddLookRotation(Vector2 lookRotationDelta)
|
||
|
{
|
||
|
AddLookRotation(lookRotationDelta.x, lookRotationDelta.y);
|
||
|
}
|
||
|
|
||
|
public void AddLookRotation(Vector2 lookRotationDelta, float minPitch, float maxPitch)
|
||
|
{
|
||
|
AddLookRotation(lookRotationDelta.x, lookRotationDelta.y, minPitch, maxPitch);
|
||
|
}
|
||
|
|
||
|
public void SetLookRotation(float pitch, float yaw)
|
||
|
{
|
||
|
KCCData kCCData = _renderData;
|
||
|
kCCData.SetLookRotation(pitch, yaw);
|
||
|
if (IsInFixedUpdate)
|
||
|
{
|
||
|
kCCData = _fixedData;
|
||
|
kCCData.SetLookRotation(pitch, yaw);
|
||
|
}
|
||
|
|
||
|
SynchronizeTransform(kCCData, synchronizePosition: false, synchronizeRotation: true, allowAntiJitter: false);
|
||
|
}
|
||
|
|
||
|
public void SetLookRotation(Vector2 lookRotation)
|
||
|
{
|
||
|
SetLookRotation(lookRotation.x, lookRotation.y);
|
||
|
}
|
||
|
|
||
|
public void SetLookRotation(Quaternion lookRotation, bool preservePitch = false, bool preserveYaw = false)
|
||
|
{
|
||
|
KCCData kCCData = _renderData;
|
||
|
kCCData.SetLookRotation(lookRotation, preservePitch, preserveYaw);
|
||
|
if (IsInFixedUpdate)
|
||
|
{
|
||
|
kCCData = _fixedData;
|
||
|
kCCData.SetLookRotation(lookRotation, preservePitch, preserveYaw);
|
||
|
}
|
||
|
|
||
|
SynchronizeTransform(kCCData, synchronizePosition: false, synchronizeRotation: true, allowAntiJitter: false);
|
||
|
}
|
||
|
|
||
|
public void SetPosition(Vector3 position)
|
||
|
{
|
||
|
KCCData kCCData = _renderData;
|
||
|
kCCData.BasePosition = position;
|
||
|
kCCData.DesiredPosition = position;
|
||
|
kCCData.TargetPosition = position;
|
||
|
kCCData.HasTeleported = true;
|
||
|
kCCData.IsSteppingUp = false;
|
||
|
kCCData.IsSnappingToGround = false;
|
||
|
if (IsInFixedUpdate)
|
||
|
{
|
||
|
kCCData = _fixedData;
|
||
|
kCCData.BasePosition = position;
|
||
|
kCCData.DesiredPosition = position;
|
||
|
kCCData.TargetPosition = position;
|
||
|
kCCData.HasTeleported = true;
|
||
|
kCCData.IsSteppingUp = false;
|
||
|
kCCData.IsSnappingToGround = false;
|
||
|
}
|
||
|
|
||
|
SynchronizeTransform(kCCData, synchronizePosition: true, synchronizeRotation: false, allowAntiJitter: false);
|
||
|
}
|
||
|
|
||
|
public void SetShape(EKCCShape shape, float radius = 0f, float height = 0f)
|
||
|
{
|
||
|
_settings.Shape = shape;
|
||
|
if (radius > 0f)
|
||
|
{
|
||
|
_settings.Radius = radius;
|
||
|
}
|
||
|
|
||
|
if (height > 0f)
|
||
|
{
|
||
|
_settings.Height = height;
|
||
|
}
|
||
|
|
||
|
RefreshCollider();
|
||
|
}
|
||
|
|
||
|
public void SetTrigger(bool isTrigger)
|
||
|
{
|
||
|
_settings.IsTrigger = isTrigger;
|
||
|
RefreshCollider();
|
||
|
}
|
||
|
|
||
|
public void SetRadius(float radius)
|
||
|
{
|
||
|
if (!(radius <= 0f))
|
||
|
{
|
||
|
_settings.Radius = radius;
|
||
|
RefreshCollider();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void SetHeight(float height)
|
||
|
{
|
||
|
if (!(height <= 0f))
|
||
|
{
|
||
|
_settings.Height = height;
|
||
|
RefreshCollider();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void SetColliderLayer(int layer)
|
||
|
{
|
||
|
_settings.ColliderLayer = layer;
|
||
|
RefreshCollider();
|
||
|
}
|
||
|
|
||
|
public void SetCollisionLayerMask(LayerMask layerMask)
|
||
|
{
|
||
|
_settings.CollisionLayerMask = layerMask;
|
||
|
}
|
||
|
|
||
|
private RenderTimeframe GetInterpolationTimeframe()
|
||
|
{
|
||
|
if (!base.Object.IsInSimulation)
|
||
|
{
|
||
|
return RenderTimeframe.Remote;
|
||
|
}
|
||
|
|
||
|
return RenderTimeframe.Local;
|
||
|
}
|
||
|
|
||
|
private unsafe Vector3 GetNetworkBufferPosition()
|
||
|
{
|
||
|
fixed (int* ptr = &ReinterpretState<int>())
|
||
|
{
|
||
|
return ((NetworkTRSPData*)ptr)->Position + KCCNetworkUtility.ReadVector3(ptr + 14);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private bool GetInterpolatedNetworkBufferPosition(out Vector3 interpolatedPosition)
|
||
|
{
|
||
|
interpolatedPosition = default(Vector3);
|
||
|
RenderSource renderSource = base.Object.RenderSource;
|
||
|
RenderTimeframe renderTimeframe = base.Object.RenderTimeframe;
|
||
|
base.Object.RenderSource = RenderSource.Interpolated;
|
||
|
base.Object.RenderTimeframe = GetInterpolationTimeframe();
|
||
|
NetworkBehaviourBuffer from;
|
||
|
NetworkBehaviourBuffer to;
|
||
|
float alpha;
|
||
|
bool num = TryGetSnapshotsBuffers(out from, out to, out alpha);
|
||
|
base.Object.RenderSource = renderSource;
|
||
|
base.Object.RenderTimeframe = renderTimeframe;
|
||
|
if (!num)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
KCCNetworkProperties.ReadPositions(from, to, out var fromTargetPosition, out var toTargetPosition);
|
||
|
interpolatedPosition = Vector3.Lerp(fromTargetPosition, toTargetPosition, alpha);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
private int GetNetworkDataWordCount()
|
||
|
{
|
||
|
InitializeNetworkProperties();
|
||
|
int num = 0;
|
||
|
int i = 0;
|
||
|
for (int num2 = _networkProperties.Length; i < num2; i++)
|
||
|
{
|
||
|
IKCCNetworkProperty iKCCNetworkProperty = _networkProperties[i];
|
||
|
num += iKCCNetworkProperty.WordCount;
|
||
|
}
|
||
|
|
||
|
return num;
|
||
|
}
|
||
|
|
||
|
private unsafe void ReadNetworkData()
|
||
|
{
|
||
|
_networkContext.Data = _fixedData;
|
||
|
fixed (int* ptr = &ReinterpretState<int>())
|
||
|
{
|
||
|
int* ptr2 = ptr;
|
||
|
int i = 0;
|
||
|
for (int num = _networkProperties.Length; i < num; i++)
|
||
|
{
|
||
|
IKCCNetworkProperty iKCCNetworkProperty = _networkProperties[i];
|
||
|
iKCCNetworkProperty.Read(ptr2);
|
||
|
ptr2 += iKCCNetworkProperty.WordCount;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private unsafe void WriteNetworkData()
|
||
|
{
|
||
|
_networkContext.Data = _fixedData;
|
||
|
fixed (int* ptr = &ReinterpretState<int>())
|
||
|
{
|
||
|
int* ptr2 = ptr;
|
||
|
int i = 0;
|
||
|
for (int num = _networkProperties.Length; i < num; i++)
|
||
|
{
|
||
|
IKCCNetworkProperty iKCCNetworkProperty = _networkProperties[i];
|
||
|
iKCCNetworkProperty.Write(ptr2);
|
||
|
ptr2 += iKCCNetworkProperty.WordCount;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void InterpolateNetworkData(RenderSource renderSource, RenderTimeframe renderTimeframe, float interpolationAlpha = -1f)
|
||
|
{
|
||
|
RenderSource renderSource2 = base.Object.RenderSource;
|
||
|
RenderTimeframe renderTimeframe2 = base.Object.RenderTimeframe;
|
||
|
base.Object.RenderSource = renderSource;
|
||
|
base.Object.RenderTimeframe = renderTimeframe;
|
||
|
NetworkBehaviourBuffer from;
|
||
|
NetworkBehaviourBuffer to;
|
||
|
float alpha;
|
||
|
bool num = TryGetSnapshotsBuffers(out from, out to, out alpha);
|
||
|
base.Object.RenderSource = renderSource2;
|
||
|
base.Object.RenderTimeframe = renderTimeframe2;
|
||
|
if (num && UpdateInterpolationTick(from.Tick, to.Tick))
|
||
|
{
|
||
|
if (interpolationAlpha >= 0f && interpolationAlpha <= 1f)
|
||
|
{
|
||
|
alpha = interpolationAlpha;
|
||
|
}
|
||
|
|
||
|
float deltaTime = base.Runner.DeltaTime;
|
||
|
float num2 = (float)(int)from.Tick + alpha * (float)((int)to.Tick - (int)from.Tick);
|
||
|
_renderData.CopyFromOther(_fixedData);
|
||
|
_renderData.Frame = Time.frameCount;
|
||
|
_renderData.Tick = Mathf.RoundToInt(num2);
|
||
|
_renderData.Alpha = alpha;
|
||
|
_renderData.DeltaTime = deltaTime;
|
||
|
_renderData.UpdateDeltaTime = deltaTime;
|
||
|
_renderData.Time = num2 * deltaTime;
|
||
|
_networkContext.Data = _renderData;
|
||
|
KCCInterpolationInfo interpolationInfo = default(KCCInterpolationInfo);
|
||
|
interpolationInfo.FromBuffer = from;
|
||
|
interpolationInfo.ToBuffer = to;
|
||
|
interpolationInfo.Alpha = alpha;
|
||
|
int i = 0;
|
||
|
for (int num3 = _networkProperties.Length; i < num3; i++)
|
||
|
{
|
||
|
IKCCNetworkProperty iKCCNetworkProperty = _networkProperties[i];
|
||
|
iKCCNetworkProperty.Interpolate(interpolationInfo);
|
||
|
interpolationInfo.Offset += iKCCNetworkProperty.WordCount;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void InterpolateNetworkTransform()
|
||
|
{
|
||
|
RenderSource renderSource = base.Object.RenderSource;
|
||
|
RenderTimeframe renderTimeframe = base.Object.RenderTimeframe;
|
||
|
base.Object.RenderSource = RenderSource.Interpolated;
|
||
|
base.Object.RenderTimeframe = RenderTimeframe.Remote;
|
||
|
NetworkBehaviourBuffer from;
|
||
|
NetworkBehaviourBuffer to;
|
||
|
float alpha;
|
||
|
bool num = TryGetSnapshotsBuffers(out from, out to, out alpha);
|
||
|
base.Object.RenderSource = renderSource;
|
||
|
base.Object.RenderTimeframe = renderTimeframe;
|
||
|
if (num && UpdateInterpolationTick(from.Tick, to.Tick))
|
||
|
{
|
||
|
KCCNetworkProperties.ReadTransforms(from, to, out var fromTargetPosition, out var toTargetPosition, out var fromLookPitch, out var toLookPitch, out var fromLookYaw, out var toLookYaw);
|
||
|
_fixedData.BasePosition = fromTargetPosition;
|
||
|
_fixedData.DesiredPosition = toTargetPosition;
|
||
|
_fixedData.TargetPosition = Vector3.Lerp(fromTargetPosition, toTargetPosition, alpha);
|
||
|
_fixedData.LookPitch = Mathf.Lerp(fromLookPitch, toLookPitch, alpha);
|
||
|
_fixedData.LookYaw = KCCUtility.InterpolateRange(fromLookYaw, toLookYaw, -180f, 180f, alpha);
|
||
|
_renderData.BasePosition = _fixedData.BasePosition;
|
||
|
_renderData.DesiredPosition = _fixedData.DesiredPosition;
|
||
|
_renderData.TargetPosition = _fixedData.TargetPosition;
|
||
|
_renderData.LookPitch = _fixedData.LookPitch;
|
||
|
_renderData.LookYaw = _fixedData.LookYaw;
|
||
|
_transform.SetPositionAndRotation(_renderData.TargetPosition, _renderData.TransformRotation);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private bool UpdateInterpolationTick(int fromTick, int toTick)
|
||
|
{
|
||
|
if (toTick - fromTick <= 0 && _interpolationTick == fromTick)
|
||
|
{
|
||
|
_interpolationAttempts = 30;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (_interpolationAttempts > 0)
|
||
|
{
|
||
|
if (toTick == base.Runner.Tick)
|
||
|
{
|
||
|
_interpolationAttempts--;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
_interpolationAttempts = 0;
|
||
|
}
|
||
|
|
||
|
_interpolationTick = fromTick;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
private void RestoreHistoryData(KCCData historyData)
|
||
|
{
|
||
|
if (_fixedData.IsGrounded)
|
||
|
{
|
||
|
_fixedData.IsGrounded = historyData.IsGrounded;
|
||
|
_fixedData.WasGrounded = historyData.WasGrounded;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void InitializeNetworkProperties()
|
||
|
{
|
||
|
if (_networkContext == null)
|
||
|
{
|
||
|
_networkContext = new KCCNetworkContext();
|
||
|
_networkContext.KCC = this;
|
||
|
_networkContext.Settings = _settings;
|
||
|
List<IKCCNetworkProperty> list = new List<IKCCNetworkProperty>(32);
|
||
|
list.Add(new KCCNetworkProperties(_networkContext));
|
||
|
_networkProperties = list.ToArray();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal bool SphereOverlap(KCCOverlapInfo overlapInfo, Vector3 position, float radius, QueryTriggerInteraction triggerInteraction)
|
||
|
{
|
||
|
return SphereOverlap(overlapInfo, Data, position, radius, 0f, _settings.CollisionLayerMask, triggerInteraction);
|
||
|
}
|
||
|
|
||
|
internal bool CapsuleOverlap(KCCOverlapInfo overlapInfo, Vector3 position, float radius, float height, QueryTriggerInteraction triggerInteraction)
|
||
|
{
|
||
|
return CapsuleOverlap(overlapInfo, Data, position, radius, height, 0f, _settings.CollisionLayerMask, triggerInteraction);
|
||
|
}
|
||
|
|
||
|
internal bool RayCast(KCCShapeCastInfo shapeCastInfo, Vector3 position, Vector3 direction, float maxDistance, QueryTriggerInteraction triggerInteraction)
|
||
|
{
|
||
|
return RayCast(shapeCastInfo, Data, position, direction, maxDistance, _settings.CollisionLayerMask, triggerInteraction);
|
||
|
}
|
||
|
|
||
|
internal bool SphereCast(KCCShapeCastInfo shapeCastInfo, Vector3 position, float radius, Vector3 direction, float maxDistance, QueryTriggerInteraction triggerInteraction, bool trackInitialOverlaps = true)
|
||
|
{
|
||
|
return SphereCast(shapeCastInfo, Data, position, radius, 0f, direction, maxDistance, _settings.CollisionLayerMask, triggerInteraction, trackInitialOverlaps);
|
||
|
}
|
||
|
|
||
|
internal bool CapsuleCast(KCCShapeCastInfo shapeCastInfo, Vector3 position, float radius, float height, Vector3 direction, float maxDistance, QueryTriggerInteraction triggerInteraction, bool trackInitialOverlaps = true)
|
||
|
{
|
||
|
return CapsuleCast(shapeCastInfo, Data, position, radius, height, 0f, direction, maxDistance, _settings.CollisionLayerMask, triggerInteraction, trackInitialOverlaps);
|
||
|
}
|
||
|
|
||
|
internal void UpdateHits(KCCOverlapInfo baseOverlapInfo, EKCCHitsOverlapQuery overlapQuery)
|
||
|
{
|
||
|
UpdateHits(Data, baseOverlapInfo, overlapQuery);
|
||
|
}
|
||
|
|
||
|
internal bool IsValidHitCollider(Collider hitCollider)
|
||
|
{
|
||
|
if (hitCollider == null)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return IsValidHitCollider(Data, hitCollider);
|
||
|
}
|
||
|
|
||
|
private bool SphereOverlap(KCCOverlapInfo overlapInfo, KCCData data, Vector3 position, float radius, float extent, LayerMask layerMask, QueryTriggerInteraction triggerInteraction)
|
||
|
{
|
||
|
overlapInfo.Reset(deep: false);
|
||
|
overlapInfo.Position = position;
|
||
|
overlapInfo.Radius = radius;
|
||
|
overlapInfo.Height = 0f;
|
||
|
overlapInfo.Extent = extent;
|
||
|
overlapInfo.LayerMask = layerMask;
|
||
|
overlapInfo.TriggerInteraction = triggerInteraction;
|
||
|
Collider[] hitColliders = _hitColliders;
|
||
|
int num = base.Runner.GetPhysicsScene().OverlapSphere(position, radius + extent, hitColliders, layerMask, triggerInteraction);
|
||
|
for (int i = 0; i < num; i++)
|
||
|
{
|
||
|
Collider overlapCollider = hitColliders[i];
|
||
|
if (IsValidHitColliderUnsafe(data, overlapCollider))
|
||
|
{
|
||
|
overlapInfo.AddHit(overlapCollider);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return overlapInfo.AllHitCount > 0;
|
||
|
}
|
||
|
|
||
|
private bool CapsuleOverlap(KCCOverlapInfo overlapInfo, KCCData data, Vector3 position, float radius, float height, float extent, LayerMask layerMask, QueryTriggerInteraction triggerInteraction)
|
||
|
{
|
||
|
overlapInfo.Reset(deep: false);
|
||
|
overlapInfo.Position = position;
|
||
|
overlapInfo.Radius = radius;
|
||
|
overlapInfo.Height = height;
|
||
|
overlapInfo.Extent = extent;
|
||
|
overlapInfo.LayerMask = layerMask;
|
||
|
overlapInfo.TriggerInteraction = triggerInteraction;
|
||
|
Vector3 point = position + new Vector3(0f, height - radius, 0f);
|
||
|
Vector3 point2 = position + new Vector3(0f, radius, 0f);
|
||
|
Collider[] hitColliders = _hitColliders;
|
||
|
int num = base.Runner.GetPhysicsScene().OverlapCapsule(point2, point, radius + extent, hitColliders, layerMask, triggerInteraction);
|
||
|
for (int i = 0; i < num; i++)
|
||
|
{
|
||
|
Collider overlapCollider = hitColliders[i];
|
||
|
if (IsValidHitColliderUnsafe(data, overlapCollider))
|
||
|
{
|
||
|
overlapInfo.AddHit(overlapCollider);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return overlapInfo.AllHitCount > 0;
|
||
|
}
|
||
|
|
||
|
private bool RayCast(KCCShapeCastInfo shapeCastInfo, KCCData data, Vector3 position, Vector3 direction, float maxDistance, LayerMask layerMask, QueryTriggerInteraction triggerInteraction)
|
||
|
{
|
||
|
shapeCastInfo.Reset(deep: false);
|
||
|
shapeCastInfo.Position = position;
|
||
|
shapeCastInfo.Direction = direction;
|
||
|
shapeCastInfo.MaxDistance = maxDistance;
|
||
|
shapeCastInfo.LayerMask = layerMask;
|
||
|
shapeCastInfo.TriggerInteraction = triggerInteraction;
|
||
|
RaycastHit[] raycastHits = _raycastHits;
|
||
|
int num = base.Runner.GetPhysicsScene().Raycast(position, direction, raycastHits, maxDistance, layerMask, triggerInteraction);
|
||
|
for (int i = 0; i < num; i++)
|
||
|
{
|
||
|
RaycastHit raycastHit = raycastHits[i];
|
||
|
if (IsValidHitColliderUnsafe(data, raycastHit.collider))
|
||
|
{
|
||
|
shapeCastInfo.AddHit(raycastHit);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return shapeCastInfo.AllHitCount > 0;
|
||
|
}
|
||
|
|
||
|
private bool SphereCast(KCCShapeCastInfo shapeCastInfo, KCCData data, Vector3 position, float radius, float extent, Vector3 direction, float maxDistance, LayerMask layerMask, QueryTriggerInteraction triggerInteraction, bool trackInitialOverlaps)
|
||
|
{
|
||
|
shapeCastInfo.Reset(deep: false);
|
||
|
shapeCastInfo.Position = position;
|
||
|
shapeCastInfo.Radius = radius;
|
||
|
shapeCastInfo.Extent = extent;
|
||
|
shapeCastInfo.Direction = direction;
|
||
|
shapeCastInfo.MaxDistance = maxDistance;
|
||
|
shapeCastInfo.LayerMask = layerMask;
|
||
|
shapeCastInfo.TriggerInteraction = triggerInteraction;
|
||
|
RaycastHit[] raycastHits = _raycastHits;
|
||
|
int num = base.Runner.GetPhysicsScene().SphereCast(position, radius + extent, direction, raycastHits, maxDistance, layerMask, triggerInteraction);
|
||
|
for (int i = 0; i < num; i++)
|
||
|
{
|
||
|
RaycastHit raycastHit = raycastHits[i];
|
||
|
if ((trackInitialOverlaps || !(raycastHit.distance <= 0f) || !raycastHit.point.Equals(default(Vector3))) && IsValidHitColliderUnsafe(data, raycastHit.collider))
|
||
|
{
|
||
|
shapeCastInfo.AddHit(raycastHit);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return shapeCastInfo.AllHitCount > 0;
|
||
|
}
|
||
|
|
||
|
private bool CapsuleCast(KCCShapeCastInfo shapeCastInfo, KCCData data, Vector3 position, float radius, float height, float extent, Vector3 direction, float maxDistance, LayerMask layerMask, QueryTriggerInteraction triggerInteraction, bool trackInitialOverlaps)
|
||
|
{
|
||
|
shapeCastInfo.Reset(deep: false);
|
||
|
shapeCastInfo.Position = position;
|
||
|
shapeCastInfo.Radius = radius;
|
||
|
shapeCastInfo.Height = height;
|
||
|
shapeCastInfo.Extent = extent;
|
||
|
shapeCastInfo.Position = position;
|
||
|
shapeCastInfo.Direction = direction;
|
||
|
shapeCastInfo.MaxDistance = maxDistance;
|
||
|
shapeCastInfo.LayerMask = layerMask;
|
||
|
shapeCastInfo.TriggerInteraction = triggerInteraction;
|
||
|
Vector3 point = position + new Vector3(0f, height - radius, 0f);
|
||
|
Vector3 point2 = position + new Vector3(0f, radius, 0f);
|
||
|
RaycastHit[] raycastHits = _raycastHits;
|
||
|
int num = base.Runner.GetPhysicsScene().CapsuleCast(point2, point, radius + extent, direction, raycastHits, maxDistance, layerMask, triggerInteraction);
|
||
|
for (int i = 0; i < num; i++)
|
||
|
{
|
||
|
RaycastHit raycastHit = raycastHits[i];
|
||
|
if ((trackInitialOverlaps || !(raycastHit.distance <= 0f) || !raycastHit.point.Equals(default(Vector3))) && IsValidHitColliderUnsafe(data, raycastHit.collider))
|
||
|
{
|
||
|
shapeCastInfo.AddHit(raycastHit);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return shapeCastInfo.AllHitCount > 0;
|
||
|
}
|
||
|
|
||
|
private void UpdateHits(KCCData data, KCCOverlapInfo baseOverlapInfo, EKCCHitsOverlapQuery overlapQuery)
|
||
|
{
|
||
|
if (overlapQuery switch
|
||
|
{
|
||
|
EKCCHitsOverlapQuery.Default => baseOverlapInfo?.AllHitsWithinExtent() ?? false,
|
||
|
EKCCHitsOverlapQuery.Reuse => baseOverlapInfo != null,
|
||
|
EKCCHitsOverlapQuery.New => false,
|
||
|
_ => throw new NotImplementedException("overlapQuery"),
|
||
|
})
|
||
|
{
|
||
|
_trackOverlapInfo.CopyFromOther(baseOverlapInfo);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
CapsuleOverlap(_trackOverlapInfo, data, data.TargetPosition, _settings.Radius, _settings.Height, _settings.Extent, _settings.CollisionLayerMask, QueryTriggerInteraction.Collide);
|
||
|
if (baseOverlapInfo != null)
|
||
|
{
|
||
|
for (int i = 0; i < _trackOverlapInfo.AllHitCount; i++)
|
||
|
{
|
||
|
KCCOverlapHit kCCOverlapHit = _trackOverlapInfo.AllHits[i];
|
||
|
for (int j = 0; j < baseOverlapInfo.AllHitCount; j++)
|
||
|
{
|
||
|
KCCOverlapHit kCCOverlapHit2 = baseOverlapInfo.AllHits[j];
|
||
|
if ((object)kCCOverlapHit.Collider == kCCOverlapHit2.Collider)
|
||
|
{
|
||
|
kCCOverlapHit.CopyFromOther(kCCOverlapHit2);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
data.Hits.Clear();
|
||
|
int k = 0;
|
||
|
for (int allHitCount = _trackOverlapInfo.AllHitCount; k < allHitCount; k++)
|
||
|
{
|
||
|
data.Hits.Add(_trackOverlapInfo.AllHits[k]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void ForceRemoveAllHits(KCCData data)
|
||
|
{
|
||
|
_trackOverlapInfo.Reset(deep: false);
|
||
|
_extendedOverlapInfo.Reset(deep: false);
|
||
|
data.Hits.Clear();
|
||
|
}
|
||
|
|
||
|
private bool IsValidHitCollider(KCCData data, Collider hitCollider)
|
||
|
{
|
||
|
if (hitCollider == _collider.Collider)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
int i = 0;
|
||
|
for (int count = _childColliders.Count; i < count; i++)
|
||
|
{
|
||
|
if (hitCollider == _childColliders[i])
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int num = 1 << hitCollider.gameObject.layer;
|
||
|
if (((int)_settings.CollisionLayerMask & num) != num)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (ResolveCollision != null)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
return ResolveCollision(this, hitCollider);
|
||
|
}
|
||
|
catch (Exception exception)
|
||
|
{
|
||
|
Debug.LogException(exception);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
private bool IsValidHitColliderUnsafe(KCCData data, Collider overlapCollider)
|
||
|
{
|
||
|
if ((object)overlapCollider == _collider.Collider)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
int i = 0;
|
||
|
for (int count = _childColliders.Count; i < count; i++)
|
||
|
{
|
||
|
if ((object)overlapCollider == _childColliders[i])
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (ResolveCollision != null)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
return ResolveCollision(this, overlapCollider);
|
||
|
}
|
||
|
catch (Exception exception)
|
||
|
{
|
||
|
Debug.LogException(exception);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public void SetMaxGroundAngle(float maxGroundAngle)
|
||
|
{
|
||
|
if (IsSpawned)
|
||
|
{
|
||
|
Data.MaxGroundAngle = maxGroundAngle;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void SetGravity(float gravity)
|
||
|
{
|
||
|
if (IsSpawned)
|
||
|
{
|
||
|
Data.Gravity = Vector3.up * gravity;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void Move(Vector3 kinematicVelocity = default(Vector3), float jumpImpulse = 0f)
|
||
|
{
|
||
|
if (IsSpawned)
|
||
|
{
|
||
|
if (!IsInFixedUpdate)
|
||
|
{
|
||
|
throw new InvalidOperationException("[" + base.name + "] Move can be invoked only from within fixed update!");
|
||
|
}
|
||
|
|
||
|
FixedData.KinematicVelocity = kinematicVelocity;
|
||
|
FixedData.JumpImpulse += Vector3.up * jumpImpulse;
|
||
|
ManualFixedUpdate();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public bool ProjectOnGround(Vector3 vector, out Vector3 projectedVector)
|
||
|
{
|
||
|
KCCData data = Data;
|
||
|
if (data.IsGrounded)
|
||
|
{
|
||
|
return KCCPhysicsUtility.ProjectOnGround(data.GroundNormal, vector, out projectedVector);
|
||
|
}
|
||
|
|
||
|
projectedVector = default(Vector3);
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|