620 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			620 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | namespace Fusion.Addons.KCC | ||
|  | { | ||
|  | 	using UnityEngine; | ||
|  | 
 | ||
|  | 	/// <summary> | ||
|  | 	/// Main data structure used for movement calculations. Stores data which require rollback, network synchronization + various metadata. | ||
|  | 	/// </summary> | ||
|  | 	public sealed partial class KCCData | ||
|  | 	{ | ||
|  | 		// PUBLIC MEMBERS | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Frame number, equals to <c>Time.frameCount</c>. | ||
|  | 		/// </summary> | ||
|  | 		public int Frame; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Tick number, equals to <c>Simulation.Tick</c> or calculated fixed update frame count. | ||
|  | 		/// </summary> | ||
|  | 		public int Tick; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Relative position of the time between two fixed times. Valid range is <0.0f, 1.0f> | ||
|  | 		/// </summary> | ||
|  | 		public float Alpha; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Current time, equals to <c>NetworkRunner.SimulationTime</c> or <c>NetworkRunner.SimulationRenderTime</c> or variable if CCD is active. | ||
|  | 		/// </summary> | ||
|  | 		public float Time; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Partial delta time, variable if CCD is active. Valid range is <<c>0.0f, UpdateDeltaTime</c>>, but can be altered. | ||
|  | 		/// </summary> | ||
|  | 		public float DeltaTime; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Delta time of full update/tick (CCD independent). | ||
|  | 	    /// <list type="number"> | ||
|  | 	    /// <item><description>FixedUpdate => FixedUpdate</description></item> | ||
|  | 	    /// <item><description>FixedUpdate => Render</description></item> | ||
|  | 	    /// <item><description>Render => Render</description></item> | ||
|  | 	    /// </list> | ||
|  | 		/// </summary> | ||
|  | 		public float UpdateDeltaTime; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Controls execution of the KCC. | ||
|  | 		/// </summary> | ||
|  | 		public bool IsActive = true; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Base position, initialized with TargetPosition at the start of each KCC step. | ||
|  | 		/// </summary> | ||
|  | 		public Vector3 BasePosition; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Desired position before depenetration and post-processing. | ||
|  | 		/// </summary> | ||
|  | 		public Vector3 DesiredPosition; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Calculated or explicitly set position which is propagated to <c>Transform</c>. | ||
|  | 		/// </summary> | ||
|  | 		public Vector3 TargetPosition; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Explicitly set look pitch rotation, this should propagate to camera rotation. | ||
|  | 		/// </summary> | ||
|  | 		public float LookPitch | ||
|  | 		{ | ||
|  | 			get { return _lookPitch; } | ||
|  | 			set | ||
|  | 			{ | ||
|  | 				if (_lookPitch != value) | ||
|  | 				{ | ||
|  | 					_lookPitch               = value; | ||
|  | 					_lookRotationCalculated  = false; | ||
|  | 					_lookDirectionCalculated = false; | ||
|  | 				} | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Explicitly set look yaw rotation, this should propagate to camera and transform rotation. | ||
|  | 		/// </summary> | ||
|  | 		public float LookYaw | ||
|  | 		{ | ||
|  | 			get { return _lookYaw; } | ||
|  | 			set | ||
|  | 			{ | ||
|  | 				if (_lookYaw != value) | ||
|  | 				{ | ||
|  | 					_lookYaw                       = value; | ||
|  | 					_lookRotationCalculated        = false; | ||
|  | 					_lookDirectionCalculated       = false; | ||
|  | 					_transformRotationCalculated   = false; | ||
|  | 					_transformDirectionCalculated  = false; | ||
|  | 				} | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Combination of <c>LookPitch</c> and <c>LookYaw</c>. | ||
|  | 		/// </summary> | ||
|  | 		public Quaternion LookRotation | ||
|  | 		{ | ||
|  | 			get | ||
|  | 			{ | ||
|  | 				if (_lookRotationCalculated == false) | ||
|  | 				{ | ||
|  | 					_lookRotation           = Quaternion.Euler(_lookPitch, _lookYaw, 0.0f); | ||
|  | 					_lookRotationCalculated = true; | ||
|  | 				} | ||
|  | 
 | ||
|  | 				return _lookRotation; | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Calculated and cached look direction based on <c>LookRotation</c>. | ||
|  | 		/// </summary> | ||
|  | 		public Vector3 LookDirection | ||
|  | 		{ | ||
|  | 			get | ||
|  | 			{ | ||
|  | 				if (_lookDirectionCalculated == false) | ||
|  | 				{ | ||
|  | 					_lookDirection           = LookRotation * Vector3.forward; | ||
|  | 					_lookDirectionCalculated = true; | ||
|  | 				} | ||
|  | 
 | ||
|  | 				return _lookDirection; | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Calculated and cached transform rotation based on Yaw look rotation. | ||
|  | 		/// </summary> | ||
|  | 		public Quaternion TransformRotation | ||
|  | 		{ | ||
|  | 			get | ||
|  | 			{ | ||
|  | 				if (_transformRotationCalculated == false) | ||
|  | 				{ | ||
|  | 					_transformRotation           = Quaternion.Euler(0.0f, _lookYaw, 0.0f); | ||
|  | 					_transformRotationCalculated = true; | ||
|  | 				} | ||
|  | 
 | ||
|  | 				return _transformRotation; | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Calculated and cached transform direction based on <c>TransformRotation</c>. | ||
|  | 		/// </summary> | ||
|  | 		public Vector3 TransformDirection | ||
|  | 		{ | ||
|  | 			get | ||
|  | 			{ | ||
|  | 				if (_transformDirectionCalculated == false) | ||
|  | 				{ | ||
|  | 					_transformDirection           = TransformRotation * Vector3.forward; | ||
|  | 					_transformDirectionCalculated = true; | ||
|  | 				} | ||
|  | 
 | ||
|  | 				return _transformDirection; | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Non-interpolated world space input direction - based on Keyboard / Joystick / NavMesh / ... | ||
|  | 		/// </summary> | ||
|  | 		public Vector3 InputDirection; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// One-time world space jump impulse based on input. | ||
|  | 		/// </summary> | ||
|  | 		public Vector3 JumpImpulse; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Gravitational acceleration. | ||
|  | 		/// </summary> | ||
|  | 		public Vector3 Gravity; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Maximum angle between KCC up direction and ground normal (depenetration vector) in degrees. Valid range is <0, 90>. Default is 75. | ||
|  | 		/// </summary> | ||
|  | 		public float MaxGroundAngle; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Maximum angle between KCC up direction and wall surface (perpendicular to depenetration vector) in degrees. Valid range is <0, MaxGroundAngle> Default is 5. | ||
|  | 		/// </summary> | ||
|  | 		public float MaxWallAngle; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Maximum angle between KCC up direction and hang surface (perpendicular to depenetration vector) in degrees. Valid range is <MaxWallAngle, 90> Default is 30. | ||
|  | 		/// </summary> | ||
|  | 		public float MaxHangAngle; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Single Move/CCD step is split into multiple smaller sub-steps which results in higher overall depenetration quality. | ||
|  | 		/// </summary> | ||
|  | 		public int MaxPenetrationSteps; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Velocity from external sources, one-time effect - reseted on the end of <c>Move()</c> call to prevent subsequent applications in render, ignoring <c>Mass</c>, example usage - jump pad. | ||
|  | 		/// </summary> | ||
|  | 		public Vector3 ExternalVelocity; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Acceleration from external sources, continuous effect - value remains same for subsequent applications in render, ignoring <c>Mass</c>, example usage - escalator. | ||
|  | 		/// </summary> | ||
|  | 		public Vector3 ExternalAcceleration; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Impulse from external sources, one-time effect - reseted on the end of <c>Move()</c> call to prevent subsequent applications in render, affected by <c>Mass</c>, example usage - explosion. | ||
|  | 		/// </summary> | ||
|  | 		public Vector3 ExternalImpulse; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Force from external sources, continuous effect - value remains same for subsequent applications in render, affected by Mass, example usage - attractor. | ||
|  | 		/// </summary> | ||
|  | 		public Vector3 ExternalForce; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Absolute position delta which is consumed by single move. It can also be set from ProcessPhysicsQuery and still consumed by currently executed move (useful for depenetration corrections). | ||
|  | 		/// </summary> | ||
|  | 		public Vector3 ExternalDelta; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Speed used to calculate <c>KinematicVelocity</c>. | ||
|  | 		/// </summary> | ||
|  | 		public float KinematicSpeed; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Calculated kinematic tangent, based on <c>KinematicDirection</c> and affected by other factors like ground normal, used to calculate <c>KinematicVelocity</c>. | ||
|  | 		/// </summary> | ||
|  | 		public Vector3 KinematicTangent; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Desired kinematic direction, based on <c>InputDirection</c> and other factors, used to calculate <c>KinematicVelocity</c>. | ||
|  | 		/// </summary> | ||
|  | 		public Vector3 KinematicDirection; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Velocity calculated from <c>InputDirection</c>, <c>KinematicDirection</c>, <c>KinematicTangent</c> and <c>KinematicSpeed</c>. | ||
|  | 		/// </summary> | ||
|  | 		public Vector3 KinematicVelocity; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Velocity calculated from <c>Gravity</c>, <c>ExternalVelocity</c>, <c>ExternalAcceleration</c>, <c>ExternalImpulse</c>, <c>ExternalForce</c> and <c>JumpImpulse</c>. | ||
|  | 		/// </summary> | ||
|  | 		public Vector3 DynamicVelocity; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Final calculated velocity used for position change, combined <c>KinematicVelocity</c> and <c>DynamicVelocity</c>. | ||
|  | 		/// </summary> | ||
|  | 		public Vector3 DesiredVelocity => KinematicVelocity + DynamicVelocity; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Speed calculated from real position change. | ||
|  | 		/// </summary> | ||
|  | 		public float RealSpeed; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Velocity calculated from real position change. | ||
|  | 		/// </summary> | ||
|  | 		public Vector3 RealVelocity; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Counter in how many frames the JumpImpulse was applied in a row. | ||
|  | 		/// Fixed update have 1 at max. In render update value higher than 1 indicates that jump happened in earlier render frame and should be processed next fixed update as well. | ||
|  | 		/// </summary> | ||
|  | 		public int JumpFrames; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Flag that indicates KCC has jumped in current tick/frame. | ||
|  | 		/// </summary> | ||
|  | 		public bool HasJumped => JumpFrames == 1; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Flag that indicates KCC has teleported in current tick. | ||
|  | 		/// </summary> | ||
|  | 		public bool HasTeleported; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Flag that indicates KCC is touching a collider with normal angle lower than <c>MaxGroundAngle</c>. | ||
|  | 		/// </summary> | ||
|  | 		public bool IsGrounded; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Same as IsGrounded previous tick or physics query. | ||
|  | 		/// </summary> | ||
|  | 		public bool WasGrounded; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Indicates the KCC temporarily or permanently lost grounded state. | ||
|  | 		/// </summary> | ||
|  | 		public bool IsOnEdge => IsGrounded == false && WasGrounded == true; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Indicates the KCC is stepping up. | ||
|  | 		/// </summary> | ||
|  | 		public bool IsSteppingUp; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Same as IsSteppingUp previous tick or physics query. | ||
|  | 		/// </summary> | ||
|  | 		public bool WasSteppingUp; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Indicates the KCC temporarily lost grounded state and is snapping to ground. | ||
|  | 		/// </summary> | ||
|  | 		public bool IsSnappingToGround; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Same as IsSnappingToGround previous tick or physics query. | ||
|  | 		/// </summary> | ||
|  | 		public bool WasSnappingToGround; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Combined normal of all touching colliders. Normals less distant from up direction have bigger impacton final normal. | ||
|  | 		/// </summary> | ||
|  | 		public Vector3 GroundNormal; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Tangent to <c>GroundNormal</c>, can be calculated from <c>DesiredVelocity</c> or <c>TargetRotation</c> if <c>GroundNormal</c> and up direction is same. | ||
|  | 		/// </summary> | ||
|  | 		public Vector3 GroundTangent; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Position of the KCC collider surface touching the ground collider. | ||
|  | 		/// </summary> | ||
|  | 		public Vector3 GroundPosition; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Distance from ground. | ||
|  | 		/// </summary> | ||
|  | 		public float GroundDistance; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Difference between ground normal and up direction in degrees. | ||
|  | 		/// </summary> | ||
|  | 		public float GroundAngle; | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Collection of networked collisions. Represents colliders the KCC interacts with. | ||
|  | 		/// Only objects with NetworkObject component are stored for compatibility with local prediction. | ||
|  | 		/// </summary> | ||
|  | 		public readonly KCCCollisions Collisions = new KCCCollisions(); | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Collection of manually registered modifiers (for example processors) the KCC interacts with. | ||
|  | 		/// Only objects with NetworkObject component are stored for compatibility with local prediction. | ||
|  | 		/// </summary> | ||
|  | 		public readonly KCCModifiers Modifiers = new KCCModifiers(); | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Collection of ignored colliders. | ||
|  | 		/// Only objects with NetworkObject component are stored for compatibility with local prediction. | ||
|  | 		/// </summary> | ||
|  | 		public readonly KCCIgnores Ignores = new KCCIgnores(); | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Collection of colliders/triggers the KCC overlaps (radius + extent). | ||
|  | 		/// This collection is not synchronized over the network! NetworkObject component is not needed, only local history is supported. | ||
|  | 		/// </summary> | ||
|  | 		public readonly KCCHits Hits = new KCCHits(); | ||
|  | 
 | ||
|  | 		// PRIVATE MEMBERS | ||
|  | 
 | ||
|  | 		private float      _lookPitch; | ||
|  | 		private float      _lookYaw; | ||
|  | 		private Quaternion _lookRotation; | ||
|  | 		private bool       _lookRotationCalculated; | ||
|  | 		private Vector3    _lookDirection; | ||
|  | 		private bool       _lookDirectionCalculated; | ||
|  | 		private Quaternion _transformRotation; | ||
|  | 		private bool       _transformRotationCalculated; | ||
|  | 		private Vector3    _transformDirection; | ||
|  | 		private bool       _transformDirectionCalculated; | ||
|  | 
 | ||
|  | 		// PUBLIC METHODS | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Returns the look rotation vector with selected axes. | ||
|  | 		/// </summary> | ||
|  | 		public Vector2 GetLookRotation(bool pitch = true, bool yaw = true) | ||
|  | 		{ | ||
|  | 			Vector2 lookRotation = default; | ||
|  | 
 | ||
|  | 			if (pitch == true) { lookRotation.x = _lookPitch; } | ||
|  | 			if (yaw   == true) { lookRotation.y = _lookYaw;   } | ||
|  | 
 | ||
|  | 			return lookRotation; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Add pitch and yaw look rotation. Resulting values are clamped to <-90, 90> (pitch) and <-180, 180> (yaw). | ||
|  | 		/// Changes are not propagated to Transform component. | ||
|  | 		/// </summary> | ||
|  | 		public void AddLookRotation(float pitchDelta, float yawDelta) | ||
|  | 		{ | ||
|  | 			if (pitchDelta != 0.0f) | ||
|  | 			{ | ||
|  | 				LookPitch = Mathf.Clamp(LookPitch + pitchDelta, -90.0f, 90.0f); | ||
|  | 			} | ||
|  | 
 | ||
|  | 			if (yawDelta != 0.0f) | ||
|  | 			{ | ||
|  | 				float lookYaw = LookYaw + yawDelta; | ||
|  | 				while (lookYaw > 180.0f) | ||
|  | 				{ | ||
|  | 					lookYaw -= 360.0f; | ||
|  | 				} | ||
|  | 				while (lookYaw < -180.0f) | ||
|  | 				{ | ||
|  | 					lookYaw += 360.0f; | ||
|  | 				} | ||
|  | 
 | ||
|  | 				LookYaw = lookYaw; | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Add pitch and yaw look rotation. Resulting values are clamped to <minPitch, maxPitch> (pitch) and <-180, 180> (yaw). | ||
|  | 		/// Changes are not propagated to Transform component. | ||
|  | 		/// </summary> | ||
|  | 		public void AddLookRotation(float pitchDelta, float yawDelta, float minPitch, float maxPitch) | ||
|  | 		{ | ||
|  | 			if (pitchDelta != 0.0f) | ||
|  | 			{ | ||
|  | 				if (minPitch < -90.0f) { minPitch = -90.0f; } | ||
|  | 				if (maxPitch >  90.0f) { maxPitch =  90.0f; } | ||
|  | 
 | ||
|  | 				if (maxPitch < minPitch) { maxPitch = minPitch; } | ||
|  | 
 | ||
|  | 				LookPitch = Mathf.Clamp(LookPitch + pitchDelta, minPitch, maxPitch); | ||
|  | 			} | ||
|  | 
 | ||
|  | 			if (yawDelta != 0.0f) | ||
|  | 			{ | ||
|  | 				float lookYaw = LookYaw + yawDelta; | ||
|  | 				while (lookYaw > 180.0f) | ||
|  | 				{ | ||
|  | 					lookYaw -= 360.0f; | ||
|  | 				} | ||
|  | 				while (lookYaw < -180.0f) | ||
|  | 				{ | ||
|  | 					lookYaw += 360.0f; | ||
|  | 				} | ||
|  | 
 | ||
|  | 				LookYaw = lookYaw; | ||
|  | 			} | ||
|  | 		} | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Add pitch (x) and yaw (y) look rotation. Resulting values are clamped to <-90, 90> (pitch) and <-180, 180> (yaw). | ||
|  | 		/// Changes are not propagated to Transform component. | ||
|  | 		/// </summary> | ||
|  | 		public void AddLookRotation(Vector2 lookRotationDelta) | ||
|  | 		{ | ||
|  | 			AddLookRotation(lookRotationDelta.x, lookRotationDelta.y); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Add pitch (x) and yaw (y) look rotation. Resulting values are clamped to <minPitch, maxPitch> (pitch) and <-180, 180> (yaw). | ||
|  | 		/// Changes are not propagated to Transform component. | ||
|  | 		/// </summary> | ||
|  | 		public void AddLookRotation(Vector2 lookRotationDelta, float minPitch, float maxPitch) | ||
|  | 		{ | ||
|  | 			AddLookRotation(lookRotationDelta.x, lookRotationDelta.y, minPitch, maxPitch); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Set pitch and yaw look rotation. Values are clamped to <-90, 90> (pitch) and <-180, 180> (yaw). | ||
|  | 		/// Changes are not propagated to Transform component. | ||
|  | 		/// </summary> | ||
|  | 		public void SetLookRotation(float pitch, float yaw) | ||
|  | 		{ | ||
|  | 			KCCUtility.ClampLookRotationAngles(ref pitch, ref yaw); | ||
|  | 
 | ||
|  | 			LookPitch = pitch; | ||
|  | 			LookYaw   = yaw; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Set pitch and yaw look rotation. Values are clamped to <minPitch, maxPitch> (pitch) and <-180, 180> (yaw). | ||
|  | 		/// Changes are not propagated to Transform component. | ||
|  | 		/// </summary> | ||
|  | 		public void SetLookRotation(float pitch, float yaw, float minPitch, float maxPitch) | ||
|  | 		{ | ||
|  | 			KCCUtility.ClampLookRotationAngles(ref pitch, ref yaw, minPitch, maxPitch); | ||
|  | 
 | ||
|  | 			LookPitch = pitch; | ||
|  | 			LookYaw   = yaw; | ||
|  | 		} | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Set pitch (x) and yaw (y) look rotation. Values are clamped to <-90, 90> (pitch) and <-180, 180> (yaw). | ||
|  | 		/// Changes are not propagated to Transform component. | ||
|  | 		/// </summary> | ||
|  | 		public void SetLookRotation(Vector2 lookRotation) | ||
|  | 		{ | ||
|  | 			SetLookRotation(lookRotation.x, lookRotation.y); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Set pitch (x) and yaw (y) look rotation. Values are clamped to <minPitch, maxPitch> (pitch) and <-180, 180> (yaw). | ||
|  | 		/// Changes are not propagated to Transform component. | ||
|  | 		/// </summary> | ||
|  | 		public void SetLookRotation(Vector2 lookRotation, float minPitch, float maxPitch) | ||
|  | 		{ | ||
|  | 			SetLookRotation(lookRotation.x, lookRotation.y, minPitch, maxPitch); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Set pitch and yaw look rotation. Roll is ignored (not supported). Values are clamped to <-90, 90> (pitch) and <-180, 180> (yaw). | ||
|  | 		/// Changes are not propagated to Transform component. | ||
|  | 		/// </summary> | ||
|  | 		public void SetLookRotation(Quaternion lookRotation, bool preservePitch = false, bool preserveYaw = false) | ||
|  | 		{ | ||
|  | 			KCCUtility.GetClampedLookRotationAngles(lookRotation, out float pitch, out float yaw); | ||
|  | 
 | ||
|  | 			if (preservePitch == false) { LookPitch = pitch; } | ||
|  | 			if (preserveYaw   == false) { LookYaw   = yaw;   } | ||
|  | 		} | ||
|  | 
 | ||
|  | 		/// <summary> | ||
|  | 		/// Clear all properties which should not propagate to next tick/frame if IsActive == false. | ||
|  | 		/// </summary> | ||
|  | 		public void ClearTransientProperties() | ||
|  | 		{ | ||
|  | 			JumpFrames           = default; | ||
|  | 			JumpImpulse          = default; | ||
|  | 			ExternalVelocity     = default; | ||
|  | 			ExternalAcceleration = default; | ||
|  | 			ExternalImpulse      = default; | ||
|  | 			ExternalForce        = default; | ||
|  | 
 | ||
|  | 			ClearUserTransientProperties(); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		public void Clear() | ||
|  | 		{ | ||
|  | 			ClearUserData(); | ||
|  | 
 | ||
|  | 			Collisions.Clear(); | ||
|  | 			Modifiers.Clear(); | ||
|  | 			Ignores.Clear(); | ||
|  | 			Hits.Clear(); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		public void CopyFromOther(KCCData other) | ||
|  | 		{ | ||
|  | 			Frame                        = other.Frame; | ||
|  | 			Tick                         = other.Tick; | ||
|  | 			Alpha                        = other.Alpha; | ||
|  | 			Time                         = other.Time; | ||
|  | 			DeltaTime                    = other.DeltaTime; | ||
|  | 			UpdateDeltaTime              = other.UpdateDeltaTime; | ||
|  | 			IsActive                     = other.IsActive; | ||
|  | 			BasePosition                 = other.BasePosition; | ||
|  | 			DesiredPosition              = other.DesiredPosition; | ||
|  | 			TargetPosition               = other.TargetPosition; | ||
|  | 			LookPitch                    = other.LookPitch; | ||
|  | 			LookYaw                      = other.LookYaw; | ||
|  | 
 | ||
|  | 			InputDirection               = other.InputDirection; | ||
|  | 			JumpImpulse                  = other.JumpImpulse; | ||
|  | 			Gravity                      = other.Gravity; | ||
|  | 			MaxGroundAngle               = other.MaxGroundAngle; | ||
|  | 			MaxWallAngle                 = other.MaxWallAngle; | ||
|  | 			MaxHangAngle                 = other.MaxHangAngle; | ||
|  | 			MaxPenetrationSteps          = other.MaxPenetrationSteps; | ||
|  | 			ExternalVelocity             = other.ExternalVelocity; | ||
|  | 			ExternalAcceleration         = other.ExternalAcceleration; | ||
|  | 			ExternalImpulse              = other.ExternalImpulse; | ||
|  | 			ExternalForce                = other.ExternalForce; | ||
|  | 			ExternalDelta                = other.ExternalDelta; | ||
|  | 
 | ||
|  | 			KinematicSpeed               = other.KinematicSpeed; | ||
|  | 			KinematicTangent             = other.KinematicTangent; | ||
|  | 			KinematicDirection           = other.KinematicDirection; | ||
|  | 			KinematicVelocity            = other.KinematicVelocity; | ||
|  | 			DynamicVelocity              = other.DynamicVelocity; | ||
|  | 
 | ||
|  | 			RealSpeed                    = other.RealSpeed; | ||
|  | 			RealVelocity                 = other.RealVelocity; | ||
|  | 			JumpFrames                   = other.JumpFrames; | ||
|  | 			HasTeleported                = other.HasTeleported; | ||
|  | 			IsGrounded                   = other.IsGrounded; | ||
|  | 			WasGrounded                  = other.WasGrounded; | ||
|  | 			IsSteppingUp                 = other.IsSteppingUp; | ||
|  | 			WasSteppingUp                = other.WasSteppingUp; | ||
|  | 			IsSnappingToGround           = other.IsSnappingToGround; | ||
|  | 			WasSnappingToGround          = other.WasSnappingToGround; | ||
|  | 			GroundNormal                 = other.GroundNormal; | ||
|  | 			GroundTangent                = other.GroundTangent; | ||
|  | 			GroundPosition               = other.GroundPosition; | ||
|  | 			GroundDistance               = other.GroundDistance; | ||
|  | 			GroundAngle                  = other.GroundAngle; | ||
|  | 
 | ||
|  | 			Collisions.CopyFromOther(other.Collisions); | ||
|  | 			Modifiers.CopyFromOther(other.Modifiers); | ||
|  | 			Ignores.CopyFromOther(other.Ignores); | ||
|  | 			Hits.CopyFromOther(other.Hits); | ||
|  | 
 | ||
|  | 			CopyUserDataFromOther(other); | ||
|  | 		} | ||
|  | 
 | ||
|  | 		// PARTIAL METHODS | ||
|  | 
 | ||
|  | 		partial void ClearUserTransientProperties(); | ||
|  | 		partial void ClearUserData(); | ||
|  | 		partial void CopyUserDataFromOther(KCCData other); | ||
|  | 	} | ||
|  | } |