Added Feel plugin
This commit is contained in:
154
Assets/External/Feel/MMTools/Accessories/MMMovement/MMAim.cs
vendored
Normal file
154
Assets/External/Feel/MMTools/Accessories/MMMovement/MMAim.cs
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
|
||||
using UnityEngine.InputSystem;
|
||||
#endif
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
[Serializable]
|
||||
public class MMAim
|
||||
{
|
||||
/// the list of possible control modes .
|
||||
public enum AimControls { Off, PrimaryMovement, SecondaryMovement, Mouse, Script }
|
||||
/// the list of possible rotation modes
|
||||
public enum RotationModes { Free, Strict4Directions, Strict8Directions }
|
||||
|
||||
[Header("Control Mode")]
|
||||
[MMInformation("Pick a control mode : mouse (aims towards the pointer), primary movement (you'll aim towards the current input direction), or secondary movement (aims " +
|
||||
"towards a second input axis, think twin stick shooters), and set minimum and maximum angles.", MoreMountains.Tools.MMInformationAttribute.InformationType.Info, false)]
|
||||
/// the aim control mode
|
||||
public AimControls AimControl = AimControls.SecondaryMovement;
|
||||
/// the rotation mode
|
||||
public RotationModes RotationMode = RotationModes.Free;
|
||||
|
||||
[Header("Limits")]
|
||||
[Range(-180, 180)]
|
||||
/// the minimum angle at which the weapon's rotation will be clamped
|
||||
public float MinimumAngle = -180f;
|
||||
[Range(-180, 180)]
|
||||
/// the maximum angle at which the weapon's rotation will be clamped
|
||||
public float MaximumAngle = 180f;
|
||||
|
||||
/// the current angle the weapon is aiming at
|
||||
[MMReadOnly]
|
||||
public float CurrentAngle;
|
||||
|
||||
public virtual Vector3 CurrentPosition { get; set; }
|
||||
public virtual Vector2 PrimaryMovement { get; set; }
|
||||
public virtual Vector2 SecondaryMovement { get; set; }
|
||||
|
||||
protected float[] _possibleAngleValues;
|
||||
protected Vector3 _currentAim = Vector3.zero;
|
||||
protected Vector3 _direction;
|
||||
protected Vector3 _mousePosition;
|
||||
protected Vector2 _inputSystemMousePosition;
|
||||
|
||||
protected Camera _mainCamera;
|
||||
|
||||
/// <summary>
|
||||
/// Grabs the weapon component, initializes the angle values
|
||||
/// </summary>
|
||||
public virtual void Initialization()
|
||||
{
|
||||
if (RotationMode == RotationModes.Strict4Directions)
|
||||
{
|
||||
_possibleAngleValues = new float[5];
|
||||
_possibleAngleValues[0] = -180f;
|
||||
_possibleAngleValues[1] = -90f;
|
||||
_possibleAngleValues[2] = 0f;
|
||||
_possibleAngleValues[3] = 90f;
|
||||
_possibleAngleValues[4] = 180f;
|
||||
}
|
||||
if (RotationMode == RotationModes.Strict8Directions)
|
||||
{
|
||||
_possibleAngleValues = new float[9];
|
||||
_possibleAngleValues[0] = -180f;
|
||||
_possibleAngleValues[1] = -135f;
|
||||
_possibleAngleValues[2] = -90f;
|
||||
_possibleAngleValues[3] = -45f;
|
||||
_possibleAngleValues[4] = 0f;
|
||||
_possibleAngleValues[5] = 45f;
|
||||
_possibleAngleValues[6] = 90f;
|
||||
_possibleAngleValues[7] = 135f;
|
||||
_possibleAngleValues[8] = 180f;
|
||||
}
|
||||
|
||||
_mainCamera = Camera.main;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the current aim direction
|
||||
/// </summary>
|
||||
public virtual Vector2 GetCurrentAim()
|
||||
{
|
||||
switch (AimControl)
|
||||
{
|
||||
case AimControls.Off:
|
||||
_currentAim = Vector2.zero;
|
||||
break;
|
||||
|
||||
case AimControls.Script:
|
||||
// in that mode we simply use _currentAim, as set by the SetAim method
|
||||
break;
|
||||
|
||||
case AimControls.PrimaryMovement:
|
||||
_currentAim = PrimaryMovement;
|
||||
break;
|
||||
|
||||
case AimControls.SecondaryMovement:
|
||||
_currentAim = SecondaryMovement;
|
||||
break;
|
||||
|
||||
case AimControls.Mouse:
|
||||
#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
|
||||
_mousePosition = Mouse.current.position.ReadValue();
|
||||
#else
|
||||
_mousePosition = Input.mousePosition;
|
||||
#endif
|
||||
_mousePosition.z = 10;
|
||||
_direction = _mainCamera.ScreenToWorldPoint(_mousePosition);
|
||||
_direction.z = CurrentPosition.z;
|
||||
_currentAim = _direction - CurrentPosition;
|
||||
break;
|
||||
|
||||
default:
|
||||
_currentAim = Vector2.zero;
|
||||
break;
|
||||
}
|
||||
|
||||
// we compute our angle in degrees
|
||||
CurrentAngle = Mathf.Atan2(_currentAim.y, _currentAim.x) * Mathf.Rad2Deg;
|
||||
|
||||
// we clamp our raw angle if needed
|
||||
if ((CurrentAngle < MinimumAngle) || (CurrentAngle > MaximumAngle))
|
||||
{
|
||||
float minAngleDifference = Mathf.DeltaAngle(CurrentAngle, MinimumAngle);
|
||||
float maxAngleDifference = Mathf.DeltaAngle(CurrentAngle, MaximumAngle);
|
||||
CurrentAngle = (Mathf.Abs(minAngleDifference) < Mathf.Abs(maxAngleDifference)) ? MinimumAngle : MaximumAngle;
|
||||
}
|
||||
|
||||
// we round to the closest angle
|
||||
if (RotationMode == RotationModes.Strict4Directions || RotationMode == RotationModes.Strict8Directions)
|
||||
{
|
||||
CurrentAngle = MMMaths.RoundToClosest(CurrentAngle, _possibleAngleValues);
|
||||
}
|
||||
|
||||
// we clamp the final value
|
||||
CurrentAngle = Mathf.Clamp(CurrentAngle, MinimumAngle, MaximumAngle);
|
||||
|
||||
// we return our aim vector
|
||||
_currentAim = (_currentAim.magnitude == 0f) ? Vector2.zero : MMMaths.RotateVector2(Vector2.right, CurrentAngle);
|
||||
return _currentAim;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use this method to set the aim when in AimControl mode : Script
|
||||
/// </summary>
|
||||
/// <param name="newAim"></param>
|
||||
public virtual void SetAim(Vector2 newAim)
|
||||
{
|
||||
_currentAim = newAim;
|
||||
}
|
||||
}
|
||||
}
|
||||
18
Assets/External/Feel/MMTools/Accessories/MMMovement/MMAim.cs.meta
vendored
Normal file
18
Assets/External/Feel/MMTools/Accessories/MMMovement/MMAim.cs.meta
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e078eaa3f1defa44cad7a1243d113a84
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 183370
|
||||
packageName: Feel
|
||||
packageVersion: 5.9.1
|
||||
assetPath: Assets/Feel/MMTools/Accessories/MMMovement/MMAim.cs
|
||||
uploadId: 830868
|
||||
195
Assets/External/Feel/MMTools/Accessories/MMMovement/MMAutoRotate.cs
vendored
Normal file
195
Assets/External/Feel/MMTools/Accessories/MMMovement/MMAutoRotate.cs
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
/// <summary>
|
||||
/// Add this class to a GameObject to make it rotate on itself
|
||||
/// </summary>
|
||||
[AddComponentMenu("More Mountains/Tools/Movement/MM Auto Rotate")]
|
||||
public class MMAutoRotate : MonoBehaviour
|
||||
{
|
||||
public enum UpdateModes { Update, LateUpdate, FixedUpdate }
|
||||
|
||||
[Header("Rotation")]
|
||||
/// whether or not this object should be rotating right now
|
||||
public bool Rotating = true;
|
||||
[MMCondition("Rotating", true)]
|
||||
/// the space to apply the rotation in
|
||||
public Space RotationSpace = Space.Self;
|
||||
/// whether movement should happen at Update, FixedUpdate or LateUpdate
|
||||
public UpdateModes UpdateMode = UpdateModes.Update;
|
||||
[MMCondition("Rotating", true)]
|
||||
/// The rotation speed. Positive means clockwise, negative means counter clockwise.
|
||||
public Vector3 RotationSpeed = new Vector3(100f, 0f, 0f);
|
||||
/// Whether or not the rotation speed should be randomized
|
||||
public bool RandomizeRotationSpeed = false;
|
||||
/// the minimum rotation speed to use if RandomizeRotationSpeed is true
|
||||
[MMCondition("RandomizeRotationSpeed", true)]
|
||||
public Vector3 RotationSpeedMin = new Vector3(100f, 0f, 0f);
|
||||
/// the maximum rotation speed to use if RandomizeRotationSpeed is true
|
||||
[MMCondition("RandomizeRotationSpeed", true)]
|
||||
public Vector3 RotationSpeedMax = new Vector3(300f, 0f, 0f);
|
||||
/// an offset, in seconds, to apply before starting the rotation, to allow for a delay
|
||||
[MMVector("Min", "Max")]
|
||||
public Vector2 RandomInitialDelay = Vector2.zero;
|
||||
|
||||
[Header("Orbit")]
|
||||
/// if this is true, the object will also move around a pivot (only the position is affected, not the rotation)
|
||||
public bool Orbiting = false;
|
||||
[MMCondition("Orbiting", true)]
|
||||
/// if this is true, the orbit plane will rotate along with the parent
|
||||
public bool AdditiveOrbitRotation = false;
|
||||
/// the pivot to rotate around (if left blank, will be the object itself
|
||||
[MMCondition("Orbiting", true)]
|
||||
public Transform OrbitCenterTransform;
|
||||
/// the pivot (relative to the object's position in local space) to rotate around
|
||||
[MMCondition("Orbiting", true)]
|
||||
public Vector3 OrbitCenterOffset = Vector3.zero;
|
||||
/// the axis around which the object should rotate (don't make it zero)
|
||||
[MMCondition("Orbiting", true)]
|
||||
public Vector3 OrbitRotationAxis = new Vector3(0f, 1f, 0f);
|
||||
/// the speed at which to rotate
|
||||
[MMCondition("Orbiting", true)]
|
||||
public float OrbitRotationSpeed = 10f;
|
||||
/// the radius at which to orbit
|
||||
[MMCondition("Orbiting", true)]
|
||||
public float OrbitRadius = 3f;
|
||||
/// the speed at which the object catches up when orbit radius or axis changes
|
||||
[MMCondition("Orbiting", true)]
|
||||
public float OrbitCorrectionSpeed = 10f;
|
||||
|
||||
[Header("Settings")]
|
||||
/// if this is true, will draw gizmos to show the plane, orbit and direction
|
||||
public bool DrawGizmos = true;
|
||||
[MMCondition("DrawGizmos", true)]
|
||||
/// the color of the orbit disc
|
||||
public Color OrbitPlaneColor = new Color(54f, 169f, 225f, 0.02f);
|
||||
[MMCondition("DrawGizmos", true)]
|
||||
/// the color of the orbit line
|
||||
public Color OrbitLineColor = new Color(225f, 225f, 225f, 0.1f);
|
||||
|
||||
[HideInInspector]
|
||||
public Vector3 _orbitCenter;
|
||||
[HideInInspector]
|
||||
public Vector3 _worldRotationAxis;
|
||||
[HideInInspector]
|
||||
public Plane _rotationPlane;
|
||||
[HideInInspector]
|
||||
public Vector3 _snappedPosition;
|
||||
[HideInInspector]
|
||||
public Vector3 _radius;
|
||||
|
||||
protected Quaternion _newRotation;
|
||||
protected Vector3 _desiredOrbitPosition;
|
||||
protected float _initialDelay = 0f;
|
||||
private Vector3 _previousPosition;
|
||||
protected float _startTime = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// On start, we initialize our plane
|
||||
/// </summary>
|
||||
protected virtual void Start()
|
||||
{
|
||||
_rotationPlane = new Plane();
|
||||
|
||||
_startTime = Time.time;
|
||||
_initialDelay = Random.Range(RandomInitialDelay.x, RandomInitialDelay.y);
|
||||
|
||||
if (RandomizeRotationSpeed)
|
||||
{
|
||||
RotationSpeed = new Vector3(
|
||||
Random.Range(RotationSpeedMin.x, RotationSpeedMax.x),
|
||||
Random.Range(RotationSpeedMin.y, RotationSpeedMax.y),
|
||||
Random.Range(RotationSpeedMin.z, RotationSpeedMax.z));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes the object rotate on its center at Update
|
||||
/// </summary>
|
||||
protected virtual void Update()
|
||||
{
|
||||
if (Time.time - _startTime < _initialDelay)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (UpdateMode == UpdateModes.Update)
|
||||
{
|
||||
Rotate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes the object rotate on its center at FixedUpdate
|
||||
/// </summary>
|
||||
protected virtual void FixedUpdate()
|
||||
{
|
||||
if (UpdateMode == UpdateModes.FixedUpdate)
|
||||
{
|
||||
Rotate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes the object rotate on its center at LateUpdate
|
||||
/// </summary>
|
||||
protected virtual void LateUpdate()
|
||||
{
|
||||
if (UpdateMode == UpdateModes.LateUpdate)
|
||||
{
|
||||
Rotate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets Rotating to true or false
|
||||
/// </summary>
|
||||
/// <param name="status"></param>
|
||||
public virtual void Rotate(bool status)
|
||||
{
|
||||
Rotating = status;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets Orbiting to true or false
|
||||
/// </summary>
|
||||
/// <param name="status"></param>
|
||||
public virtual void Orbit(bool status)
|
||||
{
|
||||
Orbiting = status;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotates the object
|
||||
/// </summary>
|
||||
protected virtual void Rotate()
|
||||
{
|
||||
if (Rotating)
|
||||
{
|
||||
transform.Rotate(RotationSpeed * Time.deltaTime, RotationSpace);
|
||||
}
|
||||
|
||||
if (Orbiting)
|
||||
{
|
||||
_orbitCenter = OrbitCenterTransform.transform.position + OrbitCenterOffset;
|
||||
if (AdditiveOrbitRotation)
|
||||
{
|
||||
_worldRotationAxis = OrbitCenterTransform.TransformDirection(OrbitRotationAxis);
|
||||
}
|
||||
else
|
||||
{
|
||||
_worldRotationAxis = OrbitRotationAxis;
|
||||
}
|
||||
_rotationPlane.SetNormalAndPosition(_worldRotationAxis.normalized, _orbitCenter);
|
||||
_snappedPosition = _rotationPlane.ClosestPointOnPlane(this.transform.position);
|
||||
_radius = OrbitRadius * Vector3.Normalize(_snappedPosition - _orbitCenter);
|
||||
_newRotation = Quaternion.AngleAxis(OrbitRotationSpeed * Time.deltaTime, _worldRotationAxis);
|
||||
_desiredOrbitPosition = _orbitCenter + _newRotation * _radius;
|
||||
this.transform.position = Vector3.Lerp(this.transform.position, _desiredOrbitPosition, OrbitCorrectionSpeed * Time.deltaTime);
|
||||
_previousPosition = _desiredOrbitPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
20
Assets/External/Feel/MMTools/Accessories/MMMovement/MMAutoRotate.cs.meta
vendored
Normal file
20
Assets/External/Feel/MMTools/Accessories/MMMovement/MMAutoRotate.cs.meta
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7f009572b4d918346b24337ef83f88c1
|
||||
timeCreated: 1523894079
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 183370
|
||||
packageName: Feel
|
||||
packageVersion: 5.9.1
|
||||
assetPath: Assets/Feel/MMTools/Accessories/MMMovement/MMAutoRotate.cs
|
||||
uploadId: 830868
|
||||
147
Assets/External/Feel/MMTools/Accessories/MMMovement/MMFaceDirection.cs
vendored
Normal file
147
Assets/External/Feel/MMTools/Accessories/MMMovement/MMFaceDirection.cs
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
/// <summary>
|
||||
/// Use this script to have a Transform automatically face a certain direction, whether its own movement direction, or a specific target Transform
|
||||
/// </summary>
|
||||
public class MMFaceDirection : MonoBehaviour
|
||||
{
|
||||
/// the possible Updates this script should run at
|
||||
public enum UpdateModes { Update, LateUpdate, FixedUpdate }
|
||||
/// the vector to point towards the direction
|
||||
public enum ForwardVectors { Forward, Up, Right }
|
||||
/// whether to point at this transform's movement direction, or at a target
|
||||
public enum FacingModes { MovementDirection, Target }
|
||||
|
||||
[Header("Facing Mode")]
|
||||
/// whether to point at this transform's movement direction, or at a target
|
||||
public FacingModes FacingMode = FacingModes.MovementDirection;
|
||||
/// the target to face
|
||||
[MMEnumCondition("FacingMode", (int) FacingModes.Target)]
|
||||
public Transform FacingTarget;
|
||||
/// the minimum distance to consider when computing the movement direction
|
||||
[MMEnumCondition("FacingMode", (int) FacingModes.MovementDirection)]
|
||||
public float MinimumMovementThreshold = 0.2f;
|
||||
|
||||
[Header("Directions")]
|
||||
/// the vector to point towards the direction
|
||||
public ForwardVectors ForwardVector = ForwardVectors.Forward;
|
||||
/// the angles by which to rotate the direction (in degrees)
|
||||
public Vector3 DirectionRotationAngles = Vector3.zero;
|
||||
|
||||
[Header("Axis Locks")]
|
||||
public bool LockXAxis = false;
|
||||
public bool LockYAxis = false;
|
||||
public bool LockZAxis = false;
|
||||
|
||||
[Header("Timing")]
|
||||
/// the possible Updates this script should run at
|
||||
public UpdateModes UpdateMode = UpdateModes.LateUpdate;
|
||||
/// the speed at which to interpolate the rotation
|
||||
public float InterpolationSpeed = 0.15f;
|
||||
|
||||
protected Vector3 _direction;
|
||||
protected Vector3 _positionLastFrame;
|
||||
protected Transform _transform;
|
||||
protected Vector3 _upwards;
|
||||
protected Vector3 _targetPosition;
|
||||
|
||||
/// <summary>
|
||||
/// On Awake we initialize our behaviour
|
||||
/// </summary>
|
||||
protected virtual void Awake()
|
||||
{
|
||||
Initialization();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Caches upwards vector and transform
|
||||
/// </summary>
|
||||
protected virtual void Initialization()
|
||||
{
|
||||
_transform = this.transform;
|
||||
_positionLastFrame = _transform.position;
|
||||
switch (ForwardVector)
|
||||
{
|
||||
case ForwardVectors.Forward:
|
||||
_upwards = Vector3.forward;
|
||||
break;
|
||||
case ForwardVectors.Up:
|
||||
_upwards = Vector3.up;
|
||||
break;
|
||||
case ForwardVectors.Right:
|
||||
_upwards = Vector3.right;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the direction to face
|
||||
/// </summary>
|
||||
protected virtual void FaceDirection()
|
||||
{
|
||||
if (FacingMode == FacingModes.Target)
|
||||
{
|
||||
_targetPosition = FacingTarget.position;
|
||||
if (LockXAxis) { _targetPosition.x = _transform.position.x; }
|
||||
if (LockYAxis) { _targetPosition.y = _transform.position.y; }
|
||||
if (LockZAxis) { _targetPosition.z = _transform.position.z; }
|
||||
|
||||
_direction = _targetPosition - _transform.position;
|
||||
_direction = Quaternion.Euler(DirectionRotationAngles.x, DirectionRotationAngles.y, DirectionRotationAngles.z) * _direction;
|
||||
ApplyRotation();
|
||||
}
|
||||
|
||||
if (FacingMode == FacingModes.MovementDirection)
|
||||
{
|
||||
_direction = (_transform.position - _positionLastFrame).normalized;
|
||||
if (LockXAxis) { _direction.x = 0; }
|
||||
if (LockYAxis) { _direction.y = 0; }
|
||||
if (LockZAxis) { _direction.z = 0; }
|
||||
_direction = Quaternion.Euler(DirectionRotationAngles.x, DirectionRotationAngles.y, DirectionRotationAngles.z) * _direction;
|
||||
|
||||
if (Vector3.Distance(_transform.position, _positionLastFrame) > MinimumMovementThreshold)
|
||||
{
|
||||
ApplyRotation();
|
||||
_positionLastFrame = _transform.position;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotates the transform
|
||||
/// </summary>
|
||||
protected virtual void ApplyRotation()
|
||||
{
|
||||
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(_direction, _upwards), InterpolationSpeed * Time.time);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On Update we compute our direction if needed
|
||||
/// </summary>
|
||||
protected virtual void Update()
|
||||
{
|
||||
if (UpdateMode == UpdateModes.Update) { FaceDirection(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On LateUpdate we compute our direction if needed
|
||||
/// </summary>
|
||||
protected virtual void LateUpdate()
|
||||
{
|
||||
if (UpdateMode == UpdateModes.LateUpdate) { FaceDirection(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On FixedUpdate we compute our direction if needed
|
||||
/// </summary>
|
||||
protected virtual void FixedUpdate()
|
||||
{
|
||||
if (UpdateMode == UpdateModes.FixedUpdate) { FaceDirection(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
18
Assets/External/Feel/MMTools/Accessories/MMMovement/MMFaceDirection.cs.meta
vendored
Normal file
18
Assets/External/Feel/MMTools/Accessories/MMMovement/MMFaceDirection.cs.meta
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1374d534191fbdf40b704f29771981b9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 183370
|
||||
packageName: Feel
|
||||
packageVersion: 5.9.1
|
||||
assetPath: Assets/Feel/MMTools/Accessories/MMMovement/MMFaceDirection.cs
|
||||
uploadId: 830868
|
||||
9
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPathMovement.meta
vendored
Normal file
9
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPathMovement.meta
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a81a0d0af22c3fb45818ed2f5e47b2e1
|
||||
folderAsset: yes
|
||||
timeCreated: 1483901466
|
||||
licenseType: Store
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
466
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPathMovement/MMPath.cs
vendored
Normal file
466
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPathMovement/MMPath.cs
vendored
Normal file
@@ -0,0 +1,466 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using MoreMountains.Tools;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
[System.Serializable]
|
||||
/// <summary>
|
||||
/// This class describes a node on an MMPath
|
||||
/// </summary>
|
||||
public class MMPathMovementElement
|
||||
{
|
||||
/// the point that make up the path the object will follow
|
||||
public Vector3 PathElementPosition;
|
||||
/// a delay (in seconds) associated to each node
|
||||
public float Delay;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add this component to an object and you'll be able to define a path, that can then be used by another component
|
||||
/// </summary>
|
||||
[AddComponentMenu("More Mountains/Tools/Movement/MM Path")]
|
||||
public class MMPath : MonoBehaviour
|
||||
{
|
||||
/// the possible cycle options
|
||||
public enum CycleOptions
|
||||
{
|
||||
BackAndForth,
|
||||
Loop,
|
||||
OnlyOnce
|
||||
}
|
||||
|
||||
/// the possible movement directions
|
||||
public enum MovementDirection
|
||||
{
|
||||
Ascending,
|
||||
Descending
|
||||
}
|
||||
|
||||
[Header("Path")]
|
||||
[MMInformation("Here you can select the '<b>Cycle Option</b>'. Back and Forth will have your object follow the path until its end, and go back to the original point. If you select Loop, the path will be closed and the object will move along it until told otherwise. If you select Only Once, the object will move along the path from the first to the last point, and remain there forever.",MoreMountains.Tools.MMInformationAttribute.InformationType.Info,false)]
|
||||
public CycleOptions CycleOption;
|
||||
|
||||
[MMInformation("Add points to the <b>Path</b> (set the size of the path first), then position the points using either the inspector or by moving the handles directly in scene view. For each path element you can specify a delay (in seconds). The order of the points will be the order the object follows.\nFor looping paths, you can then decide if the object will go through the points in the Path in Ascending (1, 2, 3...) or Descending (Last, Last-1, Last-2...) order.",MoreMountains.Tools.MMInformationAttribute.InformationType.Info,false)]
|
||||
/// the initial movement direction : ascending > will go from the points 0 to 1, 2, etc ; descending > will go from the last point to last-1, last-2, etc
|
||||
public MovementDirection LoopInitialMovementDirection = MovementDirection.Ascending;
|
||||
/// the points that make up the path the object will follow
|
||||
public List<MMPathMovementElement> PathElements;
|
||||
/// another MMPath that you can reference. If set, the reference MMPath's data will replace this MMPath's
|
||||
public MMPath ReferenceMMPath;
|
||||
/// if this is true, this object will move to the 0 position of the reference path
|
||||
public bool AbsoluteReferencePath = false;
|
||||
/// the minimum distance to a point at which we'll arbitrarily decide the point's been reached
|
||||
public float MinDistanceToGoal = .1f;
|
||||
/// if this is true, the path has reached its end
|
||||
public bool EndReached => _endReached;
|
||||
|
||||
[Header("Gizmos")]
|
||||
public bool LockHandlesOnXAxis = false;
|
||||
public bool LockHandlesOnYAxis = false;
|
||||
public bool LockHandlesOnZAxis = false;
|
||||
|
||||
/// the original position of the transform, hidden and shouldn't be accessed
|
||||
protected Vector3 _originalTransformPosition;
|
||||
/// internal flag, hidden and shouldn't be accessed
|
||||
protected bool _originalTransformPositionStatus=false;
|
||||
/// if this is true, the object can move along the path
|
||||
public virtual bool CanMove { get; set; }
|
||||
/// if this is true, this path has gone through its Initialization method
|
||||
public virtual bool Initialized { get; set; }
|
||||
|
||||
public virtual int Direction => _direction;
|
||||
|
||||
protected bool _active=false;
|
||||
protected IEnumerator<Vector3> _currentPoint;
|
||||
protected int _direction = 1;
|
||||
protected Vector3 _initialPosition;
|
||||
protected Vector3 _initialPositionThisFrame;
|
||||
protected Vector3 _finalPosition;
|
||||
protected Vector3 _previousPoint = Vector3.zero;
|
||||
protected int _currentIndex;
|
||||
protected float _distanceToNextPoint;
|
||||
protected bool _endReached = false;
|
||||
|
||||
/// <summary>
|
||||
/// Initialization
|
||||
/// </summary>
|
||||
protected virtual void Start ()
|
||||
{
|
||||
if (!Initialized)
|
||||
{
|
||||
Initialization ();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flag inits, initial movement determination, and object positioning
|
||||
/// </summary>
|
||||
public virtual void Initialization()
|
||||
{
|
||||
// on Start, we set our active flag to true
|
||||
_active=true;
|
||||
_endReached = false;
|
||||
CanMove = true;
|
||||
|
||||
// we copy our reference if needed
|
||||
if ((ReferenceMMPath != null) && (ReferenceMMPath.PathElements != null || ReferenceMMPath.PathElements.Count > 0))
|
||||
{
|
||||
if (AbsoluteReferencePath)
|
||||
{
|
||||
this.transform.position = ReferenceMMPath.transform.position;
|
||||
}
|
||||
PathElements = ReferenceMMPath.PathElements;
|
||||
}
|
||||
|
||||
// if the path is null we exit
|
||||
if (PathElements == null || PathElements.Count < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// if the first path element isn't at 0, we offset everything
|
||||
if (PathElements[0].PathElementPosition != Vector3.zero)
|
||||
{
|
||||
Vector3 path0Position = PathElements[0].PathElementPosition;
|
||||
this.transform.position += path0Position;
|
||||
|
||||
foreach (MMPathMovementElement element in PathElements)
|
||||
{
|
||||
element.PathElementPosition -= path0Position;
|
||||
}
|
||||
}
|
||||
|
||||
// we set our initial direction based on the settings
|
||||
if (LoopInitialMovementDirection == MovementDirection.Ascending)
|
||||
{
|
||||
_direction=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_direction=-1;
|
||||
}
|
||||
|
||||
// we initialize our path enumerator
|
||||
_initialPosition = this.transform.position;
|
||||
|
||||
_currentPoint = GetPathEnumerator();
|
||||
_previousPoint = _currentPoint.Current;
|
||||
_currentPoint.MoveNext();
|
||||
|
||||
// initial positioning
|
||||
if (!_originalTransformPositionStatus)
|
||||
{
|
||||
_originalTransformPositionStatus = true;
|
||||
_originalTransformPosition = transform.position;
|
||||
}
|
||||
transform.position = _originalTransformPosition + _currentPoint.Current;
|
||||
}
|
||||
|
||||
public int CurrentIndex()
|
||||
{
|
||||
return _currentIndex;
|
||||
}
|
||||
|
||||
public Vector3 CurrentPoint()
|
||||
{
|
||||
return _initialPosition + _currentPoint.Current;
|
||||
}
|
||||
|
||||
public Vector3 CurrentPositionRelative()
|
||||
{
|
||||
return _currentPoint.Current;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On update we keep moving along the path
|
||||
/// </summary>
|
||||
protected virtual void Update ()
|
||||
{
|
||||
// if the path is null we exit, if we only go once and have reached the end we exit, if we can't move we exit
|
||||
if(PathElements == null
|
||||
|| PathElements.Count < 1
|
||||
|| _endReached
|
||||
|| !CanMove
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ComputePath ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves the object and determines when a point has been reached
|
||||
/// </summary>
|
||||
protected virtual void ComputePath()
|
||||
{
|
||||
// we store our initial position to compute the current speed at the end of the udpate
|
||||
_initialPositionThisFrame = this.transform.position;
|
||||
|
||||
// we decide if we've reached our next destination or not, if yes, we move our destination to the next point
|
||||
_distanceToNextPoint = (this.transform.position - (_originalTransformPosition + _currentPoint.Current)).magnitude;
|
||||
if(_distanceToNextPoint < MinDistanceToGoal)
|
||||
{
|
||||
_previousPoint = _currentPoint.Current;
|
||||
_currentPoint.MoveNext();
|
||||
}
|
||||
|
||||
// we determine the current speed
|
||||
_finalPosition = this.transform.position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current target point in the path
|
||||
/// </summary>
|
||||
/// <returns>The path enumerator.</returns>
|
||||
public virtual IEnumerator<Vector3> GetPathEnumerator()
|
||||
{
|
||||
|
||||
// if the path is null we exit
|
||||
if(PathElements == null || PathElements.Count < 1)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
_currentIndex = index;
|
||||
while (true)
|
||||
{
|
||||
_currentIndex = index;
|
||||
yield return PathElements[index].PathElementPosition;
|
||||
|
||||
if(PathElements.Count <= 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// if the path is looping
|
||||
if (CycleOption == CycleOptions.Loop)
|
||||
{
|
||||
index = index + _direction;
|
||||
if(index < 0)
|
||||
{
|
||||
index = PathElements.Count-1;
|
||||
}
|
||||
else if(index > PathElements.Count - 1)
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (CycleOption == CycleOptions.BackAndForth)
|
||||
{
|
||||
if(index <= 0)
|
||||
{
|
||||
_direction = 1;
|
||||
}
|
||||
else if(index >= PathElements.Count - 1)
|
||||
{
|
||||
_direction = -1;
|
||||
}
|
||||
index = index + _direction;
|
||||
}
|
||||
|
||||
if (CycleOption == CycleOptions.OnlyOnce)
|
||||
{
|
||||
if(index <= 0)
|
||||
{
|
||||
_direction = 1;
|
||||
}
|
||||
else if(index >= PathElements.Count - 1)
|
||||
{
|
||||
_direction = 0;
|
||||
_endReached = true;
|
||||
}
|
||||
index = index + _direction;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call this method to force a change in direction at any time
|
||||
/// </summary>
|
||||
public virtual void ChangeDirection()
|
||||
{
|
||||
_direction = - _direction;
|
||||
_currentPoint.MoveNext();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On DrawGizmos, we draw lines to show the path the object will follow
|
||||
/// </summary>
|
||||
protected virtual void OnDrawGizmos()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (PathElements==null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (PathElements.Count==0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// if we haven't stored the object's original position yet, we do it
|
||||
if (_originalTransformPositionStatus==false)
|
||||
{
|
||||
_originalTransformPosition = this.transform.position;
|
||||
_originalTransformPositionStatus=true;
|
||||
}
|
||||
// if we're not in runtime mode and the transform has changed, we update our position
|
||||
if (transform.hasChanged && (_active == false))
|
||||
{
|
||||
_originalTransformPosition = this.transform.position;
|
||||
}
|
||||
// for each point in the path
|
||||
for (int i=0;i<PathElements.Count;i++)
|
||||
{
|
||||
// we draw a green point
|
||||
MMDebug.DrawGizmoPoint(_originalTransformPosition+PathElements[i].PathElementPosition,0.2f,Color.green);
|
||||
|
||||
// we draw a line towards the next point in the path
|
||||
if ((i+1)<PathElements.Count)
|
||||
{
|
||||
Gizmos.color=Color.white;
|
||||
Gizmos.DrawLine(_originalTransformPosition+PathElements[i].PathElementPosition,_originalTransformPosition+PathElements[i+1].PathElementPosition);
|
||||
}
|
||||
// we draw a line from the first to the last point if we're looping
|
||||
if ( (i == PathElements.Count-1) && (CycleOption == CycleOptions.Loop) )
|
||||
{
|
||||
Gizmos.color=Color.white;
|
||||
Gizmos.DrawLine(_originalTransformPosition+PathElements[0].PathElementPosition,_originalTransformPosition+PathElements[i].PathElementPosition);
|
||||
}
|
||||
}
|
||||
|
||||
// if the game is playing, we add a blue point to the destination, and a red point to the last visited point
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
if (_currentPoint != null)
|
||||
{
|
||||
MMDebug.DrawGizmoPoint(_originalTransformPosition + _currentPoint.Current,0.2f,Color.blue);
|
||||
MMDebug.DrawGizmoPoint(_originalTransformPosition + _previousPoint,0.2f,Color.red);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the original transform position.
|
||||
/// </summary>
|
||||
/// <param name="newOriginalTransformPosition">New original transform position.</param>
|
||||
public virtual void UpdateOriginalTransformPosition(Vector3 newOriginalTransformPosition)
|
||||
{
|
||||
_originalTransformPosition = newOriginalTransformPosition;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the original transform position.
|
||||
/// </summary>
|
||||
/// <returns>The original transform position.</returns>
|
||||
public virtual Vector3 GetOriginalTransformPosition()
|
||||
{
|
||||
return _originalTransformPosition;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the original transform position status.
|
||||
/// </summary>
|
||||
/// <param name="status">If set to <c>true</c> status.</param>
|
||||
public virtual void SetOriginalTransformPositionStatus(bool status)
|
||||
{
|
||||
_originalTransformPositionStatus = status;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the original transform position status.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c>, if original transform position status was gotten, <c>false</c> otherwise.</returns>
|
||||
public virtual bool GetOriginalTransformPositionStatus()
|
||||
{
|
||||
return _originalTransformPositionStatus ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A data structure
|
||||
/// </summary>
|
||||
[System.Serializable] public struct Data
|
||||
{
|
||||
public static Data ForwardLoopingPath(Vector3 ctr, Vector3[] vtx, float wait)
|
||||
=> new Data()
|
||||
{
|
||||
Center = ctr, Offsets = vtx, Delay = wait,
|
||||
Cycle = CycleOptions.Loop, Direction = MovementDirection.Ascending
|
||||
};
|
||||
public static Data ForwardBackAndForthPath(Vector3 ctr, Vector3[] vtx, float wait)
|
||||
=> new Data()
|
||||
{
|
||||
Center = ctr, Offsets = vtx, Delay = wait,
|
||||
Cycle = CycleOptions.BackAndForth, Direction = MovementDirection.Ascending
|
||||
};
|
||||
public static Data ForwardOnlyOncePath(Vector3 ctr, Vector3[] vtx, float wait)
|
||||
=> new Data()
|
||||
{
|
||||
Center = ctr, Offsets = vtx, Delay = wait,
|
||||
Cycle = CycleOptions.OnlyOnce, Direction = MovementDirection.Ascending
|
||||
};
|
||||
|
||||
public Vector3 Center;
|
||||
public Vector3[] Offsets;
|
||||
public float Delay;
|
||||
public CycleOptions Cycle;
|
||||
public MovementDirection Direction;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replaces this MMPath's settings with the ones passed in parameters
|
||||
/// </summary>
|
||||
/// <param name="configuration"></param>
|
||||
public void SetPath(in Data configuration)
|
||||
{
|
||||
if (configuration.Offsets == null) return;
|
||||
|
||||
// same as on Start, we set our active flag to true
|
||||
_active = true;
|
||||
_endReached = false;
|
||||
CanMove = true;
|
||||
|
||||
PathElements = PathElements ?? new List<MMPathMovementElement>(configuration.Offsets.Length);
|
||||
PathElements.Clear();
|
||||
|
||||
foreach (var offset in configuration.Offsets)
|
||||
{
|
||||
PathElements.Add(new MMPathMovementElement() {Delay = configuration.Delay, PathElementPosition = offset});
|
||||
}
|
||||
|
||||
// if the path is null we exit
|
||||
if (PathElements == null || PathElements.Count < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CycleOption = configuration.Cycle;
|
||||
|
||||
// we set our initial direction based on the settings
|
||||
if (configuration.Direction == MovementDirection.Ascending)
|
||||
{
|
||||
_direction = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_direction = -1;
|
||||
}
|
||||
|
||||
_initialPosition = configuration.Center;
|
||||
_originalTransformPosition = configuration.Center;
|
||||
_currentPoint = GetPathEnumerator();
|
||||
_previousPoint = _currentPoint.Current;
|
||||
_currentPoint.MoveNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
18
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPathMovement/MMPath.cs.meta
vendored
Normal file
18
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPathMovement/MMPath.cs.meta
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b81dc1a6e4b189d4bae2faab8a2a1a25
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 183370
|
||||
packageName: Feel
|
||||
packageVersion: 5.9.1
|
||||
assetPath: Assets/Feel/MMTools/Accessories/MMMovement/MMPathMovement/MMPath.cs
|
||||
uploadId: 830868
|
||||
514
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPathMovement/MMPathMovement.cs
vendored
Normal file
514
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPathMovement/MMPathMovement.cs
vendored
Normal file
@@ -0,0 +1,514 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using MoreMountains.Tools;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
/// <summary>
|
||||
/// Add this component to an object and it'll be able to move along a path defined from its inspector.
|
||||
/// </summary>
|
||||
[AddComponentMenu("More Mountains/Tools/Movement/MM Path Movement")]
|
||||
public class MMPathMovement : MonoBehaviour
|
||||
{
|
||||
/// the possible movement types
|
||||
public enum PossibleAccelerationType { ConstantSpeed, EaseOut, AnimationCurve }
|
||||
/// the possible cycle options
|
||||
public enum CycleOptions { BackAndForth, Loop, OnlyOnce, StopAtBounds, Random }
|
||||
/// the possible movement directions
|
||||
public enum MovementDirection { Ascending, Descending }
|
||||
/// whether progress on the pass should be made at update, fixed update or late update
|
||||
public enum UpdateModes { Update, FixedUpdate, LateUpdate }
|
||||
/// whether to align the path on nothing, this object's rotation, or this object's parent's rotation
|
||||
public enum AlignmentModes { None, ThisRotation, ParentRotation }
|
||||
|
||||
[Header("Path")]
|
||||
[MMInformation("Here you can select the '<b>Cycle Option</b>'. Back and Forth will have your object follow the path until its end, and go back to the original point. If you select Loop, the path will be closed and the object will move along it until told otherwise. If you select Only Once, the object will move along the path from the first to the last point, and remain there forever.",MoreMountains.Tools.MMInformationAttribute.InformationType.Info,false)]
|
||||
public CycleOptions CycleOption;
|
||||
|
||||
[MMInformation("Add points to the <b>Path</b> (set the size of the path first), then position the points using either the inspector or by moving the handles directly in scene view. For each path element you can specify a delay (in seconds). The order of the points will be the order the object follows.\nFor looping paths, you can then decide if the object will go through the points in the Path in Ascending (1, 2, 3...) or Descending (Last, Last-1, Last-2...) order.",MoreMountains.Tools.MMInformationAttribute.InformationType.Info,false)]
|
||||
/// the initial movement direction : ascending > will go from the points 0 to 1, 2, etc ; descending > will go from the last point to last-1, last-2, etc
|
||||
[Tooltip("the initial movement direction : ascending > will go from the points 0 to 1, 2, etc ; descending > will go from the last point to last-1, last-2, etc")]
|
||||
public MovementDirection LoopInitialMovementDirection = MovementDirection.Ascending;
|
||||
/// the points that make up the path the object will follow
|
||||
[Tooltip("the points that make up the path the object will follow")]
|
||||
public List<MMPathMovementElement> PathElements;
|
||||
|
||||
[Header("Path Alignment")]
|
||||
/// whether to align the path on nothing, this object's rotation, or this object's parent's rotation
|
||||
[Tooltip("whether to align the path on nothing, this object's rotation, or this object's parent's rotation")]
|
||||
public AlignmentModes AlignmentMode = AlignmentModes.None;
|
||||
|
||||
[Header("Movement")]
|
||||
[MMInformation("Set the <b>speed</b> at which the path will be crawled, and if the movement should be constant or eased.",MoreMountains.Tools.MMInformationAttribute.InformationType.Info,false)]
|
||||
/// the movement speed
|
||||
[Tooltip("the movement speed")]
|
||||
public float MovementSpeed = 1;
|
||||
/// returns the current speed at which the object is traveling
|
||||
public virtual Vector3 CurrentSpeed { get; protected set; }
|
||||
/// the movement type of the object
|
||||
[Tooltip("the movement type of the object")]
|
||||
public PossibleAccelerationType AccelerationType = PossibleAccelerationType.ConstantSpeed;
|
||||
/// the acceleration to apply to an object traveling between two points of the path.
|
||||
[Tooltip("the acceleration to apply to an object traveling between two points of the path.")]
|
||||
public AnimationCurve Acceleration = new AnimationCurve(new Keyframe(0,1f),new Keyframe(1f,0f));
|
||||
/// the chosen update mode (update, fixed update, late update)
|
||||
[Tooltip("the chosen update mode (update, fixed update, late update)")]
|
||||
public UpdateModes UpdateMode = UpdateModes.Update;
|
||||
|
||||
[Header("Settings")]
|
||||
[MMInformation("The <b>MinDistanceToGoal</b> is used to check if we've (almost) reached a point in the Path. The 2 other settings here are for debug only, don't change them.",MoreMountains.Tools.MMInformationAttribute.InformationType.Info,false)]
|
||||
/// the minimum distance to a point at which we'll arbitrarily decide the point's been reached
|
||||
[Tooltip("the minimum distance to a point at which we'll arbitrarily decide the point's been reached")]
|
||||
public float MinDistanceToGoal = .1f;
|
||||
/// the original position of the transform, hidden and shouldn't be accessed
|
||||
[Tooltip("the original position of the transform, hidden and shouldn't be accessed")]
|
||||
protected Vector3 _originalTransformPosition;
|
||||
/// if this is true, the object can move along the path
|
||||
public virtual bool CanMove { get; set; }
|
||||
|
||||
protected bool _originalTransformPositionStatus = false;
|
||||
protected bool _active=false;
|
||||
protected IEnumerator<Vector3> _currentPoint;
|
||||
protected int _direction = 1;
|
||||
protected Vector3 _initialPosition;
|
||||
protected Vector3 _finalPosition;
|
||||
protected Vector3 _previousPoint = Vector3.zero;
|
||||
protected float _waiting=0;
|
||||
protected int _currentIndex;
|
||||
protected float _distanceToNextPoint;
|
||||
protected bool _endReached = false;
|
||||
protected Vector3 _positionLastFrame;
|
||||
protected Vector3 _vector3Zero = Vector3.zero;
|
||||
|
||||
/// <summary>
|
||||
/// Initialization
|
||||
/// </summary>
|
||||
protected virtual void Awake ()
|
||||
{
|
||||
Initialization ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On Start we store our initial position
|
||||
/// </summary>
|
||||
protected virtual void Start()
|
||||
{
|
||||
_originalTransformPosition = transform.position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A public method you can call to reset the path
|
||||
/// </summary>
|
||||
public virtual void ResetPath()
|
||||
{
|
||||
Initialization();
|
||||
CanMove = false;
|
||||
transform.position = _originalTransformPosition;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flag inits, initial movement determination, and object positioning
|
||||
/// </summary>
|
||||
protected virtual void Initialization()
|
||||
{
|
||||
// on Start, we set our active flag to true
|
||||
_active=true;
|
||||
_endReached = false;
|
||||
CanMove = true;
|
||||
|
||||
// if the path is null we exit
|
||||
if(PathElements == null || PathElements.Count < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// we set our initial direction based on the settings
|
||||
if (LoopInitialMovementDirection == MovementDirection.Ascending)
|
||||
{
|
||||
_direction=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_direction=-1;
|
||||
}
|
||||
|
||||
// we initialize our path enumerator
|
||||
_currentPoint = GetPathEnumerator();
|
||||
_previousPoint = _currentPoint.Current;
|
||||
_currentPoint.MoveNext();
|
||||
|
||||
// initial positioning
|
||||
if (!_originalTransformPositionStatus)
|
||||
{
|
||||
_originalTransformPositionStatus = true;
|
||||
_originalTransformPosition = transform.position;
|
||||
}
|
||||
transform.position = PointPosition(_currentPoint.Current);
|
||||
}
|
||||
|
||||
protected virtual void FixedUpdate()
|
||||
{
|
||||
if (UpdateMode == UpdateModes.FixedUpdate)
|
||||
{
|
||||
ExecuteUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void LateUpdate()
|
||||
{
|
||||
if (UpdateMode == UpdateModes.LateUpdate)
|
||||
{
|
||||
ExecuteUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Update()
|
||||
{
|
||||
if (UpdateMode == UpdateModes.Update)
|
||||
{
|
||||
ExecuteUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override this to describe what happens when a point is reached
|
||||
/// </summary>
|
||||
protected virtual void PointReached()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override this to describe what happens when the end of the path is reached
|
||||
/// </summary>
|
||||
protected virtual void EndReached()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On update we keep moving along the path
|
||||
/// </summary>
|
||||
protected virtual void ExecuteUpdate ()
|
||||
{
|
||||
// if the path is null we exit, if we only go once and have reached the end we exit, if we can't move we exit
|
||||
if(PathElements == null
|
||||
|| PathElements.Count < 1
|
||||
|| _endReached
|
||||
|| !CanMove
|
||||
)
|
||||
{
|
||||
CurrentSpeed = _vector3Zero;
|
||||
return;
|
||||
}
|
||||
|
||||
Move ();
|
||||
|
||||
_positionLastFrame = this.transform.position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves the object and determines when a point has been reached
|
||||
/// </summary>
|
||||
protected virtual void Move()
|
||||
{
|
||||
// we wait until we can proceed
|
||||
_waiting -= Time.deltaTime;
|
||||
if (_waiting > 0)
|
||||
{
|
||||
CurrentSpeed = Vector3.zero;
|
||||
return;
|
||||
}
|
||||
|
||||
// we store our initial position to compute the current speed at the end of the udpate
|
||||
_initialPosition = transform.position;
|
||||
|
||||
// we move our object
|
||||
MoveAlongThePath();
|
||||
|
||||
// we decide if we've reached our next destination or not, if yes, we move our destination to the next point
|
||||
_distanceToNextPoint = (transform.position - (PointPosition(_currentPoint.Current))).magnitude;
|
||||
if(_distanceToNextPoint < MinDistanceToGoal)
|
||||
{
|
||||
//we check if we need to wait
|
||||
if (PathElements.Count > _currentIndex)
|
||||
{
|
||||
_waiting = PathElements[_currentIndex].Delay;
|
||||
}
|
||||
PointReached();
|
||||
_previousPoint = _currentPoint.Current;
|
||||
_currentPoint.MoveNext();
|
||||
}
|
||||
|
||||
// we determine the current speed
|
||||
_finalPosition = this.transform.position;
|
||||
if (Time.deltaTime != 0f)
|
||||
{
|
||||
CurrentSpeed = (_finalPosition - _initialPosition) / Time.deltaTime;
|
||||
}
|
||||
|
||||
if (_endReached)
|
||||
{
|
||||
EndReached();
|
||||
CurrentSpeed = Vector3.zero;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves the object along the path according to the specified movement type.
|
||||
/// </summary>
|
||||
public virtual void MoveAlongThePath()
|
||||
{
|
||||
switch (AccelerationType)
|
||||
{
|
||||
case PossibleAccelerationType.ConstantSpeed:
|
||||
transform.position = Vector3.MoveTowards (transform.position, PointPosition(_currentPoint.Current), Time.deltaTime * MovementSpeed);
|
||||
break;
|
||||
|
||||
case PossibleAccelerationType.EaseOut:
|
||||
transform.position = Vector3.Lerp (transform.position, PointPosition(_currentPoint.Current), Time.deltaTime * MovementSpeed);
|
||||
break;
|
||||
|
||||
case PossibleAccelerationType.AnimationCurve:
|
||||
float distanceBetweenPoints = Vector3.Distance (_previousPoint, _currentPoint.Current);
|
||||
|
||||
if (distanceBetweenPoints <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float remappedDistance = 1 - MMMaths.Remap (_distanceToNextPoint, 0f, distanceBetweenPoints, 0f, 1f);
|
||||
float speedFactor = Acceleration.Evaluate (remappedDistance);
|
||||
|
||||
transform.position = Vector3.MoveTowards (transform.position, PointPosition(_currentPoint.Current), Time.deltaTime * MovementSpeed * speedFactor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current target point in the path
|
||||
/// </summary>
|
||||
/// <returns>The path enumerator.</returns>
|
||||
public virtual IEnumerator<Vector3> GetPathEnumerator()
|
||||
{
|
||||
|
||||
// if the path is null we exit
|
||||
if(PathElements == null || PathElements.Count < 1)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
_currentIndex = index;
|
||||
while (true)
|
||||
{
|
||||
_currentIndex = index;
|
||||
yield return PathElements[index].PathElementPosition;
|
||||
|
||||
if(PathElements.Count <= 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// if the path is looping
|
||||
switch(CycleOption)
|
||||
{
|
||||
case CycleOptions.Loop:
|
||||
index = index + _direction;
|
||||
if (index < 0)
|
||||
{
|
||||
index = PathElements.Count - 1;
|
||||
}
|
||||
else if (index > PathElements.Count - 1)
|
||||
{
|
||||
index = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case CycleOptions.BackAndForth:
|
||||
if (index <= 0)
|
||||
{
|
||||
_direction = 1;
|
||||
}
|
||||
else if (index >= PathElements.Count - 1)
|
||||
{
|
||||
_direction = -1;
|
||||
}
|
||||
index = index + _direction;
|
||||
break;
|
||||
|
||||
case CycleOptions.OnlyOnce:
|
||||
if (index <= 0)
|
||||
{
|
||||
_direction = 1;
|
||||
}
|
||||
else if (index >= PathElements.Count - 1)
|
||||
{
|
||||
_direction = 0;
|
||||
CurrentSpeed = Vector3.zero;
|
||||
_endReached = true;
|
||||
}
|
||||
index = index + _direction;
|
||||
break;
|
||||
|
||||
case CycleOptions.Random:
|
||||
int newIndex = index;
|
||||
if (PathElements.Count > 1)
|
||||
{
|
||||
while (newIndex == index)
|
||||
{
|
||||
newIndex = Random.Range(0, PathElements.Count);
|
||||
}
|
||||
}
|
||||
index = newIndex;
|
||||
break;
|
||||
|
||||
case CycleOptions.StopAtBounds:
|
||||
if (index <= 0)
|
||||
{
|
||||
if (_direction == -1)
|
||||
{
|
||||
CurrentSpeed = Vector3.zero;
|
||||
_endReached = true;
|
||||
}
|
||||
_direction = 1;
|
||||
}
|
||||
else if (index >= PathElements.Count - 1)
|
||||
{
|
||||
if (_direction == 1)
|
||||
{
|
||||
CurrentSpeed = Vector3.zero;
|
||||
_endReached = true;
|
||||
}
|
||||
_direction = -1;
|
||||
}
|
||||
index = index + _direction;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call this method to force a change in direction at any time
|
||||
/// </summary>
|
||||
public virtual void ChangeDirection()
|
||||
{
|
||||
_direction = -_direction;
|
||||
_currentPoint.MoveNext();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On DrawGizmos, we draw lines to show the path the object will follow
|
||||
/// </summary>
|
||||
protected virtual void OnDrawGizmos()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (PathElements == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (PathElements.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// if we haven't stored the object's original position yet, we do it
|
||||
if (_originalTransformPositionStatus == false)
|
||||
{
|
||||
_originalTransformPosition = this.transform.position;
|
||||
_originalTransformPositionStatus = true;
|
||||
}
|
||||
// if we're not in runtime mode and the transform has changed, we update our position
|
||||
if (transform.hasChanged && _active==false)
|
||||
{
|
||||
_originalTransformPosition = this.transform.position;
|
||||
}
|
||||
// for each point in the path
|
||||
for (int i=0;i<PathElements.Count;i++)
|
||||
{
|
||||
// we draw a green point
|
||||
MMDebug.DrawGizmoPoint(PointPosition(i),0.2f,Color.green);
|
||||
|
||||
// we draw a line towards the next point in the path
|
||||
if ((i+1)<PathElements.Count)
|
||||
{
|
||||
Gizmos.color=Color.white;
|
||||
Gizmos.DrawLine(PointPosition(i), PointPosition(i + 1));
|
||||
}
|
||||
// we draw a line from the first to the last point if we're looping
|
||||
if ( (i == PathElements.Count-1) && (CycleOption == CycleOptions.Loop) )
|
||||
{
|
||||
Gizmos.color=Color.white;
|
||||
Gizmos.DrawLine(PointPosition(0), PointPosition(i));
|
||||
}
|
||||
}
|
||||
|
||||
// if the game is playing, we add a blue point to the destination, and a red point to the last visited point
|
||||
if (Application.isPlaying)
|
||||
{
|
||||
MMDebug.DrawGizmoPoint(PointPosition(_currentPoint.Current), 0.2f, Color.blue);
|
||||
MMDebug.DrawGizmoPoint(PointPosition(_previousPoint),0.2f,Color.red);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public virtual Vector3 PointPosition(int index)
|
||||
{
|
||||
return PointPosition(PathElements[index].PathElementPosition);
|
||||
}
|
||||
|
||||
public virtual Vector3 PointPosition(Vector3 relativePointPosition)
|
||||
{
|
||||
switch (AlignmentMode)
|
||||
{
|
||||
case AlignmentModes.None:
|
||||
return _originalTransformPosition + relativePointPosition;
|
||||
case AlignmentModes.ThisRotation:
|
||||
return _originalTransformPosition + this.transform.rotation * relativePointPosition;
|
||||
case AlignmentModes.ParentRotation:
|
||||
return _originalTransformPosition + this.transform.parent.rotation * relativePointPosition;
|
||||
}
|
||||
return Vector3.zero;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the original transform position.
|
||||
/// </summary>
|
||||
/// <param name="newOriginalTransformPosition">New original transform position.</param>
|
||||
public virtual void UpdateOriginalTransformPosition(Vector3 newOriginalTransformPosition)
|
||||
{
|
||||
_originalTransformPosition = newOriginalTransformPosition;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the original transform position.
|
||||
/// </summary>
|
||||
/// <returns>The original transform position.</returns>
|
||||
public virtual Vector3 GetOriginalTransformPosition()
|
||||
{
|
||||
return _originalTransformPosition;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the original transform position status.
|
||||
/// </summary>
|
||||
/// <param name="status">If set to <c>true</c> status.</param>
|
||||
public virtual void SetOriginalTransformPositionStatus(bool status)
|
||||
{
|
||||
_originalTransformPositionStatus = status;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the original transform position status.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c>, if original transform position status was gotten, <c>false</c> otherwise.</returns>
|
||||
public virtual bool GetOriginalTransformPositionStatus()
|
||||
{
|
||||
return _originalTransformPositionStatus ;
|
||||
}
|
||||
}
|
||||
}
|
||||
20
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPathMovement/MMPathMovement.cs.meta
vendored
Normal file
20
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPathMovement/MMPathMovement.cs.meta
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9e07de691a1179d4c8fc231dc7dcf219
|
||||
timeCreated: 1523894079
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 183370
|
||||
packageName: Feel
|
||||
packageVersion: 5.9.1
|
||||
assetPath: Assets/Feel/MMTools/Accessories/MMMovement/MMPathMovement/MMPathMovement.cs
|
||||
uploadId: 830868
|
||||
98
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPositionRecorder.cs
vendored
Normal file
98
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPositionRecorder.cs
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
/// <summary>
|
||||
/// Add this class on a Transform, and it'll record its position periodically
|
||||
/// The Positions array can then be read from anywhere to know where that object was in the past
|
||||
/// </summary>
|
||||
public class MMPositionRecorder : MonoBehaviour
|
||||
{
|
||||
/// the possible modes to run this recorder on
|
||||
public enum Modes { Framecount, Time }
|
||||
|
||||
[Header("Recording Settings")]
|
||||
/// the amount of positions to record
|
||||
public int NumberOfPositionsToRecord = 100;
|
||||
/// whether to record every X frames, or every X seconds
|
||||
public Modes Mode = Modes.Framecount;
|
||||
/// the amount of frames to wait for between two recordings
|
||||
[MMEnumCondition("Mode", (int)Modes.Framecount)]
|
||||
public int FrameInterval = 0;
|
||||
/// the duration (in seconds) between two recordings
|
||||
[MMEnumCondition("Mode", (int) Modes.Time)]
|
||||
public float TimeInterval = 0.02f;
|
||||
/// whether or not to record if the timescale is 0
|
||||
public bool RecordOnTimescaleZero = false;
|
||||
|
||||
[Header("Debug")]
|
||||
/// the array of positions (0 most recent, higher less recent)
|
||||
public Vector3[] Positions;
|
||||
/// the current frame counter
|
||||
[MMReadOnly]
|
||||
public int FrameCounter;
|
||||
|
||||
protected int _frameCountLastRecord = 0;
|
||||
protected float _timeLastRecord = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// On Awake, we initialize our array of positions
|
||||
/// </summary>
|
||||
protected virtual void Awake()
|
||||
{
|
||||
Positions = new Vector3[NumberOfPositionsToRecord];
|
||||
for (int i = 0; i < Positions.Length; i++)
|
||||
{
|
||||
Positions[i] = this.transform.position;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On Update we store our positions
|
||||
/// </summary>
|
||||
protected virtual void Update()
|
||||
{
|
||||
if (!RecordOnTimescaleZero && Time.timeScale == 0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
StorePositions();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores the position in the array and offsets it
|
||||
/// </summary>
|
||||
protected virtual void StorePositions()
|
||||
{
|
||||
FrameCounter = Time.frameCount;
|
||||
|
||||
if (Mode == Modes.Framecount)
|
||||
{
|
||||
if (FrameCounter - _frameCountLastRecord < FrameInterval)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_frameCountLastRecord = FrameCounter;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Time.time - _timeLastRecord < TimeInterval)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_timeLastRecord = Time.time;
|
||||
}
|
||||
|
||||
// we put our current position in the array at index 0
|
||||
Positions[0] = this.transform.position;
|
||||
|
||||
// we offset the array by 1 (index 0 moves to 1, etc)
|
||||
Array.Copy(Positions, 0, Positions, 1, Positions.Length - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
18
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPositionRecorder.cs.meta
vendored
Normal file
18
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPositionRecorder.cs.meta
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d82c3eb70c39c44faf5889b222def4b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 183370
|
||||
packageName: Feel
|
||||
packageVersion: 5.9.1
|
||||
assetPath: Assets/Feel/MMTools/Accessories/MMMovement/MMPositionRecorder.cs
|
||||
uploadId: 830868
|
||||
94
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPreventPassingThrough.cs
vendored
Normal file
94
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPreventPassingThrough.cs
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
/// <summary>
|
||||
/// Prevents fast moving objects from going through colliders by casting a ray backwards after each movement
|
||||
/// </summary>
|
||||
[AddComponentMenu("More Mountains/Tools/Movement/MM Prevent Passing Through")]
|
||||
public class MMPreventPassingThrough : MonoBehaviour
|
||||
{
|
||||
/// the layer mask to search obstacles on
|
||||
public LayerMask ObstaclesLayerMask;
|
||||
/// the bounds adjustment variable
|
||||
public float SkinWidth = 0.1f;
|
||||
|
||||
protected float _smallestBoundsWidth;
|
||||
protected float _adjustedSmallestBoundsWidth;
|
||||
protected float _squaredBoundsWidth;
|
||||
protected Vector3 _positionLastFrame;
|
||||
protected Rigidbody _rigidbody;
|
||||
protected Collider _collider;
|
||||
protected Vector3 _lastMovement;
|
||||
protected float _lastMovementSquared;
|
||||
|
||||
/// <summary>
|
||||
/// On Start we initialize our object
|
||||
/// </summary>
|
||||
protected virtual void Start()
|
||||
{
|
||||
Initialization ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Grabs the rigidbody and computes the bounds width
|
||||
/// </summary>
|
||||
protected virtual void Initialization()
|
||||
{
|
||||
_rigidbody = GetComponent<Rigidbody>();
|
||||
_positionLastFrame = _rigidbody.position;
|
||||
|
||||
_collider = GetComponent<Collider>();
|
||||
|
||||
_smallestBoundsWidth = Mathf.Min(Mathf.Min(_collider.bounds.extents.x, _collider.bounds.extents.y), _collider.bounds.extents.z);
|
||||
_adjustedSmallestBoundsWidth = _smallestBoundsWidth * (1.0f - SkinWidth);
|
||||
_squaredBoundsWidth = _smallestBoundsWidth * _smallestBoundsWidth;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On Enable, we initialize our last frame position
|
||||
/// </summary>
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
_positionLastFrame = this.transform.position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On fixedUpdate, checks the last movement and if needed casts a ray to detect obstacles
|
||||
/// </summary>
|
||||
protected virtual void FixedUpdate()
|
||||
{
|
||||
_lastMovement = _rigidbody.position - _positionLastFrame;
|
||||
_lastMovementSquared = _lastMovement.sqrMagnitude;
|
||||
|
||||
// if we've moved further than our bounds, we may have missed something
|
||||
if (_lastMovementSquared > _squaredBoundsWidth)
|
||||
{
|
||||
float movementMagnitude = Mathf.Sqrt(_lastMovementSquared);
|
||||
|
||||
// we cast a ray backwards to see if we should have hit something
|
||||
RaycastHit hitInfo;
|
||||
if (Physics.Raycast(_positionLastFrame, _lastMovement, out hitInfo, movementMagnitude, ObstaclesLayerMask.value))
|
||||
{
|
||||
if (!hitInfo.collider)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (hitInfo.collider.isTrigger)
|
||||
{
|
||||
hitInfo.collider.SendMessage("OnTriggerEnter", _collider);
|
||||
}
|
||||
|
||||
if (!hitInfo.collider.isTrigger)
|
||||
{
|
||||
_rigidbody.position = hitInfo.point - (_lastMovement / movementMagnitude) * _adjustedSmallestBoundsWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
_positionLastFrame = _rigidbody.position;
|
||||
}
|
||||
}
|
||||
}
|
||||
18
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPreventPassingThrough.cs.meta
vendored
Normal file
18
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPreventPassingThrough.cs.meta
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3b2a1f7815d40344186f7659d93abe80
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 183370
|
||||
packageName: Feel
|
||||
packageVersion: 5.9.1
|
||||
assetPath: Assets/Feel/MMTools/Accessories/MMMovement/MMPreventPassingThrough.cs
|
||||
uploadId: 830868
|
||||
134
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPreventPassingThrough2D.cs
vendored
Normal file
134
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPreventPassingThrough2D.cs
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
#if MM_PHYSICS2D
|
||||
/// <summary>
|
||||
/// Prevents fast moving objects from going through colliders by casting a ray backwards after each movement
|
||||
/// </summary>
|
||||
[AddComponentMenu("More Mountains/Tools/Movement/MM Prevent Passing Through 2D")]
|
||||
public class MMPreventPassingThrough2D : MonoBehaviour
|
||||
{
|
||||
public enum Modes { Raycast, BoxCast }
|
||||
/// whether to cast a ray or a boxcast to look for targets
|
||||
public Modes Mode = Modes.Raycast;
|
||||
/// the layer mask to search obstacles on
|
||||
public LayerMask ObstaclesLayerMask;
|
||||
/// the bounds adjustment variable
|
||||
public float SkinWidth = 0.1f;
|
||||
/// whether or not to reposition the rb if hitting a trigger collider
|
||||
public bool RepositionRigidbodyIfHitTrigger = true;
|
||||
/// whether or not to reposition the rb if hitting a non trigger collider
|
||||
[FormerlySerializedAs("RepositionRigidbody")]
|
||||
public bool RepositionRigidbodyIfHitNonTrigger = true;
|
||||
|
||||
[Header("Debug")]
|
||||
[MMReadOnly]
|
||||
public RaycastHit2D Hit;
|
||||
|
||||
protected float _smallestBoundsWidth;
|
||||
protected float _adjustedSmallestBoundsWidth;
|
||||
protected float _squaredBoundsWidth;
|
||||
protected Vector3 _positionLastFrame;
|
||||
protected Rigidbody2D _rigidbody;
|
||||
protected Collider2D _collider;
|
||||
protected Vector2 _lastMovement;
|
||||
protected float _lastMovementSquared;
|
||||
protected RaycastHit2D _hitInfo;
|
||||
protected Vector2 _colliderSize;
|
||||
|
||||
/// <summary>
|
||||
/// On Start we initialize our object
|
||||
/// </summary>
|
||||
protected virtual void Start()
|
||||
{
|
||||
Initialization ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Grabs the rigidbody and computes the bounds width
|
||||
/// </summary>
|
||||
protected virtual void Initialization()
|
||||
{
|
||||
_rigidbody = GetComponent<Rigidbody2D>();
|
||||
_positionLastFrame = _rigidbody.position;
|
||||
|
||||
_collider = GetComponent<Collider2D>();
|
||||
if (_collider as BoxCollider2D != null)
|
||||
{
|
||||
_colliderSize = (_collider as BoxCollider2D).size;
|
||||
}
|
||||
|
||||
_smallestBoundsWidth = Mathf.Min(Mathf.Min(_collider.bounds.extents.x, _collider.bounds.extents.y), _collider.bounds.extents.z);
|
||||
_adjustedSmallestBoundsWidth = _smallestBoundsWidth * (1.0f - SkinWidth);
|
||||
_squaredBoundsWidth = _smallestBoundsWidth * _smallestBoundsWidth;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On Enable, we initialize our last frame position
|
||||
/// </summary>
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
_positionLastFrame = this.transform.position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On fixedUpdate, checks the last movement and if needed casts a ray to detect obstacles
|
||||
/// </summary>
|
||||
protected virtual void Update()
|
||||
{
|
||||
_lastMovement = this.transform.position - _positionLastFrame;
|
||||
_lastMovementSquared = _lastMovement.sqrMagnitude;
|
||||
|
||||
// if we've moved further than our bounds, we may have missed something
|
||||
if (_lastMovementSquared > _squaredBoundsWidth)
|
||||
{
|
||||
float movementMagnitude = Mathf.Sqrt(_lastMovementSquared);
|
||||
|
||||
// we cast a ray backwards to see if we should have hit something
|
||||
if (Mode == Modes.Raycast)
|
||||
{
|
||||
_hitInfo = MMDebug.RayCast(_positionLastFrame, _lastMovement.normalized, movementMagnitude, ObstaclesLayerMask, Color.blue, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
_hitInfo = Physics2D.BoxCast(origin: _positionLastFrame,
|
||||
size: _colliderSize,
|
||||
angle: 0,
|
||||
layerMask: ObstaclesLayerMask,
|
||||
direction: _lastMovement.normalized,
|
||||
distance: movementMagnitude);
|
||||
}
|
||||
|
||||
if (_hitInfo.collider != null)
|
||||
{
|
||||
if (_hitInfo.collider.isTrigger)
|
||||
{
|
||||
_hitInfo.collider.SendMessage("OnTriggerEnter2D", _collider, SendMessageOptions.DontRequireReceiver);
|
||||
if (RepositionRigidbodyIfHitTrigger)
|
||||
{
|
||||
this.transform.position = _hitInfo.point - (_lastMovement / movementMagnitude) * _adjustedSmallestBoundsWidth;
|
||||
_rigidbody.position = _hitInfo.point - (_lastMovement / movementMagnitude) * _adjustedSmallestBoundsWidth;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_hitInfo.collider.isTrigger)
|
||||
{
|
||||
Hit = _hitInfo;
|
||||
this.gameObject.SendMessage("PreventedCollision2D", Hit, SendMessageOptions.DontRequireReceiver);
|
||||
if (RepositionRigidbodyIfHitNonTrigger)
|
||||
{
|
||||
this.transform.position = _hitInfo.point - (_lastMovement / movementMagnitude) * _adjustedSmallestBoundsWidth;
|
||||
_rigidbody.position = _hitInfo.point - (_lastMovement / movementMagnitude) * _adjustedSmallestBoundsWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_positionLastFrame = this.transform.position;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
20
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPreventPassingThrough2D.cs.meta
vendored
Normal file
20
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPreventPassingThrough2D.cs.meta
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dfdd322a582c3bc429d2350807e8a2c3
|
||||
timeCreated: 1523900811
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 183370
|
||||
packageName: Feel
|
||||
packageVersion: 5.9.1
|
||||
assetPath: Assets/Feel/MMTools/Accessories/MMMovement/MMPreventPassingThrough2D.cs
|
||||
uploadId: 830868
|
||||
143
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPreventPassingThrough3D.cs
vendored
Normal file
143
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPreventPassingThrough3D.cs
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
/// <summary>
|
||||
/// Prevents fast moving objects from going through colliders by casting a ray backwards after each movement
|
||||
/// </summary>
|
||||
[AddComponentMenu("More Mountains/Tools/Movement/MM Prevent Passing Through 3D")]
|
||||
public class MMPreventPassingThrough3D : MonoBehaviour
|
||||
{
|
||||
/// the layer mask to search obstacles on
|
||||
public LayerMask ObstaclesLayerMask;
|
||||
/// the bounds adjustment variable
|
||||
public float SkinWidth = 0.1f;
|
||||
public bool RepositionRigidbody = true;
|
||||
/// the layer mask to filter when to reposition rigidbody
|
||||
public LayerMask RepositionRigidbodyLayerMask;
|
||||
|
||||
public enum AdjustmentAxis { Auto, X, Y, Z }
|
||||
/// the local axis of the collider to use for adjustment (usually you'll want to use the axis the object is moving on)
|
||||
public AdjustmentAxis Adjustment = AdjustmentAxis.Auto;
|
||||
|
||||
|
||||
protected float _adjustmentDistance;
|
||||
protected float _adjustedDistance;
|
||||
protected float _squaredBoundsWidth;
|
||||
protected Vector3 _positionLastFrame;
|
||||
protected Rigidbody _rigidbody;
|
||||
protected Collider _collider;
|
||||
protected Vector3 _lastMovement;
|
||||
protected float _lastMovementSquared;
|
||||
|
||||
protected virtual void OnValidate()
|
||||
{
|
||||
// force initialized RepositionRigidbodyLayerMask, same behavior as before
|
||||
if (RepositionRigidbody)
|
||||
{
|
||||
if (RepositionRigidbodyLayerMask.value == default)
|
||||
{
|
||||
RepositionRigidbodyLayerMask = ObstaclesLayerMask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On Start we initialize our object
|
||||
/// </summary>
|
||||
protected virtual void Start()
|
||||
{
|
||||
Initialization ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Grabs the rigidbody and computes the bounds width
|
||||
/// </summary>
|
||||
protected virtual void Initialization()
|
||||
{
|
||||
_rigidbody = GetComponent<Rigidbody>();
|
||||
_positionLastFrame = _rigidbody.position;
|
||||
|
||||
_collider = GetComponent<Collider>();
|
||||
|
||||
_adjustmentDistance = ComputeAdjustmentDistance();
|
||||
_adjustedDistance = _adjustmentDistance * (1.0f - SkinWidth);
|
||||
_squaredBoundsWidth = _adjustmentDistance * _adjustmentDistance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines the adjustment distance, over which we decide whether or not we've moved too far
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected virtual float ComputeAdjustmentDistance()
|
||||
{
|
||||
switch (Adjustment)
|
||||
{
|
||||
case AdjustmentAxis.X:
|
||||
return _collider.bounds.extents.x;
|
||||
case AdjustmentAxis.Y:
|
||||
return _collider.bounds.extents.y;
|
||||
case AdjustmentAxis.Z:
|
||||
return _collider.bounds.extents.z;
|
||||
}
|
||||
return Mathf.Min(Mathf.Min(_collider.bounds.extents.x, _collider.bounds.extents.y), _collider.bounds.extents.z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On Enable, we initialize our last frame position
|
||||
/// </summary>
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
_positionLastFrame = this.transform.position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On fixedUpdate, checks the last movement and if needed casts a ray to detect obstacles
|
||||
/// </summary>
|
||||
protected virtual void FixedUpdate()
|
||||
{
|
||||
_lastMovement = this.transform.position - _positionLastFrame;
|
||||
_lastMovementSquared = _lastMovement.sqrMagnitude;
|
||||
|
||||
// if we've moved further than our bounds, we may have missed something
|
||||
if (_lastMovementSquared > _squaredBoundsWidth)
|
||||
{
|
||||
float movementMagnitude = Mathf.Sqrt(_lastMovementSquared);
|
||||
|
||||
// we cast a ray backwards to see if we should have hit something
|
||||
RaycastHit hitInfo;
|
||||
if (Physics.Raycast(_positionLastFrame, _lastMovement, out hitInfo, movementMagnitude, ObstaclesLayerMask.value))
|
||||
{
|
||||
if (!hitInfo.collider)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (hitInfo.collider.isTrigger)
|
||||
{
|
||||
hitInfo.collider.SendMessage("OnTriggerEnter", _collider);
|
||||
}
|
||||
|
||||
if (!hitInfo.collider.isTrigger)
|
||||
{
|
||||
this.gameObject.SendMessage("PreventedCollision3D", hitInfo, SendMessageOptions.DontRequireReceiver);
|
||||
if (RepositionRigidbody)
|
||||
{
|
||||
var hitLayer = hitInfo.collider.gameObject.layer;
|
||||
if (0 != (1 << hitLayer & RepositionRigidbodyLayerMask))
|
||||
{
|
||||
this.transform.position = hitInfo.point - (_lastMovement / movementMagnitude) * _adjustedDistance;
|
||||
_rigidbody.position = hitInfo.point - (_lastMovement / movementMagnitude) * _adjustedDistance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_positionLastFrame = this.transform.position;
|
||||
}
|
||||
}
|
||||
}
|
||||
20
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPreventPassingThrough3D.cs.meta
vendored
Normal file
20
Assets/External/Feel/MMTools/Accessories/MMMovement/MMPreventPassingThrough3D.cs.meta
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 194c644ad43b53c478e2164aa4f41cb0
|
||||
timeCreated: 1523900811
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 183370
|
||||
packageName: Feel
|
||||
packageVersion: 5.9.1
|
||||
assetPath: Assets/Feel/MMTools/Accessories/MMMovement/MMPreventPassingThrough3D.cs
|
||||
uploadId: 830868
|
||||
321
Assets/External/Feel/MMTools/Accessories/MMMovement/MMSquashAndStretch.cs
vendored
Normal file
321
Assets/External/Feel/MMTools/Accessories/MMMovement/MMSquashAndStretch.cs
vendored
Normal file
@@ -0,0 +1,321 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
/// <summary>
|
||||
/// This component will automatically update scale and rotation
|
||||
/// Put it one level below the top, and have the model one level below that
|
||||
/// Hierarchy should be as follows :
|
||||
///
|
||||
/// Parent (where the logic (and optionnally rigidbody lies)
|
||||
/// - MMSquashAndStretch
|
||||
/// - - Model / sprite
|
||||
///
|
||||
/// Make sure this intermediary layer only has one child
|
||||
/// If movement feels glitchy make sure your rigidbody is on Interpolate
|
||||
/// </summary>
|
||||
[AddComponentMenu("More Mountains/Tools/Movement/MM Squash And Stretch")]
|
||||
public class MMSquashAndStretch : MonoBehaviour
|
||||
{
|
||||
public enum Timescales { Regular, Unscaled }
|
||||
public enum Modes { Rigidbody, Rigidbody2D, Position }
|
||||
|
||||
[MMInformation("This component will apply squash and stretch based on velocity (either position based or computed from a Rigidbody. It has to be put on an intermediary level in the hierarchy, between the logic (top level) and the model (bottom level).", MMInformationAttribute.InformationType.Info, false)]
|
||||
[Header("Velocity Detection")]
|
||||
/// the possible ways to get velocity from
|
||||
[Tooltip("the possible ways to get velocity from")]
|
||||
public Modes Mode = Modes.Position;
|
||||
/// whether we should use deltaTime or unscaledDeltaTime
|
||||
[Tooltip("whether we should use deltaTime or unscaledDeltaTime")]
|
||||
public Timescales Timescale = Timescales.Regular;
|
||||
|
||||
[Header("Settings")]
|
||||
/// the intensity of the squash and stretch
|
||||
[Tooltip("the intensity of the squash and stretch")]
|
||||
public float Intensity = 0.02f;
|
||||
/// the maximum velocity of your parent object, used to remap the computed one
|
||||
[Tooltip("the maximum velocity of your parent object, used to remap the computed one")]
|
||||
public float MaximumVelocity = 1f;
|
||||
|
||||
[Header("Rescale")]
|
||||
/// the minimum scale to apply to this object
|
||||
[Tooltip("the minimum scale to apply to this object")]
|
||||
public Vector3 MinimumScale = new Vector3(0.5f, 0.5f, 0.5f);
|
||||
/// the maximum scale to apply to this object
|
||||
[Tooltip("the maximum scale to apply to this object")]
|
||||
public Vector3 MaximumScale = new Vector3(2f, 2f, 2f);
|
||||
/// whether or not to rescale on the x axis
|
||||
[Tooltip("whether or not to rescale on the x axis")]
|
||||
public bool RescaleX = true;
|
||||
/// whether or not to rescale on the y axis
|
||||
[Tooltip("whether or not to rescale on the y axis")]
|
||||
public bool RescaleY = true;
|
||||
/// whether or not to rescale on the z axis
|
||||
[Tooltip("whether or not to rescale on the z axis")]
|
||||
public bool RescaleZ = true;
|
||||
/// whether or not to rotate the transform to align with the current direction
|
||||
[Tooltip("whether or not to rotate the transform to align with the current direction")]
|
||||
public bool RotateToMatchDirection = true;
|
||||
|
||||
[Header("Squash")]
|
||||
/// if this is true, the object will squash once velocity goes below the specified threshold
|
||||
[Tooltip("if this is true, the object will squash once velocity goes below the specified threshold")]
|
||||
public bool AutoSquashOnStop = false;
|
||||
/// the curve to apply when squashing the object (this describes scale on x and z, will be inverted for y to maintain mass)
|
||||
[Tooltip("the curve to apply when squashing the object (this describes scale on x and z, will be inverted for y to maintain mass)")]
|
||||
public AnimationCurve SquashCurve = new AnimationCurve(new Keyframe(0, 0), new Keyframe(0.5f, 1f), new Keyframe(1, 0f));
|
||||
/// the velocity threshold after which a squash can be triggered if the object stops
|
||||
[Tooltip("the velocity threshold after which a squash can be triggered if the object stops")]
|
||||
public float SquashVelocityThreshold = 0.1f;
|
||||
/// the maximum duration of the squash (will be reduced if velocity is low)
|
||||
[Tooltip("the maximum duration of the squash (will be reduced if velocity is low)")]
|
||||
[MMVector("Min","Max")]
|
||||
public Vector2 SquashDuration = new Vector2(0.25f, 0.5f);
|
||||
/// the maximum intensity of the squash
|
||||
[Tooltip("the maximum intensity of the squash")]
|
||||
[MMVector("Min", "Max")]
|
||||
public Vector2 SquashIntensity = new Vector2(0f, 1f);
|
||||
|
||||
[Header("Spring")]
|
||||
/// whether or not to add extra spring to the squash and stretch
|
||||
[Tooltip("whether or not to add extra spring to the squash and stretch")]
|
||||
public bool Spring = false;
|
||||
/// the damping to apply to the spring
|
||||
[Tooltip("the damping to apply to the spring")]
|
||||
[MMCondition("Spring", true)]
|
||||
public float SpringDamping = 0.3f;
|
||||
/// the spring's frequency
|
||||
[Tooltip("the spring's frequency")]
|
||||
[MMCondition("Spring", true)]
|
||||
public float SpringFrequency = 3f;
|
||||
|
||||
[Header("Debug")]
|
||||
[MMReadOnly]
|
||||
/// the current velocity of the parent object
|
||||
[Tooltip("the current velocity of the parent object")]
|
||||
public Vector3 Velocity;
|
||||
[MMReadOnly]
|
||||
/// the remapped velocity
|
||||
[Tooltip("the remapped velocity")]
|
||||
public float RemappedVelocity;
|
||||
[MMReadOnly]
|
||||
/// the current velocity magnitude
|
||||
[Tooltip("the current velocity magnitude")]
|
||||
public float VelocityMagnitude;
|
||||
|
||||
public virtual float TimescaleTime { get { return (Timescale == Timescales.Regular) ? Time.time : Time.unscaledTime; } }
|
||||
public virtual float TimescaleDeltaTime { get { return (Timescale == Timescales.Regular) ? Time.deltaTime : Time.unscaledDeltaTime; } }
|
||||
|
||||
#if MM_PHYSICS2D
|
||||
protected Rigidbody2D _rigidbody2D;
|
||||
#endif
|
||||
protected Rigidbody _rigidbody;
|
||||
protected Transform _childTransform;
|
||||
protected Transform _parentTransform;
|
||||
protected Vector3 _direction;
|
||||
protected Vector3 _previousPosition;
|
||||
protected Vector3 _newLocalScale;
|
||||
protected Vector3 _initialScale;
|
||||
protected Quaternion _newRotation = Quaternion.identity;
|
||||
protected Quaternion _deltaRotation;
|
||||
protected float _squashStartedAt = 0f;
|
||||
protected bool _squashing = false;
|
||||
protected float _squashIntensity;
|
||||
protected float _squashDuration;
|
||||
protected bool _movementStarted = false;
|
||||
protected float _lastVelocity = 0f;
|
||||
protected Vector3 _springScale;
|
||||
protected Vector3 _springVelocity = Vector3.zero;
|
||||
|
||||
/// <summary>
|
||||
/// On start, we initialize our component
|
||||
/// </summary>
|
||||
protected virtual void Start()
|
||||
{
|
||||
Initialization();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores the initial scale, grabs the rigidbodies (or tries to), as well as the parent and child
|
||||
/// </summary>
|
||||
protected virtual void Initialization()
|
||||
{
|
||||
_initialScale = this.transform.localScale;
|
||||
_springScale = _initialScale;
|
||||
|
||||
_rigidbody = this.transform.parent.GetComponent<Rigidbody>();
|
||||
#if MM_PHYSICS2D
|
||||
_rigidbody2D = this.transform.parent.GetComponent<Rigidbody2D>();
|
||||
#endif
|
||||
|
||||
_childTransform = this.transform.GetChild(0).transform;
|
||||
_parentTransform = this.transform.parent.GetComponent<Transform>();
|
||||
|
||||
_previousPosition = _parentTransform.position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On late update, we apply our squash and stretch effect
|
||||
/// </summary>
|
||||
protected virtual void LateUpdate()
|
||||
{
|
||||
SquashAndStretch();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes velocity and applies the effect
|
||||
/// </summary>
|
||||
protected virtual void SquashAndStretch()
|
||||
{
|
||||
if (TimescaleDeltaTime <= 0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ComputeVelocityAndDirection();
|
||||
ComputeNewRotation();
|
||||
ComputeNewLocalScale();
|
||||
StorePreviousPosition();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines the current velocity and direction of the parent object
|
||||
/// </summary>
|
||||
protected virtual void ComputeVelocityAndDirection()
|
||||
{
|
||||
Velocity = Vector3.zero;
|
||||
|
||||
switch (Mode)
|
||||
{
|
||||
case Modes.Rigidbody:
|
||||
Velocity = _rigidbody.linearVelocity;
|
||||
break;
|
||||
|
||||
case Modes.Rigidbody2D:
|
||||
#if MM_PHYSICS2D
|
||||
Velocity = _rigidbody2D.linearVelocity;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case Modes.Position:
|
||||
Velocity = (_previousPosition - _parentTransform.position) / TimescaleDeltaTime;
|
||||
break;
|
||||
}
|
||||
|
||||
VelocityMagnitude = Velocity.magnitude;
|
||||
RemappedVelocity = MMMaths.Remap(VelocityMagnitude, 0f, MaximumVelocity, 0f, 1f);
|
||||
_direction = Vector3.Normalize(Velocity);
|
||||
|
||||
if (AutoSquashOnStop)
|
||||
{
|
||||
// if we've moved fast enough and have now stopped, we trigger a squash
|
||||
if (VelocityMagnitude > SquashVelocityThreshold)
|
||||
{
|
||||
_movementStarted = true;
|
||||
_lastVelocity = Mathf.Clamp(VelocityMagnitude, 0f, MaximumVelocity);
|
||||
}
|
||||
else if (_movementStarted)
|
||||
{
|
||||
_movementStarted = false;
|
||||
_squashing = true;
|
||||
float duration = MMMaths.Remap(_lastVelocity, 0f, MaximumVelocity, SquashDuration.x, SquashDuration.y);
|
||||
float intensity = MMMaths.Remap(_lastVelocity, 0f, MaximumVelocity, SquashIntensity.x, SquashIntensity.y);
|
||||
Squash(duration, intensity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes a new rotation for both this object and the child
|
||||
/// </summary>
|
||||
protected virtual void ComputeNewRotation()
|
||||
{
|
||||
if (!RotateToMatchDirection)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (VelocityMagnitude > 0.01f)
|
||||
{
|
||||
_newRotation = Quaternion.FromToRotation(Vector3.up, _direction);
|
||||
}
|
||||
_deltaRotation = _parentTransform.rotation;
|
||||
this.transform.rotation = _newRotation;
|
||||
_childTransform.rotation = _deltaRotation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes a new local scale for this object
|
||||
/// </summary>
|
||||
protected virtual void ComputeNewLocalScale()
|
||||
{
|
||||
if (_squashing)
|
||||
{
|
||||
float elapsed = MMMaths.Remap(TimescaleTime - _squashStartedAt, 0f, _squashDuration, 0f, 1f);
|
||||
float curveValue = SquashCurve.Evaluate(elapsed);
|
||||
_newLocalScale.x = _initialScale.x + curveValue * _squashIntensity;
|
||||
_newLocalScale.y = _initialScale.y - curveValue * _squashIntensity;
|
||||
_newLocalScale.z = _initialScale.z + curveValue * _squashIntensity;
|
||||
|
||||
if (elapsed >= 1f)
|
||||
{
|
||||
_squashing = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_newLocalScale.x = Mathf.Clamp01(1f / (RemappedVelocity + 0.001f));
|
||||
_newLocalScale.y = RemappedVelocity;
|
||||
_newLocalScale.z = Mathf.Clamp01(1f / (RemappedVelocity + 0.001f));
|
||||
_newLocalScale = Vector3.Lerp(Vector3.one, _newLocalScale, VelocityMagnitude * Intensity);
|
||||
}
|
||||
|
||||
_newLocalScale.x = Mathf.Clamp(_newLocalScale.x, MinimumScale.x, MaximumScale.x);
|
||||
_newLocalScale.y = Mathf.Clamp(_newLocalScale.y, MinimumScale.y, MaximumScale.y);
|
||||
_newLocalScale.z = Mathf.Clamp(_newLocalScale.z, MinimumScale.z, MaximumScale.z);
|
||||
|
||||
if (Spring)
|
||||
{
|
||||
MMMaths.Spring(ref _springScale, _newLocalScale, ref _springVelocity, SpringDamping, SpringFrequency, Time.deltaTime);
|
||||
_newLocalScale = _springScale;
|
||||
}
|
||||
|
||||
if (!RescaleX)
|
||||
{
|
||||
_newLocalScale.x = _initialScale.x;
|
||||
}
|
||||
if (!RescaleY)
|
||||
{
|
||||
_newLocalScale.y = _initialScale.y;
|
||||
}
|
||||
if (!RescaleZ)
|
||||
{
|
||||
_newLocalScale.z = _initialScale.z;
|
||||
}
|
||||
|
||||
this.transform.localScale = _newLocalScale;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores the previous position of the parent to compute velocity
|
||||
/// </summary>
|
||||
protected virtual void StorePreviousPosition()
|
||||
{
|
||||
_previousPosition = _parentTransform.position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggered either directly or via the AutoSquash setting, this squashes the object (usually after a contact / stop)
|
||||
/// </summary>
|
||||
/// <param name="duration"></param>
|
||||
/// <param name="intensity"></param>
|
||||
public virtual void Squash(float duration, float intensity)
|
||||
{
|
||||
_squashStartedAt = TimescaleTime;
|
||||
_squashing = true;
|
||||
_squashIntensity = intensity;
|
||||
_squashDuration = duration;
|
||||
}
|
||||
}
|
||||
}
|
||||
18
Assets/External/Feel/MMTools/Accessories/MMMovement/MMSquashAndStretch.cs.meta
vendored
Normal file
18
Assets/External/Feel/MMTools/Accessories/MMMovement/MMSquashAndStretch.cs.meta
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aade595aee3a1d24c9845361684f77d6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 183370
|
||||
packageName: Feel
|
||||
packageVersion: 5.9.1
|
||||
assetPath: Assets/Feel/MMTools/Accessories/MMMovement/MMSquashAndStretch.cs
|
||||
uploadId: 830868
|
||||
120
Assets/External/Feel/MMTools/Accessories/MMMovement/MMStayInPlace.cs
vendored
Normal file
120
Assets/External/Feel/MMTools/Accessories/MMMovement/MMStayInPlace.cs
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
/// <summary>
|
||||
/// This class forces a transform to stay at a fixed position, rotation and/or scale.
|
||||
/// </summary>
|
||||
[AddComponentMenu("More Mountains/Tools/Movement/MM Stay In Place")]
|
||||
public class MMStayInPlace : MonoBehaviour
|
||||
{
|
||||
public enum Spaces { World, Local }
|
||||
public enum UpdateModes { Update, FixedUpdate, LateUpdate }
|
||||
|
||||
[Header("Modes")]
|
||||
public UpdateModes UpdateMode = UpdateModes.LateUpdate;
|
||||
public Spaces Space = Spaces.World;
|
||||
|
||||
[Header("Attributes")]
|
||||
|
||||
public bool FixedPosition = true;
|
||||
public bool FixedRotation = true;
|
||||
public bool FixedScale = true;
|
||||
|
||||
[Header("Overrides")]
|
||||
|
||||
public bool OverridePosition = false;
|
||||
[MMCondition("OverridePosition", true)]
|
||||
public Vector3 OverridePositionValue;
|
||||
|
||||
public bool OverrideRotation = false;
|
||||
[MMCondition("OverrideRotation", true)]
|
||||
public Vector3 OverrideRotationValue;
|
||||
|
||||
public bool OverrideScale = false;
|
||||
[MMCondition("OverrideScale", true)]
|
||||
public Vector3 OverrideScaleValue;
|
||||
|
||||
protected Vector3 _initialPosition;
|
||||
protected Quaternion _initialRotation;
|
||||
protected Vector3 _initialScale;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
Initialization();
|
||||
}
|
||||
|
||||
protected virtual void Initialization()
|
||||
{
|
||||
_initialPosition = (Space == Spaces.World) ? this.transform.position : this.transform.localPosition;
|
||||
_initialRotation = (Space == Spaces.World) ? this.transform.rotation : this.transform.localRotation;
|
||||
_initialScale = (Space == Spaces.World) ? this.transform.position : this.transform.localScale;
|
||||
|
||||
if (OverridePosition)
|
||||
{
|
||||
_initialPosition = OverridePositionValue;
|
||||
}
|
||||
if (OverrideRotation)
|
||||
{
|
||||
_initialRotation = Quaternion.Euler(OverrideRotationValue);
|
||||
}
|
||||
if (OverrideScale)
|
||||
{
|
||||
_initialScale = OverrideScaleValue;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Update()
|
||||
{
|
||||
if (UpdateMode == UpdateModes.Update)
|
||||
{
|
||||
StayInPlace();
|
||||
}
|
||||
}
|
||||
protected virtual void FixedUpdate()
|
||||
{
|
||||
if (UpdateMode == UpdateModes.FixedUpdate)
|
||||
{
|
||||
StayInPlace();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void LateUpdate()
|
||||
{
|
||||
if (UpdateMode == UpdateModes.LateUpdate)
|
||||
{
|
||||
StayInPlace();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void StayInPlace()
|
||||
{
|
||||
if (Space == Spaces.World)
|
||||
{
|
||||
if (FixedPosition)
|
||||
{
|
||||
this.transform.position = _initialPosition;
|
||||
}
|
||||
if (FixedRotation)
|
||||
{
|
||||
this.transform.rotation = _initialRotation;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FixedPosition)
|
||||
{
|
||||
this.transform.localPosition = _initialPosition;
|
||||
}
|
||||
if (FixedRotation)
|
||||
{
|
||||
this.transform.localRotation = _initialRotation;
|
||||
}
|
||||
}
|
||||
if (FixedScale)
|
||||
{
|
||||
this.transform.localScale = _initialScale;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
18
Assets/External/Feel/MMTools/Accessories/MMMovement/MMStayInPlace.cs.meta
vendored
Normal file
18
Assets/External/Feel/MMTools/Accessories/MMMovement/MMStayInPlace.cs.meta
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9b6f7c95fc9569f47a5b6b912da588a7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 183370
|
||||
packageName: Feel
|
||||
packageVersion: 5.9.1
|
||||
assetPath: Assets/Feel/MMTools/Accessories/MMMovement/MMStayInPlace.cs
|
||||
uploadId: 830868
|
||||
Reference in New Issue
Block a user