mirror of
https://github.com/nothke/quality-control.git
synced 2025-08-30 23:43:42 +00:00
Added KCC
This commit is contained in:
10
Assets/Plugins/KinematicCharacterController/Core/Editor.meta
Normal file
10
Assets/Plugins/KinematicCharacterController/Core/Editor.meta
Normal file
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 220667f043f505a4eb52d0208e14818e
|
||||
folderAsset: yes
|
||||
timeCreated: 1504492780
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "KCC.Editor",
|
||||
"references": [
|
||||
"GUID:1bf68a6e05395544c9eb0c8d1ab94588"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8b7c931d99dfb09428a98748ecfd6169
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,28 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace KinematicCharacterController
|
||||
{
|
||||
[CustomEditor(typeof(KinematicCharacterMotor))]
|
||||
public class KinematicCharacterMotorEditor : Editor
|
||||
{
|
||||
protected virtual void OnSceneGUI()
|
||||
{
|
||||
KinematicCharacterMotor motor = (target as KinematicCharacterMotor);
|
||||
if (motor)
|
||||
{
|
||||
Vector3 characterBottom = motor.transform.position + (motor.Capsule.center + (-Vector3.up * (motor.Capsule.height * 0.5f)));
|
||||
|
||||
Handles.color = Color.yellow;
|
||||
Handles.CircleHandleCap(
|
||||
0,
|
||||
characterBottom + (motor.transform.up * motor.MaxStepHeight),
|
||||
Quaternion.LookRotation(motor.transform.up, motor.transform.forward),
|
||||
motor.Capsule.radius + 0.1f,
|
||||
EventType.Repaint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7db3ed6d74cbf2b489cab5e1586bed7a
|
||||
timeCreated: 1518400757
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,21 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace KinematicCharacterController
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(ReadOnlyAttribute))]
|
||||
public class ReadOnlyPropertyDrawer : PropertyDrawer
|
||||
{
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
return EditorGUI.GetPropertyHeight(property, label, true);
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
GUI.enabled = false;
|
||||
EditorGUI.PropertyField(position, property, label, true);
|
||||
GUI.enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d4351ab88853824b85a8f458928d825
|
||||
timeCreated: 1504492796
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,50 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace KinematicCharacterController
|
||||
{
|
||||
public interface ICharacterController
|
||||
{
|
||||
/// <summary>
|
||||
/// This is called when the motor wants to know what its rotation should be right now
|
||||
/// </summary>
|
||||
void UpdateRotation(ref Quaternion currentRotation, float deltaTime);
|
||||
/// <summary>
|
||||
/// This is called when the motor wants to know what its velocity should be right now
|
||||
/// </summary>
|
||||
void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime);
|
||||
/// <summary>
|
||||
/// This is called before the motor does anything
|
||||
/// </summary>
|
||||
void BeforeCharacterUpdate(float deltaTime);
|
||||
/// <summary>
|
||||
/// This is called after the motor has finished its ground probing, but before PhysicsMover/Velocity/etc.... handling
|
||||
/// </summary>
|
||||
void PostGroundingUpdate(float deltaTime);
|
||||
/// <summary>
|
||||
/// This is called after the motor has finished everything in its update
|
||||
/// </summary>
|
||||
void AfterCharacterUpdate(float deltaTime);
|
||||
/// <summary>
|
||||
/// This is called after when the motor wants to know if the collider can be collided with (or if we just go through it)
|
||||
/// </summary>
|
||||
bool IsColliderValidForCollisions(Collider coll);
|
||||
/// <summary>
|
||||
/// This is called when the motor's ground probing detects a ground hit
|
||||
/// </summary>
|
||||
void OnGroundHit(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint, ref HitStabilityReport hitStabilityReport);
|
||||
/// <summary>
|
||||
/// This is called when the motor's movement logic detects a hit
|
||||
/// </summary>
|
||||
void OnMovementHit(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint, ref HitStabilityReport hitStabilityReport);
|
||||
/// <summary>
|
||||
/// This is called after every move hit, to give you an opportunity to modify the HitStabilityReport to your liking
|
||||
/// </summary>
|
||||
void ProcessHitStabilityReport(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint, Vector3 atCharacterPosition, Quaternion atCharacterRotation, ref HitStabilityReport hitStabilityReport);
|
||||
/// <summary>
|
||||
/// This is called when the character detects discrete collisions (collisions that don't result from the motor's capsuleCasts when moving)
|
||||
/// </summary>
|
||||
void OnDiscreteCollisionDetected(Collider hitCollider);
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f13aa252bd3bf9943b1d65e68d93dcfb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,14 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace KinematicCharacterController
|
||||
{
|
||||
public interface IMoverController
|
||||
{
|
||||
/// <summary>
|
||||
/// This is called to let you tell the PhysicsMover where it should be right now
|
||||
/// </summary>
|
||||
void UpdateMovement(out Vector3 goalPosition, out Quaternion goalRotation, float deltaTime);
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8ae7eceec45f1be4c8450edc46c0ad36
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"name": "KCC"
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1bf68a6e05395544c9eb0c8d1ab94588
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,33 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace KinematicCharacterController
|
||||
{
|
||||
[CreateAssetMenu]
|
||||
public class KCCSettings : ScriptableObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines if the system simulates automatically.
|
||||
/// If true, the simulation is done on FixedUpdate
|
||||
/// </summary>
|
||||
[Tooltip("Determines if the system simulates automatically. If true, the simulation is done on FixedUpdate")]
|
||||
public bool AutoSimulation = true;
|
||||
/// <summary>
|
||||
/// Should interpolation of characters and PhysicsMovers be handled
|
||||
/// </summary>
|
||||
[Tooltip("Should interpolation of characters and PhysicsMovers be handled")]
|
||||
public bool Interpolate = true;
|
||||
/// <summary>
|
||||
|
||||
/// Initial capacity of the system's list of Motors (will resize automatically if needed, but setting a high initial capacity can help preventing GC allocs)
|
||||
/// </summary>
|
||||
[Tooltip("Initial capacity of the system's list of Motors (will resize automatically if needed, but setting a high initial capacity can help preventing GC allocs)")]
|
||||
public int MotorsListInitialCapacity = 100;
|
||||
/// <summary>
|
||||
/// Initial capacity of the system's list of Movers (will resize automatically if needed, but setting a high initial capacity can help preventing GC allocs)
|
||||
/// </summary>
|
||||
[Tooltip("Initial capacity of the system's list of Movers (will resize automatically if needed, but setting a high initial capacity can help preventing GC allocs)")]
|
||||
public int MoversListInitialCapacity = 100;
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2b43d8459fe4812488b2c47ac60e41c3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d1bc5515e3ab954e80599c538834774
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,294 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace KinematicCharacterController
|
||||
{
|
||||
/// <summary>
|
||||
/// The system that manages the simulation of KinematicCharacterMotor and PhysicsMover
|
||||
/// </summary>
|
||||
[DefaultExecutionOrder(-100)]
|
||||
public class KinematicCharacterSystem : MonoBehaviour
|
||||
{
|
||||
private static KinematicCharacterSystem _instance;
|
||||
|
||||
public static List<KinematicCharacterMotor> CharacterMotors = new List<KinematicCharacterMotor>();
|
||||
public static List<PhysicsMover> PhysicsMovers = new List<PhysicsMover>();
|
||||
|
||||
private static float _lastCustomInterpolationStartTime = -1f;
|
||||
private static float _lastCustomInterpolationDeltaTime = -1f;
|
||||
|
||||
public static KCCSettings Settings;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a KinematicCharacterSystem instance if there isn't already one
|
||||
/// </summary>
|
||||
public static void EnsureCreation()
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
GameObject systemGameObject = new GameObject("KinematicCharacterSystem");
|
||||
_instance = systemGameObject.AddComponent<KinematicCharacterSystem>();
|
||||
|
||||
systemGameObject.hideFlags = HideFlags.NotEditable;
|
||||
_instance.hideFlags = HideFlags.NotEditable;
|
||||
|
||||
Settings = ScriptableObject.CreateInstance<KCCSettings>();
|
||||
|
||||
GameObject.DontDestroyOnLoad(systemGameObject);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the KinematicCharacterSystem instance if any
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static KinematicCharacterSystem GetInstance()
|
||||
{
|
||||
return _instance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the maximum capacity of the character motors list, to prevent allocations when adding characters
|
||||
/// </summary>
|
||||
/// <param name="capacity"></param>
|
||||
public static void SetCharacterMotorsCapacity(int capacity)
|
||||
{
|
||||
if (capacity < CharacterMotors.Count)
|
||||
{
|
||||
capacity = CharacterMotors.Count;
|
||||
}
|
||||
CharacterMotors.Capacity = capacity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a KinematicCharacterMotor into the system
|
||||
/// </summary>
|
||||
public static void RegisterCharacterMotor(KinematicCharacterMotor motor)
|
||||
{
|
||||
CharacterMotors.Add(motor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters a KinematicCharacterMotor from the system
|
||||
/// </summary>
|
||||
public static void UnregisterCharacterMotor(KinematicCharacterMotor motor)
|
||||
{
|
||||
CharacterMotors.Remove(motor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the maximum capacity of the physics movers list, to prevent allocations when adding movers
|
||||
/// </summary>
|
||||
/// <param name="capacity"></param>
|
||||
public static void SetPhysicsMoversCapacity(int capacity)
|
||||
{
|
||||
if (capacity < PhysicsMovers.Count)
|
||||
{
|
||||
capacity = PhysicsMovers.Count;
|
||||
}
|
||||
PhysicsMovers.Capacity = capacity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers a PhysicsMover into the system
|
||||
/// </summary>
|
||||
public static void RegisterPhysicsMover(PhysicsMover mover)
|
||||
{
|
||||
PhysicsMovers.Add(mover);
|
||||
|
||||
mover.Rigidbody.interpolation = RigidbodyInterpolation.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unregisters a PhysicsMover from the system
|
||||
/// </summary>
|
||||
public static void UnregisterPhysicsMover(PhysicsMover mover)
|
||||
{
|
||||
PhysicsMovers.Remove(mover);
|
||||
}
|
||||
|
||||
// This is to prevent duplicating the singleton gameobject on script recompiles
|
||||
private void OnDisable()
|
||||
{
|
||||
Destroy(this.gameObject);
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_instance = this;
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
if (Settings.AutoSimulation)
|
||||
{
|
||||
float deltaTime = Time.deltaTime;
|
||||
|
||||
if (Settings.Interpolate)
|
||||
{
|
||||
PreSimulationInterpolationUpdate(deltaTime);
|
||||
}
|
||||
|
||||
Simulate(deltaTime, CharacterMotors, PhysicsMovers);
|
||||
|
||||
if (Settings.Interpolate)
|
||||
{
|
||||
PostSimulationInterpolationUpdate(deltaTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (Settings.Interpolate)
|
||||
{
|
||||
CustomInterpolationUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remembers the point to interpolate from for KinematicCharacterMotors and PhysicsMovers
|
||||
/// </summary>
|
||||
public static void PreSimulationInterpolationUpdate(float deltaTime)
|
||||
{
|
||||
// Save pre-simulation poses and place transform at transient pose
|
||||
for (int i = 0; i < CharacterMotors.Count; i++)
|
||||
{
|
||||
KinematicCharacterMotor motor = CharacterMotors[i];
|
||||
|
||||
motor.InitialTickPosition = motor.TransientPosition;
|
||||
motor.InitialTickRotation = motor.TransientRotation;
|
||||
|
||||
motor.Transform.SetPositionAndRotation(motor.TransientPosition, motor.TransientRotation);
|
||||
}
|
||||
|
||||
for (int i = 0; i < PhysicsMovers.Count; i++)
|
||||
{
|
||||
PhysicsMover mover = PhysicsMovers[i];
|
||||
|
||||
mover.InitialTickPosition = mover.TransientPosition;
|
||||
mover.InitialTickRotation = mover.TransientRotation;
|
||||
|
||||
mover.Transform.SetPositionAndRotation(mover.TransientPosition, mover.TransientRotation);
|
||||
mover.Rigidbody.position = mover.TransientPosition;
|
||||
mover.Rigidbody.rotation = mover.TransientRotation;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ticks characters and/or movers
|
||||
/// </summary>
|
||||
public static void Simulate(float deltaTime, List<KinematicCharacterMotor> motors, List<PhysicsMover> movers)
|
||||
{
|
||||
int characterMotorsCount = motors.Count;
|
||||
int physicsMoversCount = movers.Count;
|
||||
|
||||
#pragma warning disable 0162
|
||||
// Update PhysicsMover velocities
|
||||
for (int i = 0; i < physicsMoversCount; i++)
|
||||
{
|
||||
movers[i].VelocityUpdate(deltaTime);
|
||||
}
|
||||
|
||||
// Character controller update phase 1
|
||||
for (int i = 0; i < characterMotorsCount; i++)
|
||||
{
|
||||
motors[i].UpdatePhase1(deltaTime);
|
||||
}
|
||||
|
||||
// Simulate PhysicsMover displacement
|
||||
for (int i = 0; i < physicsMoversCount; i++)
|
||||
{
|
||||
PhysicsMover mover = movers[i];
|
||||
|
||||
mover.Transform.SetPositionAndRotation(mover.TransientPosition, mover.TransientRotation);
|
||||
mover.Rigidbody.position = mover.TransientPosition;
|
||||
mover.Rigidbody.rotation = mover.TransientRotation;
|
||||
}
|
||||
|
||||
// Character controller update phase 2 and move
|
||||
for (int i = 0; i < characterMotorsCount; i++)
|
||||
{
|
||||
KinematicCharacterMotor motor = motors[i];
|
||||
|
||||
motor.UpdatePhase2(deltaTime);
|
||||
|
||||
motor.Transform.SetPositionAndRotation(motor.TransientPosition, motor.TransientRotation);
|
||||
}
|
||||
#pragma warning restore 0162
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initiates the interpolation for KinematicCharacterMotors and PhysicsMovers
|
||||
/// </summary>
|
||||
public static void PostSimulationInterpolationUpdate(float deltaTime)
|
||||
{
|
||||
_lastCustomInterpolationStartTime = Time.time;
|
||||
_lastCustomInterpolationDeltaTime = deltaTime;
|
||||
|
||||
// Return interpolated roots to their initial poses
|
||||
for (int i = 0; i < CharacterMotors.Count; i++)
|
||||
{
|
||||
KinematicCharacterMotor motor = CharacterMotors[i];
|
||||
|
||||
motor.Transform.SetPositionAndRotation(motor.InitialTickPosition, motor.InitialTickRotation);
|
||||
}
|
||||
|
||||
for (int i = 0; i < PhysicsMovers.Count; i++)
|
||||
{
|
||||
PhysicsMover mover = PhysicsMovers[i];
|
||||
|
||||
if (mover.MoveWithPhysics)
|
||||
{
|
||||
mover.Rigidbody.position = mover.InitialTickPosition;
|
||||
mover.Rigidbody.rotation = mover.InitialTickRotation;
|
||||
|
||||
mover.Rigidbody.MovePosition(mover.TransientPosition);
|
||||
mover.Rigidbody.MoveRotation(mover.TransientRotation);
|
||||
}
|
||||
else
|
||||
{
|
||||
mover.Rigidbody.position = (mover.TransientPosition);
|
||||
mover.Rigidbody.rotation = (mover.TransientRotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles per-frame interpolation
|
||||
/// </summary>
|
||||
private static void CustomInterpolationUpdate()
|
||||
{
|
||||
float interpolationFactor = Mathf.Clamp01((Time.time - _lastCustomInterpolationStartTime) / _lastCustomInterpolationDeltaTime);
|
||||
|
||||
// Handle characters interpolation
|
||||
for (int i = 0; i < CharacterMotors.Count; i++)
|
||||
{
|
||||
KinematicCharacterMotor motor = CharacterMotors[i];
|
||||
|
||||
motor.Transform.SetPositionAndRotation(
|
||||
Vector3.Lerp(motor.InitialTickPosition, motor.TransientPosition, interpolationFactor),
|
||||
Quaternion.Slerp(motor.InitialTickRotation, motor.TransientRotation, interpolationFactor));
|
||||
}
|
||||
|
||||
// Handle PhysicsMovers interpolation
|
||||
for (int i = 0; i < PhysicsMovers.Count; i++)
|
||||
{
|
||||
PhysicsMover mover = PhysicsMovers[i];
|
||||
|
||||
mover.Transform.SetPositionAndRotation(
|
||||
Vector3.Lerp(mover.InitialTickPosition, mover.TransientPosition, interpolationFactor),
|
||||
Quaternion.Slerp(mover.InitialTickRotation, mover.TransientRotation, interpolationFactor));
|
||||
|
||||
Vector3 newPos = mover.Transform.position;
|
||||
Quaternion newRot = mover.Transform.rotation;
|
||||
mover.PositionDeltaFromInterpolation = newPos - mover.LatestInterpolationPosition;
|
||||
mover.RotationDeltaFromInterpolation = Quaternion.Inverse(mover.LatestInterpolationRotation) * newRot;
|
||||
mover.LatestInterpolationPosition = newPos;
|
||||
mover.LatestInterpolationRotation = newRot;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dbd80c9a62d41084aad50ae44255beb9
|
||||
timeCreated: 1500241576
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
261
Assets/Plugins/KinematicCharacterController/Core/PhysicsMover.cs
Normal file
261
Assets/Plugins/KinematicCharacterController/Core/PhysicsMover.cs
Normal file
@@ -0,0 +1,261 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace KinematicCharacterController
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the entire state of a PhysicsMover that is pertinent for simulation.
|
||||
/// Use this to save state or revert to past state
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public struct PhysicsMoverState
|
||||
{
|
||||
public Vector3 Position;
|
||||
public Quaternion Rotation;
|
||||
public Vector3 Velocity;
|
||||
public Vector3 AngularVelocity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Component that manages the movement of moving kinematic rigidbodies for
|
||||
/// proper interaction with characters
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(Rigidbody))]
|
||||
public class PhysicsMover : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// The mover's Rigidbody
|
||||
/// </summary>
|
||||
[ReadOnly]
|
||||
public Rigidbody Rigidbody;
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the platform moves with rigidbody.MovePosition (when true), or with rigidbody.position (when false)
|
||||
/// </summary>
|
||||
public bool MoveWithPhysics = true;
|
||||
|
||||
/// <summary>
|
||||
/// Index of this motor in KinematicCharacterSystem arrays
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
public IMoverController MoverController;
|
||||
/// <summary>
|
||||
/// Remembers latest position in interpolation
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
public Vector3 LatestInterpolationPosition;
|
||||
/// <summary>
|
||||
/// Remembers latest rotation in interpolation
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
public Quaternion LatestInterpolationRotation;
|
||||
/// <summary>
|
||||
/// The latest movement made by interpolation
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
public Vector3 PositionDeltaFromInterpolation;
|
||||
/// <summary>
|
||||
/// The latest rotation made by interpolation
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
public Quaternion RotationDeltaFromInterpolation;
|
||||
|
||||
/// <summary>
|
||||
/// Index of this motor in KinematicCharacterSystem arrays
|
||||
/// </summary>
|
||||
public int IndexInCharacterSystem { get; set; }
|
||||
/// <summary>
|
||||
/// Remembers initial position before all simulation are done
|
||||
/// </summary>
|
||||
public Vector3 Velocity { get; protected set; }
|
||||
/// <summary>
|
||||
/// Remembers initial position before all simulation are done
|
||||
/// </summary>
|
||||
public Vector3 AngularVelocity { get; protected set; }
|
||||
/// <summary>
|
||||
/// Remembers initial position before all simulation are done
|
||||
/// </summary>
|
||||
public Vector3 InitialTickPosition { get; set; }
|
||||
/// <summary>
|
||||
/// Remembers initial rotation before all simulation are done
|
||||
/// </summary>
|
||||
public Quaternion InitialTickRotation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The mover's Transform
|
||||
/// </summary>
|
||||
public Transform Transform { get; private set; }
|
||||
/// <summary>
|
||||
/// The character's position before the movement calculations began
|
||||
/// </summary>
|
||||
public Vector3 InitialSimulationPosition { get; private set; }
|
||||
/// <summary>
|
||||
/// The character's rotation before the movement calculations began
|
||||
/// </summary>
|
||||
public Quaternion InitialSimulationRotation { get; private set; }
|
||||
|
||||
private Vector3 _internalTransientPosition;
|
||||
|
||||
/// <summary>
|
||||
/// The mover's rotation (always up-to-date during the character update phase)
|
||||
/// </summary>
|
||||
public Vector3 TransientPosition
|
||||
{
|
||||
get
|
||||
{
|
||||
return _internalTransientPosition;
|
||||
}
|
||||
private set
|
||||
{
|
||||
_internalTransientPosition = value;
|
||||
}
|
||||
}
|
||||
|
||||
private Quaternion _internalTransientRotation;
|
||||
/// <summary>
|
||||
/// The mover's rotation (always up-to-date during the character update phase)
|
||||
/// </summary>
|
||||
public Quaternion TransientRotation
|
||||
{
|
||||
get
|
||||
{
|
||||
return _internalTransientRotation;
|
||||
}
|
||||
private set
|
||||
{
|
||||
_internalTransientRotation = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
ValidateData();
|
||||
}
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
ValidateData();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle validating all required values
|
||||
/// </summary>
|
||||
public void ValidateData()
|
||||
{
|
||||
Rigidbody = gameObject.GetComponent<Rigidbody>();
|
||||
|
||||
Rigidbody.centerOfMass = Vector3.zero;
|
||||
Rigidbody.maxAngularVelocity = Mathf.Infinity;
|
||||
Rigidbody.maxDepenetrationVelocity = Mathf.Infinity;
|
||||
Rigidbody.isKinematic = true;
|
||||
Rigidbody.interpolation = RigidbodyInterpolation.None;
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
KinematicCharacterSystem.EnsureCreation();
|
||||
KinematicCharacterSystem.RegisterPhysicsMover(this);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
KinematicCharacterSystem.UnregisterPhysicsMover(this);
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
Transform = this.transform;
|
||||
ValidateData();
|
||||
|
||||
TransientPosition = Rigidbody.position;
|
||||
TransientRotation = Rigidbody.rotation;
|
||||
InitialSimulationPosition = Rigidbody.position;
|
||||
InitialSimulationRotation = Rigidbody.rotation;
|
||||
LatestInterpolationPosition = Transform.position;
|
||||
LatestInterpolationRotation = Transform.rotation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the mover's position directly
|
||||
/// </summary>
|
||||
public void SetPosition(Vector3 position)
|
||||
{
|
||||
Transform.position = position;
|
||||
Rigidbody.position = position;
|
||||
InitialSimulationPosition = position;
|
||||
TransientPosition = position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the mover's rotation directly
|
||||
/// </summary>
|
||||
public void SetRotation(Quaternion rotation)
|
||||
{
|
||||
Transform.rotation = rotation;
|
||||
Rigidbody.rotation = rotation;
|
||||
InitialSimulationRotation = rotation;
|
||||
TransientRotation = rotation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the mover's position and rotation directly
|
||||
/// </summary>
|
||||
public void SetPositionAndRotation(Vector3 position, Quaternion rotation)
|
||||
{
|
||||
Transform.SetPositionAndRotation(position, rotation);
|
||||
Rigidbody.position = position;
|
||||
Rigidbody.rotation = rotation;
|
||||
InitialSimulationPosition = position;
|
||||
InitialSimulationRotation = rotation;
|
||||
TransientPosition = position;
|
||||
TransientRotation = rotation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all the state information of the mover that is pertinent for simulation
|
||||
/// </summary>
|
||||
public PhysicsMoverState GetState()
|
||||
{
|
||||
PhysicsMoverState state = new PhysicsMoverState();
|
||||
|
||||
state.Position = TransientPosition;
|
||||
state.Rotation = TransientRotation;
|
||||
state.Velocity = Velocity;
|
||||
state.AngularVelocity = AngularVelocity;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies a mover state instantly
|
||||
/// </summary>
|
||||
public void ApplyState(PhysicsMoverState state)
|
||||
{
|
||||
SetPositionAndRotation(state.Position, state.Rotation);
|
||||
Velocity = state.Velocity;
|
||||
AngularVelocity = state.AngularVelocity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Caches velocity values based on deltatime and target position/rotations
|
||||
/// </summary>
|
||||
public void VelocityUpdate(float deltaTime)
|
||||
{
|
||||
InitialSimulationPosition = TransientPosition;
|
||||
InitialSimulationRotation = TransientRotation;
|
||||
|
||||
MoverController.UpdateMovement(out _internalTransientPosition, out _internalTransientRotation, deltaTime);
|
||||
|
||||
if (deltaTime > 0f)
|
||||
{
|
||||
Velocity = (TransientPosition - InitialSimulationPosition) / deltaTime;
|
||||
|
||||
Quaternion rotationFromCurrentToGoal = TransientRotation * (Quaternion.Inverse(InitialSimulationRotation));
|
||||
AngularVelocity = (Mathf.Deg2Rad * rotationFromCurrentToGoal.eulerAngles) / deltaTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 075ccbe9837b0744985e09ba3f015b9b
|
||||
timeCreated: 1488089271
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace KinematicCharacterController
|
||||
{
|
||||
public class ReadOnlyAttribute : PropertyAttribute
|
||||
{
|
||||
}
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63e8828991cf67f42bfeb498686aad0b
|
||||
timeCreated: 1504493014
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user