导入leg插件,完成腿部动画
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e5fc2f0ca890a5c4399a76a12ef0edc0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,114 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace FIMSpace
|
||||
{
|
||||
/// <summary>
|
||||
/// FimpossibleC: Extensions methods which can be helpful when using Colors
|
||||
/// </summary>
|
||||
public static class FColorMethods
|
||||
{
|
||||
/// <summary>
|
||||
/// Changing color's alpha value
|
||||
/// </summary>
|
||||
public static Color ChangeColorAlpha(this Color color, float alpha)
|
||||
{
|
||||
return new Color(color.r, color.g, color.b, alpha);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove HDR values, clamp to max 1 value
|
||||
/// </summary>
|
||||
/// <param name="hdrColor"></param>
|
||||
/// <returns></returns>
|
||||
public static Color ToGammaSpace(Color hdrColor)
|
||||
{
|
||||
float getMax = hdrColor.r;
|
||||
if (hdrColor.g > getMax) getMax = hdrColor.g;
|
||||
if (hdrColor.b > getMax) getMax = hdrColor.b;
|
||||
if (hdrColor.a > getMax) getMax = hdrColor.a;
|
||||
|
||||
if (getMax <= 0f) return Color.clear;
|
||||
return hdrColor / getMax;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changing color brightness or darkness value (adding / subliming .r .g .b) -1 to 1 value
|
||||
/// </summary>
|
||||
public static Color ChangeColorsValue(this Color color, float brightenOrDarken = 0f)
|
||||
{
|
||||
return new Color(color.r + brightenOrDarken, color.g + brightenOrDarken, color.b + brightenOrDarken, color.a);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converting colors from hexadecimal to rgba color
|
||||
/// </summary>
|
||||
public static Color32 HexToColor(this string hex)
|
||||
{
|
||||
if (string.IsNullOrEmpty(hex))
|
||||
{
|
||||
Debug.Log("<color=red>Trying convert from hex to color empty string!</color>");
|
||||
return Color.white;
|
||||
}
|
||||
|
||||
uint rgba = 0x000000FF;
|
||||
|
||||
hex = hex.Replace("#", "");
|
||||
hex = hex.Replace("0x", "");
|
||||
|
||||
if (!uint.TryParse(hex, System.Globalization.NumberStyles.HexNumber, null, out rgba))
|
||||
{
|
||||
Debug.Log("Error during converting hex string.");
|
||||
return Color.white;
|
||||
}
|
||||
|
||||
return new Color32((byte)((rgba & -16777216) >> 0x18),
|
||||
(byte)((rgba & 0xff0000) >> 0x10),
|
||||
(byte)((rgba & 0xff00) >> 8),
|
||||
(byte)(rgba & 0xff));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coverting color32 to hex string
|
||||
/// </summary>
|
||||
public static string ColorToHex(this Color32 color, bool addHash = true)
|
||||
{
|
||||
string hex = "";
|
||||
|
||||
if (addHash) hex = "#";
|
||||
|
||||
hex += System.String.Format("{0}{1}{2}{3}"
|
||||
, color.r.ToString("X").Length == 1 ? System.String.Format("0{0}", color.r.ToString("X")) : color.r.ToString("X")
|
||||
, color.g.ToString("X").Length == 1 ? System.String.Format("0{0}", color.g.ToString("X")) : color.g.ToString("X")
|
||||
, color.b.ToString("X").Length == 1 ? System.String.Format("0{0}", color.b.ToString("X")) : color.b.ToString("X")
|
||||
, color.a.ToString("X").Length == 1 ? System.String.Format("0{0}", color.a.ToString("X")) : color.a.ToString("X"));
|
||||
|
||||
return hex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Coverting color to hex string
|
||||
/// </summary>
|
||||
public static string ColorToHex(this Color color, bool addHash = true)
|
||||
{
|
||||
Color32 col32 = new Color32((byte)(color.r * 255), (byte)(color.g * 255), (byte)(color.b * 255), (byte)(color.a * 255));
|
||||
return ColorToHex(col32, addHash);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Doing linear interpolation with deltaTime to change material color smoothly
|
||||
/// </summary>
|
||||
public static void LerpMaterialColor(this Material mat, string property, Color targetColor, float deltaMultiplier = 8f)
|
||||
{
|
||||
if (mat == null) return;
|
||||
|
||||
if (!mat.HasProperty(property))
|
||||
{
|
||||
Debug.LogError("Material " + mat.name + " don't have property '" + property + "' " + " in shader " + mat.shader.name);
|
||||
return;
|
||||
}
|
||||
|
||||
Color currentColor = mat.GetColor(property);
|
||||
mat.SetColor(property, Color.Lerp(currentColor, targetColor, Time.deltaTime * deltaMultiplier));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b2a20a2000093084e84d0fc02e3581bf
|
||||
timeCreated: 1528881308
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ae5221f810379dc449e478a99df9b4be
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,659 @@
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace FIMSpace
|
||||
{
|
||||
/// <summary>
|
||||
/// FM: Class which contains many helpful methods which operates on Vectors and Quaternions or some other floating point maths
|
||||
/// </summary>
|
||||
public static class FEngineering
|
||||
{
|
||||
|
||||
|
||||
#region Rotations and directions
|
||||
|
||||
|
||||
public static bool VIsZero( this Vector3 vec )
|
||||
{
|
||||
if( vec.sqrMagnitude == 0f ) return true; return false;
|
||||
//if (vec.x != 0f) return false; if (vec.y != 0f) return false; if (vec.z != 0f) return false; return true;
|
||||
}
|
||||
|
||||
public static bool VIsSame( this Vector3 vec1, Vector3 vec2 )
|
||||
{
|
||||
if( vec1.x != vec2.x ) return false; if( vec1.y != vec2.y ) return false; if( vec1.z != vec2.z ) return false; return true;
|
||||
}
|
||||
|
||||
|
||||
public static Vector3 TransformVector( this Quaternion parentRot, Vector3 parentLossyScale, Vector3 childLocalPos )
|
||||
{
|
||||
return parentRot * Vector3.Scale( childLocalPos, parentLossyScale );
|
||||
}
|
||||
|
||||
/// <summary> Same like transform vector but without scaling but also supporting negative scale </summary>
|
||||
public static Vector3 TransformInDirection( this Quaternion childRotation, Vector3 parentLossyScale, Vector3 childLocalPos )
|
||||
{
|
||||
return childRotation * Vector3.Scale( childLocalPos, new Vector3( parentLossyScale.x > 0 ? 1 : -1, parentLossyScale.y > 0 ? 1 : -1, parentLossyScale.y > 0 ? 1 : -1 ) );
|
||||
}
|
||||
|
||||
public static Vector3 InverseTransformVector( this Quaternion tRotation, Vector3 tLossyScale, Vector3 worldPos )
|
||||
{
|
||||
worldPos = Quaternion.Inverse( tRotation ) * worldPos;
|
||||
return new Vector3( worldPos.x / tLossyScale.x, worldPos.y / tLossyScale.y, worldPos.z / tLossyScale.z );
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Instance for 2D Axis limit calculations </summary>
|
||||
private static Plane axis2DProjection;
|
||||
|
||||
/// <summary>
|
||||
/// Calculating offset (currentPos -= Axis2DLimit...) to prevent object from moving in provided axis
|
||||
/// </summary>
|
||||
/// <param name="axis">1 is X 2 is Y 3 is Z</param>
|
||||
public static Vector3 VAxis2DLimit( this Transform parent, Vector3 parentPos, Vector3 childPos, int axis = 3 )
|
||||
{
|
||||
if( axis == 3 ) // Z is depth
|
||||
axis2DProjection.SetNormalAndPosition( parent.forward, parentPos );
|
||||
else
|
||||
if( axis == 2 ) // Y
|
||||
axis2DProjection.SetNormalAndPosition( parent.up, parentPos );
|
||||
else // X is depth
|
||||
axis2DProjection.SetNormalAndPosition( parent.right, parentPos );
|
||||
|
||||
return axis2DProjection.normal * axis2DProjection.GetDistanceToPoint( childPos );
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Just Rotations related
|
||||
|
||||
/// <summary>
|
||||
/// Locating world rotation in local space of parent transform
|
||||
/// </summary>
|
||||
public static Quaternion QToLocal( this Quaternion parentRotation, Quaternion worldRotation )
|
||||
{
|
||||
return Quaternion.Inverse( parentRotation ) * worldRotation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Locating local rotation of child local space to world
|
||||
/// </summary>
|
||||
public static Quaternion QToWorld( this Quaternion parentRotation, Quaternion localRotation )
|
||||
{
|
||||
return parentRotation * localRotation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Offsetting rotation of child transform with defined axis orientation
|
||||
/// </summary>
|
||||
public static Quaternion QRotateChild( this Quaternion offset, Quaternion parentRot, Quaternion childLocalRot )
|
||||
{
|
||||
return ( offset * parentRot ) * childLocalRot;
|
||||
}
|
||||
|
||||
public static Quaternion ClampRotation( this Vector3 current, Vector3 bounds )
|
||||
{
|
||||
WrapVector( current );
|
||||
|
||||
if( current.x < -bounds.x ) current.x = -bounds.x; else if( current.x > bounds.x ) current.x = bounds.x;
|
||||
if( current.y < -bounds.y ) current.y = -bounds.y; else if( current.y > bounds.y ) current.y = bounds.y;
|
||||
if( current.z < -bounds.z ) current.z = -bounds.z; else if( current.z > bounds.z ) current.z = bounds.z;
|
||||
|
||||
return Quaternion.Euler( current );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// For use with rigidbody.angularVelocity (Remember to set "rigidbody.maxAngularVelocity" higher)
|
||||
/// </summary>
|
||||
/// <param name="deltaRotation"> Create with [TargetRotation] * Quaternion.Inverse([CurrentRotation]) </param>
|
||||
/// <returns> Multiply this value by rotation speed parameter like QToAngularVelocity(deltaRot) * RotationSpeed </returns>
|
||||
public static Vector3 QToAngularVelocity( this Quaternion deltaRotation, bool fix = false )
|
||||
{
|
||||
return QToAngularVelocity( deltaRotation, fix ? ( 1f / Time.fixedDeltaTime ) : 1f );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For use with rigidbody.angularVelocity (Remember to set "rigidbody.maxAngularVelocity" higher)
|
||||
/// </summary>
|
||||
/// <param name="deltaRotation"> Create with [TargetRotation] * Quaternion.Inverse([CurrentRotation]) </param>
|
||||
/// <returns> Multiply this value by rotation speed parameter like QToAngularVelocity(deltaRot) * RotationSpeed </returns>
|
||||
public static Vector3 QToAngularVelocity( this Quaternion deltaRotation, float multiplyAngle )
|
||||
{
|
||||
float angle; Vector3 axis;
|
||||
deltaRotation.ToAngleAxis( out angle, out axis );
|
||||
if( angle != 0f ) angle = Mathf.DeltaAngle( 0f, angle );
|
||||
else return Vector3.zero;
|
||||
|
||||
axis = axis * ( angle * Mathf.Deg2Rad * multiplyAngle );
|
||||
|
||||
#if UNITY_2018_4_OR_NEWER
|
||||
if( axis.x is float.NaN ) return Vector3.zero;
|
||||
if( axis.y is float.NaN ) return Vector3.zero;
|
||||
if( axis.z is float.NaN ) return Vector3.zero;
|
||||
#endif
|
||||
|
||||
return axis;
|
||||
}
|
||||
|
||||
public static Vector3 QToAngularVelocity( this Quaternion currentRotation, Quaternion targetRotation, bool fix = false )
|
||||
{
|
||||
return QToAngularVelocity( targetRotation * Quaternion.Inverse( currentRotation ), fix );
|
||||
}
|
||||
|
||||
public static Vector3 QToAngularVelocity( this Quaternion currentRotation, Quaternion targetRotation, float multiply )
|
||||
{
|
||||
return QToAngularVelocity( targetRotation * Quaternion.Inverse( currentRotation ), multiply );
|
||||
}
|
||||
|
||||
public static bool QIsZero( this Quaternion rot )
|
||||
{
|
||||
if( rot.x != 0f ) return false; if( rot.y != 0f ) return false; if( rot.z != 0f ) return false; return true;
|
||||
}
|
||||
|
||||
public static bool QIsSame( this Quaternion rot1, Quaternion rot2 )
|
||||
{
|
||||
if( rot1.x != rot2.x ) return false; if( rot1.y != rot2.y ) return false; if( rot1.z != rot2.z ) return false; if( rot1.w != rot2.w ) return false; return true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Wrapping angle (clamping in +- 360) </summary>
|
||||
public static float WrapAngle( float angle )
|
||||
{
|
||||
angle %= 360;
|
||||
if( angle > 180 ) return angle - 360;
|
||||
return angle;
|
||||
}
|
||||
|
||||
public static Vector3 WrapVector( Vector3 angles )
|
||||
{ return new Vector3( WrapAngle( angles.x ), WrapAngle( angles.y ), WrapAngle( angles.z ) ); }
|
||||
|
||||
/// <summary> Unwrapping angle </summary>
|
||||
public static float UnwrapAngle( float angle )
|
||||
{
|
||||
if( angle >= 0 ) return angle;
|
||||
angle = -angle % 360;
|
||||
return 360 - angle;
|
||||
}
|
||||
|
||||
public static Vector3 UnwrapVector( Vector3 angles )
|
||||
{ return new Vector3( UnwrapAngle( angles.x ), UnwrapAngle( angles.y ), UnwrapAngle( angles.z ) ); }
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Animation Related
|
||||
|
||||
|
||||
public static Quaternion SmoothDampRotation( this Quaternion current, Quaternion target, ref Quaternion velocityRef, float duration, float delta )
|
||||
{
|
||||
return SmoothDampRotation( current, target, ref velocityRef, duration, Mathf.Infinity, delta );
|
||||
}
|
||||
|
||||
public static Quaternion SmoothDampRotation( this Quaternion current, Quaternion target, ref Quaternion velocityRef, float duration, float maxSpeed, float delta )
|
||||
{
|
||||
float dot = Quaternion.Dot( current, target );
|
||||
float sign = dot > 0f ? 1f : -1f;
|
||||
target.x *= sign;
|
||||
target.y *= sign;
|
||||
target.z *= sign;
|
||||
target.w *= sign;
|
||||
|
||||
Vector4 smoothVal = new Vector4(
|
||||
Mathf.SmoothDamp( current.x, target.x, ref velocityRef.x, duration, maxSpeed, delta ),
|
||||
Mathf.SmoothDamp( current.y, target.y, ref velocityRef.y, duration, maxSpeed, delta ),
|
||||
Mathf.SmoothDamp( current.z, target.z, ref velocityRef.z, duration, maxSpeed, delta ),
|
||||
Mathf.SmoothDamp( current.w, target.w, ref velocityRef.w, duration, maxSpeed, delta ) ).normalized;
|
||||
|
||||
Vector4 correction = Vector4.Project( new Vector4( velocityRef.x, velocityRef.y, velocityRef.z, velocityRef.w ), smoothVal );
|
||||
velocityRef.x -= correction.x;
|
||||
velocityRef.y -= correction.y;
|
||||
velocityRef.z -= correction.z;
|
||||
velocityRef.w -= correction.w;
|
||||
|
||||
return new Quaternion( smoothVal.x, smoothVal.y, smoothVal.z, smoothVal.w );
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Helper Maths
|
||||
|
||||
public static float PerlinNoise3D( float x, float y, float z )
|
||||
{
|
||||
y += 1;
|
||||
z += 2;
|
||||
float xy = Mathf.Sin( Mathf.PI * Mathf.PerlinNoise( x, y ) );
|
||||
float xz = Mathf.Sin( Mathf.PI * Mathf.PerlinNoise( x, z ) );
|
||||
float yz = Mathf.Sin( Mathf.PI * Mathf.PerlinNoise( y, z ) );
|
||||
float yx = Mathf.Sin( Mathf.PI * Mathf.PerlinNoise( y, x ) );
|
||||
float zx = Mathf.Sin( Mathf.PI * Mathf.PerlinNoise( z, x ) );
|
||||
float zy = Mathf.Sin( Mathf.PI * Mathf.PerlinNoise( z, y ) );
|
||||
|
||||
return xy * xz * yz * yx * zx * zy;
|
||||
}
|
||||
|
||||
public static float PerlinNoise3D( Vector3 pos )
|
||||
{
|
||||
return PerlinNoise3D( pos.x, pos.y, pos.z );
|
||||
}
|
||||
|
||||
public static bool SameDirection( this float a, float b )
|
||||
{
|
||||
return ( a > 0 && b > 0 ) || ( a < 0f && b < 0f );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Using Halton Sequence to choose propabilistic coords for example for raycasts
|
||||
/// !!!! baseV must be greater than one > 1
|
||||
/// </summary>
|
||||
public static float PointDisperse01( int index, int baseV = 2 )
|
||||
{
|
||||
float sum = 0f; float functionV = 1f / baseV; int i = index;
|
||||
while( i > 0 ) { sum += functionV * ( i % baseV ); i = Mathf.FloorToInt( i / baseV ); functionV /= baseV; }
|
||||
return sum;
|
||||
}
|
||||
|
||||
public static float PointDisperse( int index, int baseV = 2 )
|
||||
{
|
||||
float sum = 0f; float functionV = 1f / baseV; int i = index;
|
||||
while( i > 0 ) { sum += functionV * ( i % baseV ); i = Mathf.FloorToInt( i / baseV ); functionV /= baseV; }
|
||||
return ( sum - 0.5f );
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Matrixes
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Getting scalling axis lossy scale value if object changes it's size by transform scale
|
||||
/// </summary>
|
||||
public static float GetScaler( this Transform transform )
|
||||
{
|
||||
float scaler;
|
||||
if( transform.lossyScale.x > transform.lossyScale.y )
|
||||
{
|
||||
if( transform.lossyScale.y > transform.lossyScale.z )
|
||||
scaler = transform.lossyScale.y;
|
||||
else
|
||||
scaler = transform.lossyScale.z;
|
||||
}
|
||||
else
|
||||
scaler = transform.lossyScale.x;
|
||||
|
||||
return scaler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracting position from Matrix
|
||||
/// </summary>
|
||||
public static Vector3 PosFromMatrix( this Matrix4x4 m )
|
||||
{
|
||||
return m.GetColumn( 3 );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracting rotation from Matrix
|
||||
/// </summary>
|
||||
public static Quaternion RotFromMatrix( this Matrix4x4 m )
|
||||
{
|
||||
return Quaternion.LookRotation( m.GetColumn( 2 ), m.GetColumn( 1 ) );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracting scale from Matrix
|
||||
/// </summary>
|
||||
public static Vector3 ScaleFromMatrix( this Matrix4x4 m )
|
||||
{
|
||||
return new Vector3
|
||||
(
|
||||
m.GetColumn( 0 ).magnitude,
|
||||
m.GetColumn( 1 ).magnitude,
|
||||
m.GetColumn( 2 ).magnitude
|
||||
);
|
||||
}
|
||||
|
||||
public static Bounds TransformBounding( Bounds b, Transform by )
|
||||
{
|
||||
return TransformBounding( b, by.localToWorldMatrix );
|
||||
}
|
||||
|
||||
public static Bounds TransformBounding( Bounds b, Matrix4x4 mx )
|
||||
{
|
||||
Vector3 min = mx.MultiplyPoint( b.min );
|
||||
Vector3 max = mx.MultiplyPoint( b.max );
|
||||
|
||||
Vector3 minB = mx.MultiplyPoint( new Vector3( b.max.x, b.center.y, b.min.z ) );
|
||||
Vector3 maxB = mx.MultiplyPoint( new Vector3( b.min.x, b.center.y, b.max.z ) );
|
||||
|
||||
b = new Bounds( min, Vector3.zero );
|
||||
|
||||
b.Encapsulate( min );
|
||||
b.Encapsulate( max );
|
||||
b.Encapsulate( minB );
|
||||
b.Encapsulate( maxB );
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
#if UNITY_2018_4_OR_NEWER
|
||||
public static Bounds RotateBoundsByMatrix( this Bounds b, Quaternion rotation )
|
||||
{
|
||||
if( QIsZero( rotation ) ) return b;
|
||||
|
||||
Matrix4x4 rot = Matrix4x4.Rotate( rotation );
|
||||
|
||||
Bounds newB = new Bounds();
|
||||
Vector3 fr1 = rot.MultiplyPoint( new Vector3( b.max.x, b.min.y, b.max.z ) );
|
||||
Vector3 br1 = rot.MultiplyPoint( new Vector3( b.max.x, b.min.y, b.min.z ) );
|
||||
Vector3 bl1 = rot.MultiplyPoint( new Vector3( b.min.x, b.min.y, b.min.z ) );
|
||||
Vector3 fl1 = rot.MultiplyPoint( new Vector3( b.min.x, b.min.y, b.max.z ) );
|
||||
newB.Encapsulate( fr1 );
|
||||
newB.Encapsulate( br1 );
|
||||
newB.Encapsulate( bl1 );
|
||||
newB.Encapsulate( fl1 );
|
||||
|
||||
Vector3 fr = rot.MultiplyPoint( new Vector3( b.max.x, b.max.y, b.max.z ) );
|
||||
Vector3 br = rot.MultiplyPoint( new Vector3( b.max.x, b.max.y, b.min.z ) );
|
||||
Vector3 bl = rot.MultiplyPoint( new Vector3( b.min.x, b.max.y, b.min.z ) );
|
||||
Vector3 fl = rot.MultiplyPoint( new Vector3( b.min.x, b.max.y, b.max.z ) );
|
||||
newB.Encapsulate( fr );
|
||||
newB.Encapsulate( br );
|
||||
newB.Encapsulate( bl );
|
||||
newB.Encapsulate( fl );
|
||||
|
||||
return newB;
|
||||
}
|
||||
#else
|
||||
public static Bounds RotateBoundsByMatrix(this Bounds b, Quaternion rotation)
|
||||
{
|
||||
if (QIsZero(rotation)) return b;
|
||||
|
||||
Matrix4x4 rot = Matrix4x4.Rotate(rotation);
|
||||
|
||||
Bounds newB = new Bounds();
|
||||
Vector3 fr1 = rot.MultiplyPoint(new Vector3(b.max.x, b.min.y, b.max.z));
|
||||
Vector3 br1 = rot.MultiplyPoint(new Vector3(b.max.x, b.min.y, b.min.z));
|
||||
Vector3 bl1 = rot.MultiplyPoint(new Vector3(b.min.x, b.min.y, b.min.z));
|
||||
Vector3 fl1 = rot.MultiplyPoint(new Vector3(b.min.x, b.min.y, b.max.z));
|
||||
newB.Encapsulate(fr1);
|
||||
newB.Encapsulate(br1);
|
||||
newB.Encapsulate(bl1);
|
||||
newB.Encapsulate(fl1);
|
||||
|
||||
Vector3 fr = rot.MultiplyPoint(new Vector3(b.max.x, b.max.y, b.max.z));
|
||||
Vector3 br = rot.MultiplyPoint(new Vector3(b.max.x, b.max.y, b.min.z));
|
||||
Vector3 bl = rot.MultiplyPoint(new Vector3(b.min.x, b.max.y, b.min.z));
|
||||
Vector3 fl = rot.MultiplyPoint(new Vector3(b.min.x, b.max.y, b.max.z));
|
||||
newB.Encapsulate(fr);
|
||||
newB.Encapsulate(br);
|
||||
newB.Encapsulate(bl);
|
||||
newB.Encapsulate(fl);
|
||||
|
||||
return newB;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Roatate by 90, not precise
|
||||
/// </summary>
|
||||
public static Bounds RotateLocalBounds( this Bounds b, Quaternion rotation )
|
||||
{
|
||||
float angle = Quaternion.Angle( rotation, Quaternion.identity );
|
||||
|
||||
if( angle > 45 && angle < 135 ) b.size = new Vector3( b.size.z, b.size.y, b.size.x );
|
||||
if( angle < 315 && angle > 225 ) b.size = new Vector3( b.size.z, b.size.y, b.size.x );
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
public static int[] GetLayermaskValues( int mask, int optionsCount )
|
||||
{
|
||||
System.Collections.Generic.List<int> masks = new System.Collections.Generic.List<int>();
|
||||
|
||||
for( int i = 0; i < optionsCount; i++ )
|
||||
{
|
||||
int layer = 1 << i;
|
||||
if( ( mask & layer ) != 0 ) masks.Add( i );
|
||||
}
|
||||
|
||||
return masks.ToArray();
|
||||
}
|
||||
|
||||
|
||||
#region Physical Materials Stuff
|
||||
|
||||
|
||||
public static LayerMask GetLayerMaskUsingPhysicsProjectSettingsMatrix( int maskForLayer )
|
||||
{
|
||||
LayerMask layerMask = 0;
|
||||
|
||||
for( int i = 0; i < 32; i++ )
|
||||
{
|
||||
if( !Physics.GetIgnoreLayerCollision( maskForLayer, i ) ) layerMask = layerMask | 1 << i;
|
||||
}
|
||||
|
||||
return layerMask;
|
||||
}
|
||||
|
||||
public static PhysicsMaterial PMSliding
|
||||
{
|
||||
get
|
||||
{
|
||||
if( _slidingMat ) return _slidingMat;
|
||||
else
|
||||
{
|
||||
_slidingMat = new PhysicsMaterial( "Slide" );
|
||||
_slidingMat.frictionCombine = PhysicsMaterialCombine.Minimum;
|
||||
_slidingMat.dynamicFriction = 0f;
|
||||
_slidingMat.staticFriction = 0f;
|
||||
return _slidingMat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static PhysicsMaterial _slidingMat;
|
||||
public static PhysicsMaterial PMFrict
|
||||
{
|
||||
get
|
||||
{
|
||||
if( _frictMat ) return _frictMat;
|
||||
else
|
||||
{
|
||||
_frictMat = new PhysicsMaterial( "Friction" );
|
||||
_frictMat.frictionCombine = PhysicsMaterialCombine.Maximum;
|
||||
_frictMat.dynamicFriction = 10f;
|
||||
_frictMat.staticFriction = 10f;
|
||||
return _frictMat;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static PhysicsMaterial _frictMat;
|
||||
|
||||
|
||||
public static PhysicsMaterial2D PMSliding2D
|
||||
{
|
||||
get
|
||||
{
|
||||
if( _slidingMat2D ) return _slidingMat2D;
|
||||
else
|
||||
{
|
||||
_slidingMat2D = new PhysicsMaterial2D( "Slide2D" );
|
||||
_slidingMat2D.friction = 0f;
|
||||
return _slidingMat2D;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static PhysicsMaterial2D _slidingMat2D;
|
||||
|
||||
public static PhysicsMaterial2D PMFrict2D
|
||||
{
|
||||
get
|
||||
{
|
||||
if( _frictMat2D ) return _frictMat2D;
|
||||
else
|
||||
{
|
||||
_frictMat2D = new PhysicsMaterial2D( "Friction2D" );
|
||||
_frictMat2D.friction = 5f;
|
||||
return _frictMat2D;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static PhysicsMaterial2D _frictMat2D;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Extra Quick Trigonometrics and 2D
|
||||
|
||||
|
||||
public static float DistanceTo_2D( Vector3 aPos, Vector3 bPos )
|
||||
{
|
||||
return Vector2.Distance( new Vector2( aPos.x, aPos.z ), new Vector2( bPos.x, bPos.z ) );
|
||||
}
|
||||
|
||||
public static float DistanceTo_2DSqrt( Vector3 aPos, Vector3 bPos )
|
||||
{
|
||||
return Vector2.SqrMagnitude( new Vector2( aPos.x, aPos.z ) - new Vector2( bPos.x, bPos.z ) );
|
||||
}
|
||||
|
||||
public static Vector2 GetAngleDirection2D( float angle )
|
||||
{
|
||||
float degToRad = angle * Mathf.Deg2Rad;
|
||||
return new Vector2( Mathf.Sin( degToRad ), Mathf.Cos( degToRad ) );
|
||||
}
|
||||
|
||||
public static Vector3 GetAngleDirection( float angle )
|
||||
{
|
||||
float degToRad = angle * Mathf.Deg2Rad;
|
||||
return new Vector3( Mathf.Sin( degToRad ), 0f, Mathf.Cos( degToRad ) );
|
||||
}
|
||||
|
||||
public static Vector3 GetAngleDirectionXZ( float angle )
|
||||
{
|
||||
return GetAngleDirection( angle );
|
||||
}
|
||||
public static Vector3 GetAngleDirectionZX( float angle )
|
||||
{
|
||||
float degToRad = angle * Mathf.Deg2Rad;
|
||||
return new Vector3( Mathf.Cos( degToRad ), 0f, Mathf.Sin( degToRad ) );
|
||||
}
|
||||
public static Vector3 GetAngleDirectionXY( float angle, float radOffset = 0f, float secAxisRadOffset = 0f )
|
||||
{
|
||||
float degToRad = angle * Mathf.Deg2Rad;
|
||||
return new Vector3( Mathf.Sin( degToRad + radOffset ), Mathf.Cos( degToRad + secAxisRadOffset ), 0f );
|
||||
}
|
||||
public static Vector3 GetAngleDirectionYX( float angle, float firstAxisRadOffset = 0f, float secAxisRadOffset = 0f )
|
||||
{
|
||||
float degToRad = angle * Mathf.Deg2Rad;
|
||||
return new Vector3( Mathf.Cos( degToRad + secAxisRadOffset ), Mathf.Sin( degToRad + firstAxisRadOffset ), 0f );
|
||||
}
|
||||
public static Vector3 GetAngleDirectionYZ( float angle )
|
||||
{
|
||||
float degToRad = angle * Mathf.Deg2Rad;
|
||||
return new Vector3( 0f, Mathf.Sin( degToRad ), Mathf.Cos( degToRad ) );
|
||||
}
|
||||
public static Vector3 GetAngleDirectionZY( float angle )
|
||||
{
|
||||
float degToRad = angle * Mathf.Deg2Rad;
|
||||
return new Vector3( 0f, Mathf.Cos( degToRad ), Mathf.Sin( degToRad ) );
|
||||
}
|
||||
|
||||
public static Vector3 V2ToV3TopDown( Vector2 v )
|
||||
{
|
||||
return new Vector3( v.x, 0f, v.y );
|
||||
}
|
||||
|
||||
/// <summary> new V2(a.x, a.z) </summary>
|
||||
public static Vector2 V3ToV2( Vector3 a )
|
||||
{
|
||||
return new Vector2( a.x, a.z );
|
||||
}
|
||||
|
||||
public static Vector2 V3TopDownDiff( Vector3 target, Vector3 me )
|
||||
{
|
||||
return V3ToV2( target ) - V3ToV2( me );
|
||||
}
|
||||
|
||||
/// <summary> Reads x and z value </summary>
|
||||
public static float GetAngleDeg( Vector3 v )
|
||||
{
|
||||
return GetAngleDeg( v.x, v.z );
|
||||
}
|
||||
public static float GetAngleDeg( Vector2 v )
|
||||
{
|
||||
return GetAngleDeg( v.x, v.y );
|
||||
}
|
||||
public static float GetAngleDeg( float x, float z )
|
||||
{
|
||||
return GetAngleRad( x, z ) * Mathf.Rad2Deg;
|
||||
}
|
||||
public static float GetAngleRad( float x, float z )
|
||||
{
|
||||
return Mathf.Atan2( x, z );
|
||||
}
|
||||
|
||||
public static float Rnd( float val, int dec = 0 )
|
||||
{
|
||||
if( dec <= 0 ) return Mathf.Round( val );
|
||||
return (float)System.Math.Round( val, dec );
|
||||
}
|
||||
|
||||
/// <summary> Cheap distance calculation 2D </summary>
|
||||
internal static float ManhattanTopDown2D( Vector3 probePos, Vector3 worldPosition )
|
||||
{
|
||||
float d1 = probePos.x - worldPosition.x;
|
||||
if( d1 < 0 ) d1 = -d1;
|
||||
|
||||
float d2 = probePos.z - worldPosition.z;
|
||||
if( d2 < 0 ) d2 = -d2;
|
||||
|
||||
return d1 + d2;
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Cheap check if position is contained in square </summary>
|
||||
internal static bool IsInSqureBounds2D( Vector3 probePos, Vector3 boundsPos, float boundsRange )
|
||||
{
|
||||
if( boundsRange <= 0f ) return false;
|
||||
|
||||
if( probePos.x > boundsPos.x - boundsRange && probePos.x < boundsPos.x + boundsRange &&
|
||||
probePos.z > boundsPos.z - boundsRange && probePos.z < boundsPos.z + boundsRange )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static bool IsInSqureBounds2D( Vector3 boundsAPos, float boundsAHalfRange, Vector3 boundsBPos, float boundsBHRange )
|
||||
{
|
||||
return ( boundsAPos.x - boundsAHalfRange <= boundsBPos.x + boundsBHRange ) && ( boundsAPos.x + boundsAHalfRange >= boundsBPos.x - boundsBHRange ) &&
|
||||
( boundsAPos.z - boundsAHalfRange <= boundsBPos.z + boundsBHRange ) && ( boundsAPos.z + boundsAHalfRange >= boundsBPos.z - boundsBHRange );
|
||||
}
|
||||
|
||||
internal static Vector3 GetDirectionTowards( Vector3 me, Vector3 target )
|
||||
{
|
||||
return new Vector3( target.x - me.x, 0f, target.z - me.z );
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bf673a9cfd972764caec127fd830fa1d
|
||||
timeCreated: 1528881308
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,246 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FIMSpace
|
||||
{
|
||||
/// <summary>
|
||||
/// FM: Class which contains many helpful logic methods
|
||||
/// </summary>
|
||||
public static class FLogicMethods
|
||||
{
|
||||
|
||||
#region Lerping
|
||||
|
||||
public static float Lerp(this float from, float to, float value)
|
||||
{
|
||||
if (to != from) // Prevent from dividing by zero
|
||||
return Mathf.Clamp((value - from) / (to - from), -1f, 1f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inverse Lerp without clamping
|
||||
/// </summary>
|
||||
public static float InverseLerp(float from, float to, float value)
|
||||
{
|
||||
if (to != from) // Prevent from dividing by zero
|
||||
return Mathf.Clamp((value - from) / (to - from), -1f, 1f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
public static float InverseLerpUnclamped(float xx, float yy, float value)
|
||||
{
|
||||
if (yy - xx == 0f) return 0f; else return (value - xx) / (yy - xx);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lerp which finishing on b value, factor means value which will be added / substracted to which lerp will reaching
|
||||
/// </summary>
|
||||
public static float FLerp(float a, float b, float t, float factor = 0.01f)
|
||||
{
|
||||
float preB = b; if (preB > a) b += factor; else b -= factor;
|
||||
float val = Mathf.LerpUnclamped(a, b, t);
|
||||
if (preB > a) { if (val >= preB) return preB; } else if (val <= preB) return preB;
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
public static int IntLerp(int a, int b, float t)
|
||||
{
|
||||
int lerp = 0;
|
||||
IntLerp(ref lerp, a, b, t);
|
||||
return lerp;
|
||||
}
|
||||
|
||||
|
||||
public static void IntLerp(ref int source, int a, int b, float t)
|
||||
{
|
||||
source = Mathf.RoundToInt(a * (1f - t)) + Mathf.RoundToInt(b * t);
|
||||
}
|
||||
|
||||
|
||||
public static void IntLerp(ref int source, int b, float t)
|
||||
{
|
||||
IntLerp(ref source, source, b, t);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Behaves like Mathf.Abs but in performance tests this one is much quicker
|
||||
/// </summary>
|
||||
public static float FAbs(this float value)
|
||||
{
|
||||
if (value < 0) value = -value;
|
||||
return value;
|
||||
}
|
||||
|
||||
public static float HyperCurve(this float value)
|
||||
{
|
||||
return -(1f / (3.2f * value - 4)) - 0.25f;
|
||||
}
|
||||
|
||||
|
||||
#region Calculate Distance Related
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// For detecting difference in position (very cheap) but less precise -> Ignoring Y Axis value
|
||||
/// </summary>
|
||||
public static float TopDownDistanceManhattan(this Vector3 a, Vector3 b)
|
||||
{
|
||||
float diff = 0f;
|
||||
diff += FAbs(a.x - b.x);
|
||||
diff += FAbs(a.z - b.z);
|
||||
return diff;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculating 2D distance -> ignoring Y axis value
|
||||
/// </summary>
|
||||
public static float TopDownDistance(this Vector3 a, Vector3 b)
|
||||
{
|
||||
a.y = a.z;
|
||||
b.y = b.z;
|
||||
return Vector2.Distance(a, b);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For detecting difference in position (very cheap) but less precise
|
||||
/// </summary>
|
||||
public static float DistanceManhattan(this Vector3 a, Vector3 b)
|
||||
{
|
||||
float diff = 0f;
|
||||
diff += FAbs(a.x - b.x);
|
||||
diff += FAbs(a.y - b.y);
|
||||
diff += FAbs(a.z - b.z);
|
||||
return diff;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Wrapping angles
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Wrapping angle (clamping in +- 360)
|
||||
/// </summary>
|
||||
public static float WrapAngle(float angle)
|
||||
{
|
||||
angle %= 360;
|
||||
|
||||
if (angle > 180) return angle - 360;
|
||||
|
||||
return angle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapping all angles (clamping in +- 360)
|
||||
/// </summary>
|
||||
public static Vector3 WrapVector(Vector3 angles)
|
||||
{
|
||||
return new Vector3(WrapAngle(angles.x), WrapAngle(angles.y), WrapAngle(angles.z));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unwrapping angle
|
||||
/// </summary>
|
||||
public static float UnwrapAngle(float angle)
|
||||
{
|
||||
if (angle >= 0) return angle;
|
||||
|
||||
angle = -angle % 360;
|
||||
|
||||
return 360 - angle;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unwrapping all angles
|
||||
/// </summary>
|
||||
public static Vector3 UnwrapVector(Vector3 angles)
|
||||
{
|
||||
return new Vector3(UnwrapAngle(angles.x), UnwrapAngle(angles.y), UnwrapAngle(angles.z));
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Detects if variable is very near to target value
|
||||
/// </summary>
|
||||
public static bool IsAlmostEqual(float val, float to, int afterComma = 2, float addRange = 0f)
|
||||
{
|
||||
float commaVal = 1 / Mathf.Pow(10, afterComma) + addRange;
|
||||
|
||||
if ((val > to - commaVal && val < to + commaVal) || val == to)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#region Angles
|
||||
|
||||
/// <summary>
|
||||
/// Calculating rotation to target object ignoring Y axis
|
||||
/// </summary>
|
||||
public static Quaternion TopDownAngle(Vector3 from, Vector3 to)
|
||||
{
|
||||
from.y = 0f;
|
||||
to.y = 0f;
|
||||
|
||||
return Quaternion.LookRotation(to - from);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Math formula to calculate direction in 2D space
|
||||
/// </summary>
|
||||
public static Quaternion TopDownAnglePosition2D(Vector2 from, Vector2 to, float offset = 0f)
|
||||
{
|
||||
Vector2 dir = to - from;
|
||||
var angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg + offset;
|
||||
return Quaternion.AngleAxis(angle, Vector3.forward);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
public static bool ContainsIndex<T>(this List<T> list, int i, bool falseIfNull = true) where T : class
|
||||
{
|
||||
if (list == null) return false;
|
||||
if (i < 0) return false;
|
||||
if (i >= list.Count) return false;
|
||||
if (falseIfNull) if (list[i] == null) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool ContainsIndex<T>(this List<T> list, int i) where T : struct
|
||||
{
|
||||
if (list == null) return false;
|
||||
if (i < 0) return false;
|
||||
if (i >= list.Count) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool ContainsIndex<T>(this T[] list, int i, bool falseIfNull) where T : class
|
||||
{
|
||||
if (list == null) return false;
|
||||
if (i < 0) return false;
|
||||
if (i >= list.Length) return false;
|
||||
if (falseIfNull) if (list[i] == null) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5375d2c189639774f9469f0a20a94301
|
||||
timeCreated: 1528881308
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,181 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
namespace FIMSpace
|
||||
{
|
||||
/// <summary>
|
||||
/// FM: Class with methods which can be helpful when using unity Transforms
|
||||
/// </summary>
|
||||
public static class FTransformMethods
|
||||
{
|
||||
/// <summary>
|
||||
/// Method which is searching in depth of choosed transform for other transform with choosed name
|
||||
/// </summary>
|
||||
public static Transform FindChildByNameInDepth(string name, Transform transform, bool findInDeactivated = true, string[] additionalContains = null)
|
||||
{
|
||||
/* If choosed transform is already one we are searching for */
|
||||
if (transform.name == name)
|
||||
{
|
||||
return transform;
|
||||
}
|
||||
|
||||
/* Searching every transform component inside choosed transform */
|
||||
foreach (Transform child in transform.GetComponentsInChildren<Transform>(findInDeactivated))
|
||||
{
|
||||
if (child.name.ToLower().Contains(name.ToLower()))
|
||||
{
|
||||
bool allow = false;
|
||||
|
||||
if (additionalContains == null || additionalContains.Length == 0) allow = true;
|
||||
else
|
||||
for (int i = 0; i < additionalContains.Length; i++)
|
||||
if (child.name.ToLower().Contains(additionalContains[i].ToLower()))
|
||||
{
|
||||
allow = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (allow) return child;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Method which finds all components of given type in all children in choosed transform
|
||||
/// </summary>
|
||||
public static List<T> FindComponentsInAllChildren<T>(Transform transformToSearchIn, bool includeInactive = false, bool tryGetMultipleOutOfSingleObject = false) where T : Component
|
||||
{
|
||||
List<T> components = new List<T>();
|
||||
|
||||
foreach (T child in transformToSearchIn.GetComponents<T>())
|
||||
{
|
||||
if (child) components.Add(child);
|
||||
}
|
||||
|
||||
foreach (Transform child in transformToSearchIn.GetComponentsInChildren<Transform>(includeInactive))
|
||||
{
|
||||
if (tryGetMultipleOutOfSingleObject == false)
|
||||
{
|
||||
T component = child.GetComponent<T>();
|
||||
if (component) if (components.Contains(component) == false) components.Add(component);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (T component in child.GetComponents<T>())
|
||||
{
|
||||
if (component) if (components.Contains(component) == false) components.Add(component);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return components;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method which finds component of given type in all children in choosed transform
|
||||
/// </summary>
|
||||
public static T FindComponentInAllChildren<T>(Transform transformToSearchIn) where T : Component
|
||||
{
|
||||
foreach (Transform childInDepth in transformToSearchIn.GetComponentsInChildren<Transform>())
|
||||
{
|
||||
T component = childInDepth.GetComponent<T>();
|
||||
if (component) return component;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method which finds component of given type in all parents in choosed transform
|
||||
/// </summary>
|
||||
public static T FindComponentInAllParents<T>(Transform transformToSearchIn) where T : Component
|
||||
{
|
||||
Transform p = transformToSearchIn.parent;
|
||||
|
||||
for (int i = 0; i < 100 /* safe limit */; i++)
|
||||
{
|
||||
T component = p.GetComponent<T>();
|
||||
if (component) return component;
|
||||
|
||||
p = p.parent;
|
||||
if (p == null) return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changing activation for all children in give transform
|
||||
/// </summary>
|
||||
public static void ChangeActiveChildrenInside(Transform parentOfThem, bool active)
|
||||
{
|
||||
for (int i = 0; i < parentOfThem.childCount; i++)
|
||||
{
|
||||
parentOfThem.GetChild(i).gameObject.SetActive(active);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Making parents active from one transform until reach choosen transform or null
|
||||
/// </summary>
|
||||
public static void ChangeActiveThroughParentTo(Transform start, Transform end, bool active, bool changeParentsChildrenActivation = false)
|
||||
{
|
||||
start.gameObject.SetActive(active);
|
||||
Transform p = start.parent;
|
||||
|
||||
for (int i = 0; i < 100 /* safe limit */; i++)
|
||||
{
|
||||
if (p == end) return;
|
||||
if (p == null) return;
|
||||
|
||||
if (changeParentsChildrenActivation) ChangeActiveChildrenInside(p, active);
|
||||
|
||||
p = p.parent;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static Transform GetObjectByPath( Transform root, string path )
|
||||
{
|
||||
if( root == null ) return null;
|
||||
|
||||
var pathSteps = path.Split( '/' );
|
||||
|
||||
Transform current = root;
|
||||
for( int i = 0; i < pathSteps.Length; i++ )
|
||||
{
|
||||
Transform target = current.Find( pathSteps[i] );
|
||||
if( target == null ) return null;
|
||||
current = target;
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
|
||||
public static string CalculateTransformPath(Transform child, Transform root)
|
||||
{
|
||||
if( child.parent == null ) return "";
|
||||
|
||||
string path = "";
|
||||
bool first = true;
|
||||
|
||||
while(child != root)
|
||||
{
|
||||
if( child == null ) return "";
|
||||
|
||||
if( first == true ) path = child.name; else path = child.name + "/" + path;
|
||||
first = false;
|
||||
|
||||
child = child.parent;
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f437799613874af428ffadc360c401c3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,225 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace FIMSpace
|
||||
{
|
||||
/// <summary>
|
||||
/// FM: Class which contains many helpful methods which operates on Vectors
|
||||
/// </summary>
|
||||
public static class FVectorMethods
|
||||
{
|
||||
/// <summary>
|
||||
/// Creating vector with random values in each axis
|
||||
/// </summary>
|
||||
public static Vector3 RandomVector(float rangeA, float rangeB)
|
||||
{
|
||||
return new Vector3(UnityEngine.Random.Range(rangeA, rangeB), UnityEngine.Random.Range(rangeA, rangeB), UnityEngine.Random.Range(rangeA, rangeB));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Just summing all vector's axes values
|
||||
/// </summary>
|
||||
public static float VectorSum(Vector3 vector)
|
||||
{
|
||||
return vector.x + vector.y + vector.z;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creating vector with random values in each axis but leaving y axis at 0f
|
||||
/// </summary>
|
||||
public static Vector3 RandomVectorNoY(float rangeA, float rangeB)
|
||||
{
|
||||
return new Vector3(UnityEngine.Random.Range(rangeA, rangeB), 0f, UnityEngine.Random.Range(rangeA, rangeB));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creating vector with random values in each axis with min - max random ranges values
|
||||
/// </summary>
|
||||
public static Vector3 RandomVectorMinMax(float min, float max)
|
||||
{
|
||||
float mul1 = 1f;
|
||||
if (UnityEngine.Random.Range(0, 2) == 1) mul1 = -1f;
|
||||
|
||||
float mul2 = 1f;
|
||||
if (UnityEngine.Random.Range(0, 2) == 1) mul2 = -1f;
|
||||
|
||||
float mul3 = 1f;
|
||||
if (UnityEngine.Random.Range(0, 2) == 1) mul3 = -1f;
|
||||
|
||||
return new Vector3(UnityEngine.Random.Range(min, max) * mul1, UnityEngine.Random.Range(min, max) * mul2, UnityEngine.Random.Range(min, max) * mul3);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creating vector with random values in each axis with min - max random ranges values, but leaving y value to 0f
|
||||
/// </summary>
|
||||
public static Vector3 RandomVectorNoYMinMax(float min, float max)
|
||||
{
|
||||
float mul1 = 1f;
|
||||
if (UnityEngine.Random.Range(0, 2) == 1) mul1 = -1f;
|
||||
|
||||
float mul2 = 1f;
|
||||
if (UnityEngine.Random.Range(0, 2) == 1) mul2 = -1f;
|
||||
|
||||
return new Vector3(UnityEngine.Random.Range(min, max) * mul1, 0f, UnityEngine.Random.Range(min, max) * mul2);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returning position on screen for UI element in reference to position in world 3D space, the 'z' will be negative if text is behind camera
|
||||
/// </summary>
|
||||
public static Vector3 GetUIPositionFromWorldPosition(Vector3 position, Camera camera, RectTransform canvas)
|
||||
{
|
||||
Vector3 uiPosition = camera.WorldToViewportPoint(position);
|
||||
|
||||
uiPosition.x *= canvas.sizeDelta.x;
|
||||
uiPosition.y *= canvas.sizeDelta.y;
|
||||
|
||||
uiPosition.x -= canvas.sizeDelta.x * canvas.pivot.x;
|
||||
uiPosition.y -= canvas.sizeDelta.y * canvas.pivot.y;
|
||||
|
||||
return uiPosition;
|
||||
}
|
||||
|
||||
|
||||
public static Vector2 XOZ(this Vector3 toBeFlattened)
|
||||
{
|
||||
return new Vector2(toBeFlattened.x, toBeFlattened.z);
|
||||
}
|
||||
public static Vector3 XOZ(this Vector3 toBeFlattened, float yValue = 0f)
|
||||
{
|
||||
return new Vector3(toBeFlattened.x, yValue, toBeFlattened.z);
|
||||
}
|
||||
|
||||
public static float DistanceTopDown(Vector3 from, Vector3 to)
|
||||
{
|
||||
return Vector2.Distance(XOZ(from), XOZ(to));
|
||||
}
|
||||
|
||||
|
||||
public static float DistanceTopDownManhattan(Vector3 from, Vector3 to)
|
||||
{
|
||||
return Mathf.Abs(from.x - to.x) + Mathf.Abs(from.z - to.z);
|
||||
}
|
||||
|
||||
|
||||
public static float BoundsSizeOnAxis(this Bounds bounds, Vector3 normalized)
|
||||
{
|
||||
return Vector3.Scale(bounds.size, normalized).magnitude;
|
||||
}
|
||||
|
||||
public static Vector3 ChooseDominantAxis(Vector3 axis)
|
||||
{
|
||||
Vector3 abs = new Vector3(Mathf.Abs(axis.x), Mathf.Abs(axis.y), Mathf.Abs(axis.z));
|
||||
|
||||
if (abs.x > abs.y)
|
||||
{
|
||||
if (abs.z > abs.x)
|
||||
return new Vector3(0f, 0f, axis.z > 0f ? 1f : -1f);
|
||||
else
|
||||
return new Vector3(axis.x > 0f ? 1f : -1f, 0f, 0f);
|
||||
}
|
||||
else
|
||||
if (abs.z > abs.y) return new Vector3(0f, 0f, axis.z > 0f ? 1f : -1f);
|
||||
else
|
||||
return new Vector3(0f, axis.y > 0f ? 1f : -1f, 0f);
|
||||
}
|
||||
|
||||
|
||||
public static Vector3 GetRounded(Vector3 dir)
|
||||
{
|
||||
return new Vector3(Mathf.Round(dir.x), Mathf.Round(dir.y), Mathf.Round(dir.z));
|
||||
}
|
||||
|
||||
|
||||
public static Vector3 GetCounterAxis(Vector3 axis)
|
||||
{
|
||||
return new Vector3(axis.z, axis.x, axis.y);
|
||||
}
|
||||
|
||||
|
||||
public static Color GetAxisColor(Vector3 axis, float alpha = 0.75f)
|
||||
{
|
||||
return new Color(axis.z, axis.x, axis.y, alpha);
|
||||
}
|
||||
|
||||
|
||||
public static Vector3 FlattenVector(Vector3 v, float to = 90f)
|
||||
{
|
||||
//Vector3 moved = v;
|
||||
|
||||
v.x = Mathf.Round(v.x / to) * to;
|
||||
v.y = Mathf.Round(v.y / to) * to;
|
||||
v.z = Mathf.Round(v.z / to) * to;
|
||||
|
||||
//float modulo = to % 2;
|
||||
//if (modulo > 0f && modulo < 1f)
|
||||
//{
|
||||
// moved = v - moved;
|
||||
// Vector3 offset = Vector3.zero;
|
||||
// if (moved.x != 0f) offset.x = Mathf.Sign(moved.x) * modulo;
|
||||
// if (moved.y != 0f) offset.y = Mathf.Sign(moved.y) * modulo;
|
||||
// if (moved.z != 0f) offset.z = Mathf.Sign(moved.z) * modulo;
|
||||
|
||||
// v += offset;
|
||||
// UnityEngine.Debug.Log("modulo " + modulo + " moved " + moved + " offset by " + offset);
|
||||
//}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
public static Vector3 FlattenVectorFlr(Vector3 v, float to = 90f)
|
||||
{
|
||||
v.x = Mathf.Floor(v.x / to) * to;
|
||||
v.y = Mathf.Floor(v.y / to) * to;
|
||||
v.z = Mathf.Floor(v.z / to) * to;
|
||||
return v;
|
||||
}
|
||||
|
||||
public static Vector3 FlattenVectorCeil(Vector3 v, float to = 90f)
|
||||
{
|
||||
v.x = Mathf.Ceil(v.x / to) * to;
|
||||
v.y = Mathf.Ceil(v.y / to) * to;
|
||||
v.z = Mathf.Ceil(v.z / to) * to;
|
||||
return v;
|
||||
}
|
||||
|
||||
public static Vector3 FlattenVector(Vector3 v, Vector3 to)
|
||||
{
|
||||
v.x = Mathf.Round(v.x / to.x) * to.x;
|
||||
v.y = Mathf.Round(v.y / to.y) * to.y;
|
||||
v.z = Mathf.Round(v.z / to.z) * to.z;
|
||||
return v;
|
||||
}
|
||||
|
||||
#if UNITY_2018_4_OR_NEWER
|
||||
public static Vector3Int V3toV3Int(Vector3 v)
|
||||
{
|
||||
return new Vector3Int(Mathf.RoundToInt(v.x), Mathf.RoundToInt(v.y), Mathf.RoundToInt(v.z));
|
||||
}
|
||||
#endif
|
||||
|
||||
public static Vector3 FlattenNormal(Quaternion orientation, Vector3? forward = null, float to = 90f)
|
||||
{
|
||||
Vector3 f = forward == null ? Vector3.forward : forward.Value;
|
||||
var vec = FlattenVector(orientation.eulerAngles, to);
|
||||
return Quaternion.Euler(vec) * f;
|
||||
}
|
||||
|
||||
|
||||
public static Vector3 EqualVector(float valueAll)
|
||||
{
|
||||
return new Vector3(valueAll, valueAll, valueAll);
|
||||
}
|
||||
|
||||
|
||||
public static Quaternion FlattenRotation(Quaternion orientation, float to = 90f)
|
||||
{
|
||||
var vec = FlattenVector(orientation.eulerAngles, to);
|
||||
return Quaternion.Euler(vec);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d647467a5a43e1345818040dfcf9a1f6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1 @@
|
||||
MathHelpers is directory with classes providing helpful static methods.
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: de54ab2efb9ac9144846f079e2a28038
|
||||
timeCreated: 1530127928
|
||||
licenseType: Store
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user