using System; using UnityEngine; namespace Fusion.Addons.SimpleKCC { [Serializable] public sealed class KCCSettings { internal static readonly float ExtrapolationDeltaTimeThreshold = 5E-05f; [Header("General")] [Tooltip("Defines KCC physics behavior.\n• None - Skips internal physics query, collider is despawned.\n• Capsule - Full physics processing, Capsule collider spawned.")] public EKCCShape Shape = EKCCShape.Capsule; [Tooltip("Sets collider isTrigger.")] public bool IsTrigger; [Tooltip("Sets collider radius.")] public float Radius = 0.35f; [Tooltip("Sets collider height.")] public float Height = 1.8f; [Tooltip("Defines additional radius extent for ground detection and processors tracking. Recommended range is 10-20% of radius.\n• Low value decreases stability and has potential performance impact when executing additional checks.\n• High value increases stability at the cost of increased sustained performance impact.")] public float Extent = 0.035f; [Tooltip("Sets layer of collider game object.")] [KCCLayer] public int ColliderLayer; [Tooltip("Layer mask the KCC collides with.")] public LayerMask CollisionLayerMask = 1; [Tooltip("Defines interpolation behavior. Proxies predicted in fixed update are always fully interpolated.\n• Full - Interpolates all networked properties, synchronizes Transform and Rigidbody components everytime interpolation is triggered.\n• Transform - Interpolates only position and rotation and synchronizes Transform component. This mode is fastest, but most KCC settings properties won't be synchronized. Use with caution!")] public EKCCInterpolationMode ProxyInterpolationMode; [Tooltip("Defines minimum distance the KCC must move in a single tick to treat the movement as instant (teleport). Affects interpolation and other KCC features.")] public float TeleportThreshold = 1f; [Tooltip("Single Move/CCD step is split into multiple smaller sub-steps which results in higher overall depenetration quality.")] [Range(1f, 16f)] internal int MaxPenetrationSteps = 8; [Tooltip("Controls maximum distance the KCC moves in a single CCD step. Valid range is 25% - 75% of the radius. Use lower values if the character passes through geometry.\nThis setting is valid only when EKCCFeature.CCD is enabled. CCD Max Step Distance = Radius * CCD Radius Multiplier")] [Range(0.25f, 0.75f)] internal float CCDRadiusMultiplier = 0.75f; [Tooltip("Defines render position distance tolerance to smooth out jitter. Higher values may introduce noticeable delay when switching move direction.\n• X = Horizontal axis.\n• Y = Vertical axis.")] public Vector2 AntiJitterDistance = new Vector2(0.025f, 0.01f); [Tooltip("How fast prediction error interpolates towards zero.")] internal float PredictionCorrectionSpeed = 30f; [Tooltip("Reduces network traffic by synchronizing compressed position at the cost of precision. Useful for non-player characters.")] public bool CompressNetworkPosition; [Tooltip("This skips look rotation interpolation in render for local character and can be used for extra look responsiveness with other properties being interpolated.")] public bool ForcePredictedLookRotation; [Tooltip("Enable to always check collisions against non-convex mesh colliders to prevent ghost collisions and incorrect penetration vectors.")] internal bool SuppressConvexMeshColliders; [Header("Step Detection")] [Tooltip("Maximum obstacle height to step on it.")] public float StepHeight = 0.5f; [Tooltip("Maximum depth of the step check.")] public float StepDepth = 0.2f; [Tooltip("Multiplier of unapplied movement projected to step up. This helps traversing obstacles faster.")] public float StepSpeed = 1f; [SerializeField] [Tooltip("Minimum proportional penetration push-back distance to activate step-up. A value of 0.5f means the KCC must be pushed back from colliding geometry by at least 50% of desired movement.")] [Range(0.25f, 0.75f)] public float StepMinPushBack = 0.5f; [SerializeField] [Tooltip("Radius multiplier used for last sphere-cast (ground surface detection). Lower value work better with shorter step depth.")] [Range(0.25f, 1f)] public float StepGroundCheckRadiusScale = 0.5f; [SerializeField] [Tooltip("Step-up starts only if the target surface is walkable (angle <= MaxGroundAngle).")] public bool StepRequireGroundTarget; [Header("Ground Snapping")] [Tooltip("Maximum ground check distance for snapping.")] public float SnapDistance = 0.25f; [Tooltip("Ground snapping speed per second.")] public float SnapSpeed = 4f; public void CopyFromOther(KCCSettings other) { Shape = other.Shape; IsTrigger = other.IsTrigger; Radius = other.Radius; Height = other.Height; Extent = other.Extent; ColliderLayer = other.ColliderLayer; CollisionLayerMask = other.CollisionLayerMask; ProxyInterpolationMode = other.ProxyInterpolationMode; TeleportThreshold = other.TeleportThreshold; MaxPenetrationSteps = other.MaxPenetrationSteps; CCDRadiusMultiplier = other.CCDRadiusMultiplier; AntiJitterDistance = other.AntiJitterDistance; PredictionCorrectionSpeed = other.PredictionCorrectionSpeed; CompressNetworkPosition = other.CompressNetworkPosition; ForcePredictedLookRotation = other.ForcePredictedLookRotation; SuppressConvexMeshColliders = other.SuppressConvexMeshColliders; StepHeight = other.StepHeight; StepDepth = other.StepDepth; StepSpeed = other.StepSpeed; StepMinPushBack = other.StepMinPushBack; StepGroundCheckRadiusScale = other.StepGroundCheckRadiusScale; StepRequireGroundTarget = other.StepRequireGroundTarget; SnapDistance = other.SnapDistance; SnapSpeed = other.SnapSpeed; } } }