导入leg插件,完成腿部动画

This commit is contained in:
2025-09-24 15:12:17 +08:00
parent 5087ff1cfe
commit 090e86c0ee
1087 changed files with 417484 additions and 30288 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e5fc2f0ca890a5c4399a76a12ef0edc0
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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));
}
}
}

View File

@@ -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:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ae5221f810379dc449e478a99df9b4be
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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
}
}

View File

@@ -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:

View File

@@ -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;
}
}
}

View File

@@ -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:

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f437799613874af428ffadc360c401c3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d647467a5a43e1345818040dfcf9a1f6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1 @@
MathHelpers is directory with classes providing helpful static methods.

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: de54ab2efb9ac9144846f079e2a28038
timeCreated: 1530127928
licenseType: Store
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: