Space soccer polish and editor preview button

This commit is contained in:
Braedon 2022-02-02 03:36:20 -05:00
parent a7c1359f97
commit 147e41ca35
81 changed files with 16712 additions and 204 deletions

View file

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

View file

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 1e3f966a8e1c81a429b6881944ddb88a
folderAsset: yes
timeCreated: 1620639369
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,71 @@
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace BezierSolution
{
public class MinMaxRangeAttribute : PropertyAttribute
{
public float min;
public float max;
public MinMaxRangeAttribute( float min, float max )
{
this.min = min;
this.max = max;
}
}
}
#if UNITY_EDITOR
namespace BezierSolution.Extras
{
[CustomPropertyDrawer( typeof( MinMaxRangeAttribute ) )]
public class MixMaxRangeAttributeDrawer : PropertyDrawer
{
private const float MIN_MAX_SLIDER_TEXT_FIELD_WIDTH = 45f;
// Min-max slider credit: https://github.com/Unity-Technologies/UnityCsReference/blob/61f92bd79ae862c4465d35270f9d1d57befd1761/Editor/Mono/Inspector/LightEditor.cs#L328-L363
public override void OnGUI( Rect position, SerializedProperty property, GUIContent label )
{
MinMaxRangeAttribute minMaxRange = attribute as MinMaxRangeAttribute;
SerializedProperty minProp = property.FindPropertyRelative( "x" );
SerializedProperty maxProp = property.FindPropertyRelative( "y" );
position = EditorGUI.PrefixLabel( position, label );
EditorGUI.BeginProperty( position, GUIContent.none, property );
Rect minRect = new Rect( position ) { width = MIN_MAX_SLIDER_TEXT_FIELD_WIDTH };
Rect maxRect = new Rect( position ) { xMin = position.xMax - MIN_MAX_SLIDER_TEXT_FIELD_WIDTH };
Rect sliderRect = new Rect( position ) { xMin = minRect.xMax + 5f, xMax = maxRect.xMin - 5f };
EditorGUI.BeginChangeCheck();
EditorGUI.PropertyField( minRect, minProp, GUIContent.none );
Vector2 value = property.vector2Value;
EditorGUI.BeginChangeCheck();
EditorGUI.MinMaxSlider( sliderRect, ref value.x, ref value.y, minMaxRange.min, minMaxRange.max );
if( EditorGUI.EndChangeCheck() )
property.vector2Value = value;
EditorGUI.PropertyField( maxRect, maxProp, GUIContent.none );
if( EditorGUI.EndChangeCheck() )
{
float x = minProp.floatValue;
float y = maxProp.floatValue;
if( x < minMaxRange.min || x > minMaxRange.max )
minProp.floatValue = Mathf.Clamp( x, minMaxRange.min, minMaxRange.max );
if( y < minMaxRange.min || y > minMaxRange.max )
maxProp.floatValue = Mathf.Clamp( y, minMaxRange.min, minMaxRange.max );
}
EditorGUI.EndProperty();
}
}
}
#endif

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 277efd8192415fd4fb70032186bd5ed0
timeCreated: 1620638811
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,459 @@
using UnityEngine;
namespace BezierSolution
{
[AddComponentMenu( "Bezier Solution/Bezier Point" )]
[HelpURL( "https://github.com/yasirkula/UnityBezierSolution" )]
public partial class BezierPoint : MonoBehaviour
{
public Vector3 localPosition
{
get { return transform.localPosition; }
set
{
if( transform.localPosition == value )
return;
transform.localPosition = value;
spline.dirtyFlags |= InternalDirtyFlags.EndPointTransformChange | InternalDirtyFlags.ControlPointPositionChange;
}
}
#pragma warning disable 0649
[SerializeField, HideInInspector]
private Vector3 m_position;
public Vector3 position
{
get { return m_position; }
set
{
if( transform.position == value )
return;
transform.position = value;
spline.dirtyFlags |= InternalDirtyFlags.EndPointTransformChange | InternalDirtyFlags.ControlPointPositionChange;
}
}
public Quaternion localRotation
{
get { return transform.localRotation; }
set
{
if( transform.localRotation == value )
return;
transform.localRotation = value;
spline.dirtyFlags |= InternalDirtyFlags.EndPointTransformChange | InternalDirtyFlags.ControlPointPositionChange;
}
}
public Quaternion rotation
{
get { return transform.rotation; }
set
{
if( transform.rotation == value )
return;
transform.rotation = value;
spline.dirtyFlags |= InternalDirtyFlags.EndPointTransformChange | InternalDirtyFlags.ControlPointPositionChange;
}
}
public Vector3 localEulerAngles
{
get { return transform.localEulerAngles; }
set
{
if( transform.localEulerAngles == value )
return;
transform.localEulerAngles = value;
spline.dirtyFlags |= InternalDirtyFlags.EndPointTransformChange | InternalDirtyFlags.ControlPointPositionChange;
}
}
public Vector3 eulerAngles
{
get { return transform.eulerAngles; }
set
{
if( transform.eulerAngles == value )
return;
transform.eulerAngles = value;
spline.dirtyFlags |= InternalDirtyFlags.EndPointTransformChange | InternalDirtyFlags.ControlPointPositionChange;
}
}
public Vector3 localScale
{
get { return transform.localScale; }
set
{
if( transform.localScale == value )
return;
transform.localScale = value;
spline.dirtyFlags |= InternalDirtyFlags.EndPointTransformChange | InternalDirtyFlags.ControlPointPositionChange;
}
}
[SerializeField, HideInInspector]
private Vector3 m_precedingControlPointLocalPosition = Vector3.left;
public Vector3 precedingControlPointLocalPosition
{
get { return m_precedingControlPointLocalPosition; }
set
{
if( m_precedingControlPointLocalPosition == value )
return;
m_precedingControlPointLocalPosition = value;
m_precedingControlPointPosition = transform.TransformPoint( value );
if( m_handleMode == HandleMode.Aligned )
{
m_followingControlPointLocalPosition = -m_precedingControlPointLocalPosition.normalized * m_followingControlPointLocalPosition.magnitude;
m_followingControlPointPosition = transform.TransformPoint( m_followingControlPointLocalPosition );
}
else if( m_handleMode == HandleMode.Mirrored )
{
m_followingControlPointLocalPosition = -m_precedingControlPointLocalPosition;
m_followingControlPointPosition = transform.TransformPoint( m_followingControlPointLocalPosition );
}
spline.dirtyFlags |= InternalDirtyFlags.ControlPointPositionChange;
}
}
[SerializeField, HideInInspector]
private Vector3 m_precedingControlPointPosition;
public Vector3 precedingControlPointPosition
{
get { return m_precedingControlPointPosition; }
set
{
if( m_precedingControlPointPosition == value )
return;
m_precedingControlPointPosition = value;
m_precedingControlPointLocalPosition = transform.InverseTransformPoint( value );
if( transform.hasChanged )
{
m_position = transform.position;
m_followingControlPointPosition = transform.TransformPoint( m_followingControlPointLocalPosition );
spline.dirtyFlags |= InternalDirtyFlags.EndPointTransformChange;
transform.hasChanged = false;
}
if( m_handleMode == HandleMode.Aligned )
{
m_followingControlPointPosition = m_position - ( m_precedingControlPointPosition - m_position ).normalized *
( m_followingControlPointPosition - m_position ).magnitude;
m_followingControlPointLocalPosition = transform.InverseTransformPoint( m_followingControlPointPosition );
}
else if( m_handleMode == HandleMode.Mirrored )
{
m_followingControlPointPosition = 2f * m_position - m_precedingControlPointPosition;
m_followingControlPointLocalPosition = transform.InverseTransformPoint( m_followingControlPointPosition );
}
spline.dirtyFlags |= InternalDirtyFlags.ControlPointPositionChange;
}
}
[SerializeField, HideInInspector]
private Vector3 m_followingControlPointLocalPosition = Vector3.right;
public Vector3 followingControlPointLocalPosition
{
get { return m_followingControlPointLocalPosition; }
set
{
if( m_followingControlPointLocalPosition == value )
return;
m_followingControlPointLocalPosition = value;
m_followingControlPointPosition = transform.TransformPoint( value );
if( m_handleMode == HandleMode.Aligned )
{
m_precedingControlPointLocalPosition = -m_followingControlPointLocalPosition.normalized * m_precedingControlPointLocalPosition.magnitude;
m_precedingControlPointPosition = transform.TransformPoint( m_precedingControlPointLocalPosition );
}
else if( m_handleMode == HandleMode.Mirrored )
{
m_precedingControlPointLocalPosition = -m_followingControlPointLocalPosition;
m_precedingControlPointPosition = transform.TransformPoint( m_precedingControlPointLocalPosition );
}
spline.dirtyFlags |= InternalDirtyFlags.ControlPointPositionChange;
}
}
[SerializeField, HideInInspector]
private Vector3 m_followingControlPointPosition;
public Vector3 followingControlPointPosition
{
get { return m_followingControlPointPosition; }
set
{
if( m_followingControlPointPosition == value )
return;
m_followingControlPointPosition = value;
m_followingControlPointLocalPosition = transform.InverseTransformPoint( value );
if( transform.hasChanged )
{
m_position = transform.position;
m_precedingControlPointPosition = transform.TransformPoint( m_precedingControlPointLocalPosition );
spline.dirtyFlags |= InternalDirtyFlags.EndPointTransformChange;
transform.hasChanged = false;
}
if( m_handleMode == HandleMode.Aligned )
{
m_precedingControlPointPosition = m_position - ( m_followingControlPointPosition - m_position ).normalized *
( m_precedingControlPointPosition - m_position ).magnitude;
m_precedingControlPointLocalPosition = transform.InverseTransformPoint( m_precedingControlPointPosition );
}
else if( m_handleMode == HandleMode.Mirrored )
{
m_precedingControlPointPosition = 2f * m_position - m_followingControlPointPosition;
m_precedingControlPointLocalPosition = transform.InverseTransformPoint( m_precedingControlPointPosition );
}
spline.dirtyFlags |= InternalDirtyFlags.ControlPointPositionChange;
}
}
[SerializeField, HideInInspector]
private HandleMode m_handleMode = HandleMode.Mirrored;
public HandleMode handleMode
{
get { return m_handleMode; }
set
{
if( m_handleMode == value )
return;
m_handleMode = value;
if( value == HandleMode.Aligned || value == HandleMode.Mirrored )
{
// Temporarily change the value of m_precedingControlPointLocalPosition so that it will be different from precedingControlPointLocalPosition
// and precedingControlPointLocalPosition's setter will run
Vector3 _precedingControlPointLocalPosition = m_precedingControlPointLocalPosition;
m_precedingControlPointLocalPosition -= Vector3.one;
precedingControlPointLocalPosition = _precedingControlPointLocalPosition;
}
spline.dirtyFlags |= InternalDirtyFlags.ControlPointPositionChange;
}
}
[SerializeField, HideInInspector]
[UnityEngine.Serialization.FormerlySerializedAs( "normal" )]
private Vector3 m_normal = Vector3.up;
public Vector3 normal
{
get { return m_normal; }
set
{
if( m_normal == value )
return;
m_normal = value;
spline.dirtyFlags |= InternalDirtyFlags.NormalChange;
}
}
[SerializeField, HideInInspector]
[UnityEngine.Serialization.FormerlySerializedAs( "autoCalculatedNormalAngleOffset" )]
private float m_autoCalculatedNormalAngleOffset = 0f;
public float autoCalculatedNormalAngleOffset
{
get { return m_autoCalculatedNormalAngleOffset; }
set
{
if( m_autoCalculatedNormalAngleOffset == value )
return;
m_autoCalculatedNormalAngleOffset = value;
spline.dirtyFlags |= InternalDirtyFlags.NormalOffsetChange;
}
}
[SerializeField, HideInInspector]
private Vector3[] m_intermediateNormals;
public Vector3[] intermediateNormals
{
get { return m_intermediateNormals; }
set
{
// In this special case, don't early exit if the assigned array is the same because one of its elements might have changed.
// We can safely early exit if the assigned value was null or empty, though
if( ( m_intermediateNormals == null || m_intermediateNormals.Length == 0 ) && ( value == null || value.Length == 0 ) )
return;
m_intermediateNormals = value;
spline.dirtyFlags |= InternalDirtyFlags.NormalChange;
}
}
[SerializeField, HideInInspector]
[UnityEngine.Serialization.FormerlySerializedAs( "extraData" )]
private ExtraData m_extraData;
public ExtraData extraData
{
get { return m_extraData; }
set
{
if( m_extraData == value )
return;
m_extraData = value;
spline.dirtyFlags |= InternalDirtyFlags.ExtraDataChange;
}
}
#pragma warning restore 0649
public BezierSpline spline { get; internal set; }
public int index { get; internal set; }
public BezierPoint previousPoint
{
get
{
if( spline )
{
if( index > 0 )
return spline.endPoints[index - 1];
else if( spline.loop )
return spline.endPoints[spline.endPoints.Count - 1];
}
return null;
}
}
public BezierPoint nextPoint
{
get
{
if( spline )
{
if( index < spline.endPoints.Count - 1 )
return spline.endPoints[index + 1];
else if( spline.loop )
return spline.endPoints[0];
}
return null;
}
}
private void Awake()
{
transform.hasChanged = true;
}
private void OnDestroy()
{
if( spline )
spline.dirtyFlags |= InternalDirtyFlags.All;
}
public void CopyTo( BezierPoint other )
{
other.transform.localPosition = transform.localPosition;
other.transform.localRotation = transform.localRotation;
other.transform.localScale = transform.localScale;
other.m_handleMode = m_handleMode;
other.m_precedingControlPointLocalPosition = m_precedingControlPointLocalPosition;
other.m_followingControlPointLocalPosition = m_followingControlPointLocalPosition;
other.m_normal = m_normal;
other.m_autoCalculatedNormalAngleOffset = m_autoCalculatedNormalAngleOffset;
other.m_extraData = m_extraData;
}
public void Refresh()
{
m_position = transform.position;
m_precedingControlPointPosition = transform.TransformPoint( m_precedingControlPointLocalPosition );
m_followingControlPointPosition = transform.TransformPoint( m_followingControlPointLocalPosition );
transform.hasChanged = false;
}
internal void RefreshIfChanged()
{
if( transform.hasChanged )
{
Refresh();
spline.dirtyFlags |= InternalDirtyFlags.EndPointTransformChange | InternalDirtyFlags.ControlPointPositionChange;
}
}
internal void SetNormalAndResetIntermediateNormals( Vector3 normal, string undo )
{
if( spline && spline.autoCalculateNormals )
return;
#if UNITY_EDITOR
if( !string.IsNullOrEmpty( undo ) )
UnityEditor.Undo.RecordObject( this, undo );
#endif
this.normal = normal;
intermediateNormals = null;
BezierPoint previousPoint = this.previousPoint;
if( previousPoint && previousPoint.m_intermediateNormals != null && previousPoint.m_intermediateNormals.Length > 0 )
{
#if UNITY_EDITOR
if( !string.IsNullOrEmpty( undo ) )
UnityEditor.Undo.RecordObject( previousPoint, undo );
#endif
previousPoint.intermediateNormals = null;
}
}
public void Reset()
{
localPosition = Vector3.zero;
localRotation = Quaternion.identity;
localScale = Vector3.one;
precedingControlPointLocalPosition = Vector3.left;
followingControlPointLocalPosition = Vector3.right;
m_normal = Vector3.up;
m_autoCalculatedNormalAngleOffset = 0f;
m_extraData = new ExtraData();
transform.hasChanged = true;
}
#if UNITY_EDITOR
[ContextMenu( "Invert Spline" )]
private void InvertSplineContextMenu()
{
if( spline )
spline.InvertSpline( "Invert spline" );
}
#endif
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b9cf9c5931a3b3c4ba456c8213d7ebfc
timeCreated: 1472737829
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,3 @@
{
"name": "BezierSolution.Runtime"
}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 624c061ee4dfdaf4787b9c0bb51b4c1f
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a3dbf94c21a22d74d895b2051a04ba1e
timeCreated: 1620216034
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: -400
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 4b55326d0aea81b42b7f407fffdad047
folderAsset: yes
timeCreated: 1620724489
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 494545cd2e9cbec47adb2c1adf6066ab
timeCreated: 1472738252
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View file

@ -0,0 +1,84 @@
fileFormatVersion: 2
guid: 44b1882f3e87f214ba0c12a8e3b15d36
timeCreated: 1620040793
licenseType: Store
ModelImporter:
serializedVersion: 19
fileIDToRecycleName:
100000: tentacle_6_geo
100002: //RootNode
400000: tentacle_6_geo
400002: //RootNode
2300000: tentacle_6_geo
3300000: tentacle_6_geo
4300000: tentacle_6_geo
materials:
importMaterials: 0
materialName: 0
materialSearch: 1
animations:
legacyGenerateAnimations: 4
bakeSimulation: 0
resampleCurves: 1
optimizeGameObjects: 0
motionNodeName:
rigImportErrors:
rigImportWarnings:
animationImportErrors:
animationImportWarnings:
animationRetargetingWarnings:
animationDoRetargetingWarnings: 0
animationCompression: 1
animationRotationError: 0.5
animationPositionError: 0.5
animationScaleError: 0.5
animationWrapMode: 0
extraExposedTransformPaths: []
clipAnimations: []
isReadable: 1
meshes:
lODScreenPercentages: []
globalScale: 1
meshCompression: 0
addColliders: 0
importBlendShapes: 1
swapUVChannels: 0
generateSecondaryUV: 0
useFileUnits: 1
optimizeMeshForGPU: 1
keepQuads: 0
weldVertices: 1
secondaryUVAngleDistortion: 8
secondaryUVAreaDistortion: 15.000001
secondaryUVHardAngle: 88
secondaryUVPackMargin: 4
useFileScale: 1
tangentSpace:
normalSmoothAngle: 60
normalImportMode: 0
tangentImportMode: 3
importAnimation: 1
copyAvatar: 0
humanDescription:
serializedVersion: 2
human: []
skeleton: []
armTwist: 0.5
foreArmTwist: 0.5
upperLegTwist: 0.5
legTwist: 0.5
armStretch: 0.05
legStretch: 0.05
feetSpacing: 0
rootMotionBoneName:
rootMotionBoneRotation: {x: 0, y: 0, z: 0, w: 1}
hasTranslationDoF: 0
hasExtraRoot: 0
skeletonHasParents: 1
lastHumanDescriptionAvatarSource: {instanceID: 0}
animationType: 0
humanoidOversampling: 1
additionalBone: 0
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,79 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_Name: OctopusArm
m_Shader: {fileID: 10752, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords: _NORMALMAP
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 2800000, guid: 89e1b1c005d29cf4598ea861deb35a80, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 2800000, guid: cd20479f79180f440ad81177db5e0b12, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SamplePoint: 0
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _UVSec: 0
- _ZWrite: 1
m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _SampleRange: {r: 0, g: 1, b: 0, a: 0}
- _VertexRange: {r: 0, g: 1, b: 0, a: 0}

View file

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 6b88831b1ed3c38439c9be5ac64f87c1
timeCreated: 1620040793
licenseType: Store
NativeFormatImporter:
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 KiB

View file

@ -0,0 +1,68 @@
fileFormatVersion: 2
guid: cd20479f79180f440ad81177db5e0b12
timeCreated: 1620724293
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
filterMode: -1
aniso: -1
mipBias: -1
wrapMode: -1
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 519da3ae01006d64ea40c00e92df6614
folderAsset: yes
timeCreated: 1472735538
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 9d0566a88081c1b46b6236e5b2575a7c
timeCreated: 1472737433
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,28 @@
using UnityEditor;
using UnityEngine;
namespace BezierSolution.Extras
{
[CustomPropertyDrawer( typeof( BezierPoint.ExtraData ) )]
public class BezierPointExtraDataDrawer : PropertyDrawer
{
public override void OnGUI( Rect position, SerializedProperty property, GUIContent label )
{
EditorGUI.BeginProperty( position, label, property );
position = EditorGUI.PrefixLabel( position, GUIUtility.GetControlID( FocusType.Passive ), label );
float quarterWidth = position.width * 0.25f;
Rect c1Rect = new Rect( position.x, position.y, quarterWidth, position.height );
Rect c2Rect = new Rect( position.x + quarterWidth, position.y, quarterWidth, position.height );
Rect c3Rect = new Rect( position.x + 2f * quarterWidth, position.y, quarterWidth, position.height );
Rect c4Rect = new Rect( position.x + 3f * quarterWidth, position.y, quarterWidth, position.height );
EditorGUI.PropertyField( c1Rect, property.FindPropertyRelative( "c1" ), GUIContent.none );
EditorGUI.PropertyField( c2Rect, property.FindPropertyRelative( "c2" ), GUIContent.none );
EditorGUI.PropertyField( c3Rect, property.FindPropertyRelative( "c3" ), GUIContent.none );
EditorGUI.PropertyField( c4Rect, property.FindPropertyRelative( "c4" ), GUIContent.none );
EditorGUI.EndProperty();
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: d6fe536a44fc10242a73e0114a06befa
timeCreated: 1520266844
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,757 @@
using UnityEditor;
using UnityEngine;
namespace BezierSolution.Extras
{
public static class BezierSettings
{
#region Colors
private static Color? m_splineColor = null;
public static Color NormalSplineColor
{
get
{
if( m_splineColor == null )
m_splineColor = GetColor( "BezierSolution_SplineColor", new Color( 0.8f, 0.6f, 0.8f, 1f ) );
return m_splineColor.Value;
}
set
{
m_splineColor = value;
SetColor( "BezierSolution_SplineColor", value );
}
}
private static Color? m_selectedSplineColor = null;
public static Color SelectedSplineColor
{
get
{
if( m_selectedSplineColor == null )
m_selectedSplineColor = GetColor( "BezierSolution_SelectedSplineColor", new Color( 0.8f, 0.6f, 0.8f, 1f ) );
return m_selectedSplineColor.Value;
}
set
{
m_selectedSplineColor = value;
SetColor( "BezierSolution_SelectedSplineColor", value );
}
}
private static Color? m_endPointColor = null;
public static Color NormalEndPointColor
{
get
{
if( m_endPointColor == null )
m_endPointColor = GetColor( "BezierSolution_EndPointColor", Color.white );
return m_endPointColor.Value;
}
set
{
m_endPointColor = value;
SetColor( "BezierSolution_EndPointColor", value );
}
}
private static Color? m_selectedEndPointColor = null;
public static Color SelectedEndPointColor
{
get
{
if( m_selectedEndPointColor == null )
m_selectedEndPointColor = GetColor( "BezierSolution_SelectedEndPointColor", Color.yellow );
return m_selectedEndPointColor.Value;
}
set
{
m_selectedEndPointColor = value;
SetColor( "BezierSolution_SelectedEndPointColor", value );
}
}
private static Color? m_controlPointColor = null;
public static Color NormalControlPointColor
{
get
{
if( m_controlPointColor == null )
m_controlPointColor = GetColor( "BezierSolution_ControlPointColor", Color.white );
return m_controlPointColor.Value;
}
set
{
m_controlPointColor = value;
SetColor( "BezierSolution_ControlPointColor", value );
}
}
private static Color? m_selectedControlPointColor = null;
public static Color SelectedControlPointColor
{
get
{
if( m_selectedControlPointColor == null )
m_selectedControlPointColor = GetColor( "BezierSolution_SelectedControlPointColor", Color.green );
return m_selectedControlPointColor.Value;
}
set
{
m_selectedControlPointColor = value;
SetColor( "BezierSolution_SelectedControlPointColor", value );
}
}
private static Color? m_quickEditModeNewEndPointColor = null;
public static Color QuickEditModeNewEndPointColor
{
get
{
if( m_quickEditModeNewEndPointColor == null )
m_quickEditModeNewEndPointColor = GetColor( "BezierSolution_QuickEditNewPointColor", Color.cyan );
return m_quickEditModeNewEndPointColor.Value;
}
set
{
m_quickEditModeNewEndPointColor = value;
SetColor( "BezierSolution_QuickEditNewPointColor", value );
}
}
private static Color? m_quickEditModeDeleteEndPointColor = null;
public static Color QuickEditModeDeleteEndPointColor
{
get
{
if( m_quickEditModeDeleteEndPointColor == null )
m_quickEditModeDeleteEndPointColor = GetColor( "BezierSolution_QuickEditDeletePointColor", Color.red );
return m_quickEditModeDeleteEndPointColor.Value;
}
set
{
m_quickEditModeDeleteEndPointColor = value;
SetColor( "BezierSolution_QuickEditDeletePointColor", value );
}
}
private static Color? m_normalsPreviewColor = null;
public static Color NormalsPreviewColor
{
get
{
if( m_normalsPreviewColor == null )
m_normalsPreviewColor = GetColor( "BezierSolution_NormalsPreviewColor", Color.blue );
return m_normalsPreviewColor.Value;
}
set
{
m_normalsPreviewColor = value;
SetColor( "BezierSolution_NormalsPreviewColor", value );
}
}
private static Color? m_evenlySpacedPointsColor = null;
public static Color EvenlySpacedPointsColor
{
get
{
if( m_evenlySpacedPointsColor == null )
m_evenlySpacedPointsColor = GetColor( "BezierSolution_EvenlySpacedPointsColor", Color.white );
return m_evenlySpacedPointsColor.Value;
}
set
{
m_evenlySpacedPointsColor = value;
SetColor( "BezierSolution_EvenlySpacedPointsColor", value );
}
}
#endregion
#region Size Adjustments
private static float? m_splineThickness = null;
public static float SplineThickness
{
get
{
if( m_splineThickness == null )
m_splineThickness = EditorPrefs.GetFloat( "BezierSolution_SplineThickness", 8f );
return m_splineThickness.Value;
}
set
{
m_splineThickness = value;
EditorPrefs.SetFloat( "BezierSolution_SplineThickness", value );
}
}
private static float? m_endPointSize = null;
public static float EndPointSize
{
get
{
if( m_endPointSize == null )
m_endPointSize = EditorPrefs.GetFloat( "BezierSolution_EndPointSize", 0.075f );
return m_endPointSize.Value;
}
set
{
m_endPointSize = value;
EditorPrefs.SetFloat( "BezierSolution_EndPointSize", value );
}
}
private static float? m_selectedEndPointSize = null;
public static float SelectedEndPointSize
{
get
{
if( m_selectedEndPointSize == null )
m_selectedEndPointSize = EditorPrefs.GetFloat( "BezierSolution_SelectedEndPointSize", 0.075f * 1.5f );
return m_selectedEndPointSize.Value;
}
set
{
m_selectedEndPointSize = value;
EditorPrefs.SetFloat( "BezierSolution_SelectedEndPointSize", value );
}
}
private static float? m_controlPointSize = null;
public static float ControlPointSize
{
get
{
if( m_controlPointSize == null )
m_controlPointSize = EditorPrefs.GetFloat( "BezierSolution_ControlPointSize", 0.05f );
return m_controlPointSize.Value;
}
set
{
m_controlPointSize = value;
EditorPrefs.SetFloat( "BezierSolution_ControlPointSize", value );
}
}
private static float? m_quickEditModeNewEndPointSize = null;
public static float QuickEditModeNewEndPointSize
{
get
{
if( m_quickEditModeNewEndPointSize == null )
m_quickEditModeNewEndPointSize = EditorPrefs.GetFloat( "BezierSolution_QuickEditNewEndPointSize", 0.075f );
return m_quickEditModeNewEndPointSize.Value;
}
set
{
m_quickEditModeNewEndPointSize = value;
EditorPrefs.SetFloat( "BezierSolution_QuickEditNewEndPointSize", value );
}
}
private static float? m_normalsPreviewLength = null;
public static float NormalsPreviewLength
{
get
{
if( m_normalsPreviewLength == null )
m_normalsPreviewLength = EditorPrefs.GetFloat( "BezierSolution_NormalsPreviewLength", 0.35f );
return m_normalsPreviewLength.Value;
}
set
{
value = Mathf.Max( value, 0f );
m_normalsPreviewLength = value;
EditorPrefs.SetFloat( "BezierSolution_NormalsPreviewLength", value );
}
}
private static float? m_evenlySpacedPointsSize = null;
public static float EvenlySpacedPointsSize
{
get
{
if( m_evenlySpacedPointsSize == null )
m_evenlySpacedPointsSize = EditorPrefs.GetFloat( "BezierSolution_EvenlySpacedPointsSize", 0.1f );
return m_evenlySpacedPointsSize.Value;
}
set
{
m_evenlySpacedPointsSize = value;
EditorPrefs.SetFloat( "BezierSolution_EvenlySpacedPointsSize", value );
}
}
private static float? m_extraDataAsFrustumSize = null;
public static float ExtraDataAsFrustumSize
{
get
{
if( m_extraDataAsFrustumSize == null )
m_extraDataAsFrustumSize = EditorPrefs.GetFloat( "BezierSolution_ExtraDataFrustumSize", 2.2f );
return m_extraDataAsFrustumSize.Value;
}
set
{
m_extraDataAsFrustumSize = value;
EditorPrefs.SetFloat( "BezierSolution_ExtraDataFrustumSize", value );
}
}
#endregion
#region Other Settings
private static float? m_splineSmoothness = null;
public static float SplineSmoothness
{
get
{
if( m_splineSmoothness == null )
m_splineSmoothness = EditorPrefs.GetFloat( "BezierSolution_SplineSmoothness", 10f );
return m_splineSmoothness.Value;
}
set
{
value = Mathf.Max( value, 1f );
m_splineSmoothness = value;
EditorPrefs.SetFloat( "BezierSolution_SplineSmoothness", value );
}
}
private static int? m_displayedIntermediateNormalsCount = null;
public static int DisplayedIntermediateNormalsCount
{
get
{
if( m_displayedIntermediateNormalsCount == null )
m_displayedIntermediateNormalsCount = EditorPrefs.GetInt( "BezierSolution_IntermediateNormals", 8 );
return m_displayedIntermediateNormalsCount.Value;
}
set
{
value = Mathf.Clamp( value, 0, 999 );
m_displayedIntermediateNormalsCount = value;
EditorPrefs.SetInt( "BezierSolution_IntermediateNormals", value );
}
}
private static bool? m_moveMultiplePointsInOppositeDirections = null;
public static bool MoveMultiplePointsInOppositeDirections
{
get
{
if( m_moveMultiplePointsInOppositeDirections == null )
m_moveMultiplePointsInOppositeDirections = EditorPrefs.GetBool( "BezierSolution_OppositeTransformation", false );
return m_moveMultiplePointsInOppositeDirections.Value;
}
set
{
m_moveMultiplePointsInOppositeDirections = value;
EditorPrefs.SetBool( "BezierSolution_OppositeTransformation", value );
}
}
private static bool? m_quickEditSplineModifyNormals = null;
public static bool QuickEditSplineModifyNormals
{
get
{
if( m_quickEditSplineModifyNormals == null )
m_quickEditSplineModifyNormals = EditorPrefs.GetBool( "BezierSolution_QuickEditModifyNormals", true );
return m_quickEditSplineModifyNormals.Value;
}
set
{
m_quickEditSplineModifyNormals = value;
EditorPrefs.SetBool( "BezierSolution_QuickEditModifyNormals", value );
}
}
private static bool? m_quickEditSplinePreserveShape = null;
public static bool QuickEditSplinePreserveShape
{
get
{
if( m_quickEditSplinePreserveShape == null )
m_quickEditSplinePreserveShape = EditorPrefs.GetBool( "BezierSolution_QuickEditPreserveShape", false );
return m_quickEditSplinePreserveShape.Value;
}
set
{
m_quickEditSplinePreserveShape = value;
EditorPrefs.SetBool( "BezierSolution_QuickEditPreserveShape", value );
}
}
#endregion
#region Visibility Settings
private static bool? m_showControlPoints = null;
public static bool ShowControlPoints
{
get
{
if( m_showControlPoints == null )
m_showControlPoints = EditorPrefs.GetBool( "BezierSolution_ShowControlPoints", true );
return m_showControlPoints.Value;
}
set
{
m_showControlPoints = value;
EditorPrefs.SetBool( "BezierSolution_ShowControlPoints", value );
}
}
private static bool? m_showControlPointDirections = null;
public static bool ShowControlPointDirections
{
get
{
if( m_showControlPointDirections == null )
m_showControlPointDirections = EditorPrefs.GetBool( "BezierSolution_ShowControlPointDirs", true );
return m_showControlPointDirections.Value;
}
set
{
m_showControlPointDirections = value;
EditorPrefs.SetBool( "BezierSolution_ShowControlPointDirs", value );
}
}
private static bool? m_showEndPointLabels = null;
public static bool ShowEndPointLabels
{
get
{
if( m_showEndPointLabels == null )
m_showEndPointLabels = EditorPrefs.GetBool( "BezierSolution_ShowEndPointLabels", true );
return m_showEndPointLabels.Value;
}
set
{
m_showEndPointLabels = value;
EditorPrefs.SetBool( "BezierSolution_ShowEndPointLabels", value );
}
}
private static bool? m_showNormals = null;
public static bool ShowNormals
{
get
{
if( m_showNormals == null )
m_showNormals = EditorPrefs.GetBool( "BezierSolution_ShowNormals", true );
return m_showNormals.Value;
}
set
{
m_showNormals = value;
EditorPrefs.SetBool( "BezierSolution_ShowNormals", value );
}
}
private static bool? m_showEvenlySpacedPoints = null;
public static bool ShowEvenlySpacedPoints
{
get
{
if( m_showEvenlySpacedPoints == null )
m_showEvenlySpacedPoints = EditorPrefs.GetBool( "BezierSolution_ShowEvenlySpacedPoints", false );
return m_showEvenlySpacedPoints.Value;
}
set
{
m_showEvenlySpacedPoints = value;
EditorPrefs.SetBool( "BezierSolution_ShowEvenlySpacedPoints", value );
}
}
private static bool? m_visualizeExtraDataAsFrustum = null;
public static bool VisualizeExtraDataAsFrustum
{
get
{
if( m_visualizeExtraDataAsFrustum == null )
m_visualizeExtraDataAsFrustum = EditorPrefs.GetBool( "BezierSolution_VisualizeFrustum", false );
return m_visualizeExtraDataAsFrustum.Value;
}
set
{
m_visualizeExtraDataAsFrustum = value;
EditorPrefs.SetBool( "BezierSolution_VisualizeFrustum", value );
}
}
#endregion
#if UNITY_2018_3_OR_NEWER
[SettingsProvider]
public static SettingsProvider CreatePreferencesGUI()
{
return new SettingsProvider( "Project/yasirkula/Bezier Solution", SettingsScope.Project )
{
guiHandler = ( searchContext ) => PreferencesGUI(),
keywords = new System.Collections.Generic.HashSet<string>() { "Bezier", "Spline", "Point", "Normals", "Color", "Size" }
};
}
[MenuItem( "CONTEXT/BezierSpline/Open Settings" )]
[MenuItem( "CONTEXT/BezierPoint/Open Settings" )]
private static void OpenPreferencesWindow( MenuCommand command )
{
SettingsService.OpenProjectSettings( "yasirkula/Bezier Solution" );
}
#endif
#if !UNITY_2018_3_OR_NEWER
[PreferenceItem( "Bezier Solution" )]
#endif
public static void PreferencesGUI()
{
Color c;
float f;
int i;
bool b;
float labelWidth = EditorGUIUtility.labelWidth;
EditorGUIUtility.labelWidth += 50f;
EditorGUI.BeginChangeCheck();
EditorGUI.BeginChangeCheck();
c = ColorField( "Selected Spline Color", SelectedSplineColor, new Color( 0.8f, 0.6f, 0.8f, 1f ) );
if( EditorGUI.EndChangeCheck() )
SelectedSplineColor = c;
EditorGUI.BeginChangeCheck();
c = ColorField( "Unselected Spline Color", NormalSplineColor, new Color( 0.8f, 0.6f, 0.8f, 1f ) );
if( EditorGUI.EndChangeCheck() )
NormalSplineColor = c;
EditorGUI.BeginChangeCheck();
f = FloatField( "Selected Spline Thickness", SplineThickness, 8f );
if( EditorGUI.EndChangeCheck() )
SplineThickness = f;
EditorGUI.BeginChangeCheck();
f = FloatField( "Unselected Spline Smoothness", SplineSmoothness, 10f );
if( EditorGUI.EndChangeCheck() )
SplineSmoothness = f;
EditorGUILayout.Space();
EditorGUI.BeginChangeCheck();
c = ColorField( "Selected End Points Color", SelectedEndPointColor, Color.yellow );
if( EditorGUI.EndChangeCheck() )
SelectedEndPointColor = c;
EditorGUI.BeginChangeCheck();
c = ColorField( "Unselected End Point Color", NormalEndPointColor, Color.white );
if( EditorGUI.EndChangeCheck() )
NormalEndPointColor = c;
EditorGUI.BeginChangeCheck();
f = FloatField( "Selected End Points Size", SelectedEndPointSize, 0.075f * 1.5f );
if( EditorGUI.EndChangeCheck() )
SelectedEndPointSize = f;
EditorGUI.BeginChangeCheck();
f = FloatField( "Unselected End Points Size", EndPointSize, 0.075f );
if( EditorGUI.EndChangeCheck() )
EndPointSize = f;
EditorGUI.BeginChangeCheck();
b = EditorGUILayout.Toggle( "Show End Point Labels", ShowEndPointLabels );
if( EditorGUI.EndChangeCheck() )
ShowEndPointLabels = b;
EditorGUILayout.Space();
EditorGUI.BeginChangeCheck();
b = EditorGUILayout.Toggle( "Show Control Points", ShowControlPoints );
if( EditorGUI.EndChangeCheck() )
ShowControlPoints = b;
EditorGUI.indentLevel++;
EditorGUI.BeginChangeCheck();
b = EditorGUILayout.Toggle( "Show Control Point Directions", ShowControlPointDirections );
if( EditorGUI.EndChangeCheck() )
ShowControlPointDirections = b;
EditorGUI.BeginChangeCheck();
c = ColorField( "Selected Control Point Color", SelectedControlPointColor, Color.green );
if( EditorGUI.EndChangeCheck() )
SelectedControlPointColor = c;
EditorGUI.BeginChangeCheck();
c = ColorField( "Unselected Control Point Color", NormalControlPointColor, Color.white );
if( EditorGUI.EndChangeCheck() )
NormalControlPointColor = c;
EditorGUI.BeginChangeCheck();
f = FloatField( "Control Points Size", ControlPointSize, 0.05f );
if( EditorGUI.EndChangeCheck() )
ControlPointSize = f;
EditorGUI.indentLevel--;
EditorGUILayout.Space();
EditorGUI.BeginChangeCheck();
b = EditorGUILayout.Toggle( "Show Normals", ShowNormals );
if( EditorGUI.EndChangeCheck() )
ShowNormals = b;
EditorGUI.indentLevel++;
EditorGUI.BeginChangeCheck();
i = IntField( "Displayed Intermediate Normals", DisplayedIntermediateNormalsCount, 8 );
if( EditorGUI.EndChangeCheck() )
DisplayedIntermediateNormalsCount = i;
EditorGUI.BeginChangeCheck();
c = ColorField( "Normals Preview Color", NormalsPreviewColor, Color.blue );
if( EditorGUI.EndChangeCheck() )
NormalsPreviewColor = c;
EditorGUI.BeginChangeCheck();
f = FloatField( "Normals Preview Length", NormalsPreviewLength, 0.35f );
if( EditorGUI.EndChangeCheck() )
NormalsPreviewLength = f;
EditorGUI.indentLevel--;
EditorGUILayout.Space();
EditorGUI.BeginChangeCheck();
b = EditorGUILayout.Toggle( "Visualize Evenly Spaced Points", ShowEvenlySpacedPoints );
if( EditorGUI.EndChangeCheck() )
ShowEvenlySpacedPoints = b;
EditorGUI.indentLevel++;
EditorGUI.BeginChangeCheck();
c = ColorField( "Evenly Spaced Points Color", EvenlySpacedPointsColor, Color.white );
if( EditorGUI.EndChangeCheck() )
EvenlySpacedPointsColor = c;
EditorGUI.BeginChangeCheck();
f = FloatField( "Evenly Spaced Points Size", EvenlySpacedPointsSize, 0.1f );
if( EditorGUI.EndChangeCheck() )
EvenlySpacedPointsSize = f;
EditorGUI.indentLevel--;
EditorGUILayout.Space();
EditorGUI.BeginChangeCheck();
c = ColorField( "Quick Edit New Point Color", QuickEditModeNewEndPointColor, Color.cyan );
if( EditorGUI.EndChangeCheck() )
QuickEditModeNewEndPointColor = c;
EditorGUI.BeginChangeCheck();
c = ColorField( "Quick Edit Delete Point Color", QuickEditModeDeleteEndPointColor, Color.red );
if( EditorGUI.EndChangeCheck() )
QuickEditModeDeleteEndPointColor = c;
EditorGUI.BeginChangeCheck();
f = FloatField( "Quick Edit New Point Size", QuickEditModeNewEndPointSize, 0.075f );
if( EditorGUI.EndChangeCheck() )
QuickEditModeNewEndPointSize = f;
EditorGUILayout.Space();
EditorGUI.BeginChangeCheck();
b = EditorGUILayout.Toggle( new GUIContent( "Visualize Extra Data As Frustum", "Visualize end points' Extra Data as camera frustum in Scene window" ), VisualizeExtraDataAsFrustum );
if( EditorGUI.EndChangeCheck() )
VisualizeExtraDataAsFrustum = b;
EditorGUI.indentLevel++;
EditorGUI.BeginChangeCheck();
f = FloatField( "Frustum Size", ExtraDataAsFrustumSize, 2.2f );
if( EditorGUI.EndChangeCheck() )
ExtraDataAsFrustumSize = f;
EditorGUI.indentLevel--;
EditorGUIUtility.labelWidth = labelWidth;
if( EditorGUI.EndChangeCheck() )
SceneView.RepaintAll();
}
private static Color ColorField( string label, Color value, Color defaultValue )
{
GUILayout.BeginHorizontal();
Color result = EditorGUILayout.ColorField( label, value );
if( GUILayout.Button( "Reset", BezierUtils.GL_WIDTH_60 ) )
result = defaultValue;
GUILayout.EndHorizontal();
return result;
}
private static float FloatField( string label, float value, float defaultValue )
{
GUILayout.BeginHorizontal();
float result = EditorGUILayout.FloatField( label, value );
if( GUILayout.Button( "Reset", BezierUtils.GL_WIDTH_60 ) )
result = defaultValue;
GUILayout.EndHorizontal();
return result;
}
private static int IntField( string label, int value, int defaultValue )
{
GUILayout.BeginHorizontal();
int result = EditorGUILayout.IntField( label, value );
if( GUILayout.Button( "Reset", BezierUtils.GL_WIDTH_60 ) )
result = defaultValue;
GUILayout.EndHorizontal();
return result;
}
private static Color GetColor( string pref, Color defaultColor )
{
if( !EditorPrefs.HasKey( pref ) )
return defaultColor;
string[] parts = EditorPrefs.GetString( pref ).Split( ';' );
return new Color32( byte.Parse( parts[0] ), byte.Parse( parts[1] ), byte.Parse( parts[2] ), byte.Parse( parts[3] ) );
}
private static void SetColor( string pref, Color32 value )
{
EditorPrefs.SetString( pref, string.Concat( value.r.ToString(), ";", value.g.ToString(), ";", value.b.ToString(), ";", value.a.ToString() ) );
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e751cb465841a4f43b9297b7be55dcd0
timeCreated: 1620207781
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,17 @@
{
"name": "BezierSolution.Editor",
"references": [
"BezierSolution.Runtime"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: b99279c3e8f544f4d83dd26b3a9b5715
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,103 @@
using UnityEngine;
using UnityEditor;
namespace BezierSolution.Extras
{
[CustomEditor( typeof( BezierSpline ) )]
[CanEditMultipleObjects]
public class BezierSplineEditor : Editor
{
internal BezierSpline[] allSplines;
public static BezierSplineEditor ActiveEditor { get; private set; }
private void OnEnable()
{
Object[] splines = targets;
allSplines = new BezierSpline[splines.Length];
for( int i = 0; i < splines.Length; i++ )
{
BezierSpline spline = (BezierSpline) splines[i];
if( spline )
spline.Refresh();
allSplines[i] = spline;
}
ActiveEditor = this;
if( BezierUtils.QuickEditSplineMode )
{
Tools.hidden = true;
EditorApplication.update -= SceneView.RepaintAll;
EditorApplication.update += SceneView.RepaintAll;
}
Undo.undoRedoPerformed -= OnUndoRedo;
Undo.undoRedoPerformed += OnUndoRedo;
}
private void OnDisable()
{
ActiveEditor = null;
Tools.hidden = false;
Undo.undoRedoPerformed -= OnUndoRedo;
EditorApplication.update -= SceneView.RepaintAll;
}
private void OnSceneGUI()
{
BezierSpline spline = (BezierSpline) target;
BezierUtils.DrawSplineDetailed( spline );
for( int i = 0; i < spline.Count; i++ )
BezierUtils.DrawBezierPoint( spline[i], i + 1, false );
if( BezierSettings.ShowEvenlySpacedPoints )
BezierUtils.DrawSplineEvenlySpacedPoints( spline );
if( BezierUtils.QuickEditSplineMode )
{
// Execute quick edit mode's scene GUI only once (otherwise things can get ugly when multiple splines are selected)
if( spline == allSplines[0] )
{
BezierUtils.QuickEditModeSceneGUI( allSplines );
HandleUtility.AddDefaultControl( 0 );
}
return;
}
}
public override void OnInspectorGUI()
{
BezierUtils.DrawSplineInspectorGUI( allSplines );
}
private void OnUndoRedo()
{
for( int i = 0; i < allSplines.Length; i++ )
{
if( allSplines[i] )
{
allSplines[i].dirtyFlags |= InternalDirtyFlags.All;
allSplines[i].Refresh();
}
}
Repaint();
}
private bool HasFrameBounds()
{
return !serializedObject.isEditingMultipleObjects;
}
private Bounds OnGetFrameBounds()
{
return new Bounds( ( (BezierSpline) target ).transform.position, new Vector3( 1f, 1f, 1f ) );
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 0b74ad81d1f30ec479543aea0a27f6ef
timeCreated: 1472737433
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f472603c7062a4747bc569c7740ca872
timeCreated: 1473158123
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,120 @@
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace BezierSolution.Extras
{
public abstract class BezierWalkerEditor : Editor
{
protected Object[] walkers;
private bool simulateInEditor;
private double lastUpdateTime;
protected bool hasInitialData;
protected List<Vector3> initialPositions = new List<Vector3>( 0 );
protected List<Quaternion> initialRotations = new List<Quaternion>( 0 );
protected List<float> initialNormalizedTs = new List<float>( 0 );
private void OnEnable()
{
walkers = targets;
if( simulateInEditor )
StartSimulateInEditor();
}
private void OnDisable()
{
StopSimulateInEditor();
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
BezierUtils.DrawSeparator();
EditorGUI.BeginChangeCheck();
simulateInEditor = GUILayout.Toggle( simulateInEditor, "Simulate In Editor", GUI.skin.button );
if( EditorGUI.EndChangeCheck() )
{
if( simulateInEditor )
StartSimulateInEditor();
else
StopSimulateInEditor();
}
}
private void StartSimulateInEditor()
{
SaveInitialData();
lastUpdateTime = EditorApplication.timeSinceStartup;
EditorApplication.update -= SimulateInEditor;
EditorApplication.update += SimulateInEditor;
}
private void StopSimulateInEditor()
{
EditorApplication.update -= SimulateInEditor;
if( hasInitialData )
{
hasInitialData = false;
RestoreInitialData();
}
simulateInEditor = false;
}
protected virtual void SaveInitialData()
{
initialPositions.Clear();
initialRotations.Clear();
initialNormalizedTs.Clear();
for( int i = 0; i < walkers.Length; i++ )
{
initialPositions.Add( ( (Component) walkers[i] ).transform.position );
initialRotations.Add( ( (Component) walkers[i] ).transform.rotation );
initialNormalizedTs.Add( ( (BezierWalker) walkers[i] ).NormalizedT );
}
hasInitialData = true;
}
protected virtual void RestoreInitialData()
{
for( int i = 0; i < walkers.Length; i++ )
{
if( walkers[i] )
{
( (Component) walkers[i] ).transform.position = initialPositions[i];
( (Component) walkers[i] ).transform.rotation = initialRotations[i];
( (BezierWalker) walkers[i] ).NormalizedT = initialNormalizedTs[i];
}
}
}
private void SimulateInEditor()
{
if( EditorApplication.isPlayingOrWillChangePlaymode && !EditorApplication.isPlaying )
{
// Stop the simulation if we are about to enter Play mode
StopSimulateInEditor();
}
else
{
double time = EditorApplication.timeSinceStartup;
Simulate( (float) ( time - lastUpdateTime ) );
lastUpdateTime = time;
}
}
protected virtual void Simulate( float deltaTime )
{
for( int i = 0; i < walkers.Length; i++ )
( (BezierWalker) walkers[i] ).Execute( deltaTime );
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 0c496a7cc8ad6654f891021f652a8e5f
timeCreated: 1520346477
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,56 @@
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace BezierSolution.Extras
{
[CustomEditor( typeof( BezierWalkerLocomotion ) )]
[CanEditMultipleObjects]
public class BezierWalkerLocomotionEditor : BezierWalkerEditor
{
private int tailSaveDataStartIndex;
protected override void SaveInitialData()
{
base.SaveInitialData();
tailSaveDataStartIndex = initialPositions.Count;
for( int i = 0; i < walkers.Length; i++ )
{
List<Transform> tail = ( (BezierWalkerLocomotion) walkers[i] ).Tail;
for( int j = 0; j < tail.Count; j++ )
{
initialPositions.Add( tail[j].position );
initialRotations.Add( tail[j].rotation );
}
}
}
protected override void RestoreInitialData()
{
base.RestoreInitialData();
int index = tailSaveDataStartIndex;
for( int i = 0; i < walkers.Length; i++ )
{
if( walkers[i] )
{
List<Transform> tail = ( (BezierWalkerLocomotion) walkers[i] ).Tail;
for( int j = 0; j < tail.Count; j++, index++ )
{
tail[j].position = initialPositions[index];
tail[j].rotation = initialRotations[index];
}
}
}
}
protected override void Simulate( float deltaTime )
{
for( int i = 0; i < walkers.Length; i++ )
( (BezierWalkerLocomotion) walkers[i] ).walker.Execute( deltaTime );
base.Simulate( deltaTime );
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: afc4ab3119c2b58498c79718b6945348
timeCreated: 1520346477
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,10 @@
using UnityEditor;
namespace BezierSolution.Extras
{
[CustomEditor( typeof( BezierWalkerWithSpeed ) )]
[CanEditMultipleObjects]
public class BezierWalkerWithSpeedEditor : BezierWalkerEditor
{
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: aba64e4e7209c9b44ae73ece7f2c7164
timeCreated: 1520346477
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,10 @@
using UnityEditor;
namespace BezierSolution.Extras
{
[CustomEditor( typeof( BezierWalkerWithTime ) )]
[CanEditMultipleObjects]
public class BezierWalkerWithTimeEditor : BezierWalkerEditor
{
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e24aeb71e708e4043b77585635edfe8d
timeCreated: 1520346477
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,46 @@
using UnityEditor;
using UnityEngine;
namespace BezierSolution.Extras
{
// This class is used for resetting the particle system attached to a ParticlesFollowBezier
// component when it is selected. Otherwise, particles move in a chaotic way for a while
[CustomEditor( typeof( ParticlesFollowBezier ) )]
[CanEditMultipleObjects]
public class ParticlesFollowBezierEditor : Editor
{
private int particlesReset;
private void OnEnable()
{
particlesReset = 3;
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if( Application.isPlaying )
return;
if( particlesReset > 0 && --particlesReset == 0 )
{
foreach( Object target in targets )
{
ResetParticles( ( (ParticlesFollowBezier) target ).GetComponentsInParent<ParticlesFollowBezier>() );
ResetParticles( ( (ParticlesFollowBezier) target ).GetComponentsInChildren<ParticlesFollowBezier>() );
}
}
}
private void ResetParticles( ParticlesFollowBezier[] targets )
{
foreach( ParticlesFollowBezier target in targets )
{
ParticleSystem particleSystem = target.GetComponent<ParticleSystem>();
if( target.spline != null && particleSystem != null && target.enabled )
particleSystem.Clear();
}
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 652ad8d00b278c04fbf4252c46b7a10f
timeCreated: 1520346477
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 34eb947ee3a327b45911b699fb81c1f5
folderAsset: yes
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,344 @@
using UnityEngine;
namespace BezierSolution
{
public enum SplineAutoConstructMode { None = 0, Linear = 1, Smooth1 = 2, Smooth2 = 3 };
[System.Flags]
internal enum InternalDirtyFlags
{
None = 0,
EndPointTransformChange = 1 << 1,
ControlPointPositionChange = 1 << 2,
NormalChange = 1 << 3,
NormalOffsetChange = 1 << 4,
ExtraDataChange = 1 << 5,
All = EndPointTransformChange | ControlPointPositionChange | NormalChange | NormalOffsetChange | ExtraDataChange
};
[System.Flags]
public enum DirtyFlags
{
None = 0,
SplineShapeChanged = 1 << 1,
NormalsChanged = 1 << 2,
ExtraDataChanged = 1 << 3,
All = SplineShapeChanged | NormalsChanged | ExtraDataChanged
};
[System.Flags]
public enum PointCacheFlags
{
None = 0,
Positions = 1 << 1,
Normals = 1 << 2,
Tangents = 1 << 3,
Bitangents = 1 << 4,
ExtraDatas = 1 << 5,
All = Positions | Normals | Tangents | Bitangents | ExtraDatas
};
public delegate void SplineChangeDelegate( BezierSpline spline, DirtyFlags dirtyFlags );
public delegate BezierPoint.ExtraData ExtraDataLerpFunction( BezierPoint.ExtraData data1, BezierPoint.ExtraData data2, float normalizedT );
public partial class BezierSpline
{
private static readonly ExtraDataLerpFunction defaultExtraDataLerpFunction = BezierPoint.ExtraData.LerpUnclamped;
public struct Segment
{
public readonly BezierPoint point1, point2;
public readonly float localT;
public Segment( BezierPoint point1, BezierPoint point2, float localT )
{
this.point1 = point1;
this.point2 = point2;
this.localT = localT;
}
public float GetNormalizedT() { return GetNormalizedT( localT ); }
public float GetNormalizedT( float localT )
{
BezierSpline spline = point1.spline;
return ( point1.index + localT ) / ( spline.m_loop ? spline.Count : ( spline.Count - 1 ) );
}
public Vector3 GetPoint() { return GetPoint( localT ); }
public Vector3 GetPoint( float localT )
{
float oneMinusLocalT = 1f - localT;
return oneMinusLocalT * oneMinusLocalT * oneMinusLocalT * point1.position +
3f * oneMinusLocalT * oneMinusLocalT * localT * point1.followingControlPointPosition +
3f * oneMinusLocalT * localT * localT * point2.precedingControlPointPosition +
localT * localT * localT * point2.position;
}
public Vector3 GetTangent() { return GetTangent( localT ); }
public Vector3 GetTangent( float localT )
{
float oneMinusLocalT = 1f - localT;
return 3f * oneMinusLocalT * oneMinusLocalT * ( point1.followingControlPointPosition - point1.position ) +
6f * oneMinusLocalT * localT * ( point2.precedingControlPointPosition - point1.followingControlPointPosition ) +
3f * localT * localT * ( point2.position - point2.precedingControlPointPosition );
}
public Vector3 GetNormal() { return GetNormal( localT ); }
public Vector3 GetNormal( float localT )
{
Vector3[] intermediateNormals = point1.intermediateNormals;
if( intermediateNormals != null && intermediateNormals.Length > 0 )
{
localT = Mathf.Clamp01( localT ) * ( intermediateNormals.Length - 1 );
int localStartIndex = (int) localT;
return ( localStartIndex < intermediateNormals.Length - 1 ) ? Vector3.LerpUnclamped( intermediateNormals[localStartIndex], intermediateNormals[localStartIndex + 1], localT - localStartIndex ) : intermediateNormals[localStartIndex];
}
Vector3 startNormal = point1.normal;
Vector3 endNormal = point2.normal;
Vector3 normal = Vector3.LerpUnclamped( startNormal, endNormal, localT );
if( normal.y == 0f && normal.x == 0f && normal.z == 0f )
{
// Don't return Vector3.zero as normal
normal = Vector3.LerpUnclamped( startNormal, endNormal, localT > 0.01f ? ( localT - 0.01f ) : ( localT + 0.01f ) );
if( normal.y == 0f && normal.x == 0f && normal.z == 0f )
normal = Vector3.up;
}
return normal;
}
public BezierPoint.ExtraData GetExtraData() { return defaultExtraDataLerpFunction( point1.extraData, point2.extraData, localT ); }
public BezierPoint.ExtraData GetExtraData( float localT ) { return defaultExtraDataLerpFunction( point1.extraData, point2.extraData, localT ); }
public BezierPoint.ExtraData GetExtraData( ExtraDataLerpFunction lerpFunction ) { return lerpFunction( point1.extraData, point2.extraData, localT ); }
public BezierPoint.ExtraData GetExtraData( float localT, ExtraDataLerpFunction lerpFunction ) { return lerpFunction( point1.extraData, point2.extraData, localT ); }
}
public class EvenlySpacedPointsHolder
{
public readonly BezierSpline spline;
public readonly float splineLength;
public readonly float[] uniformNormalizedTs;
public EvenlySpacedPointsHolder( BezierSpline spline, float splineLength, float[] uniformNormalizedTs )
{
this.spline = spline;
this.splineLength = splineLength;
this.uniformNormalizedTs = uniformNormalizedTs;
}
public float GetNormalizedTAtDistance( float distance )
{
return GetNormalizedTAtPercentage( distance / splineLength );
}
public float GetNormalizedTAtPercentage( float percentage )
{
if( !spline.loop )
{
if( percentage <= 0f )
return 0f;
else if( percentage >= 1f )
return 1f;
}
else
{
while( percentage < 0f )
percentage += 1f;
while( percentage >= 1f )
percentage -= 1f;
}
float indexRaw = ( uniformNormalizedTs.Length - 1 ) * percentage;
int index = (int) indexRaw;
return Mathf.LerpUnclamped( uniformNormalizedTs[index], uniformNormalizedTs[index + 1], indexRaw - index );
}
public float GetPercentageAtNormalizedT( float normalizedT )
{
if( !spline.loop )
{
if( normalizedT <= 0f )
return 0f;
else if( normalizedT >= 1f )
return 1f;
}
else
{
if( normalizedT < 0f )
normalizedT += 1f;
if( normalizedT >= 1f )
normalizedT -= 1f;
}
// Perform binary search
int lowerBound = 0;
int upperBound = uniformNormalizedTs.Length - 1;
while( lowerBound <= upperBound )
{
int index = lowerBound + ( ( upperBound - lowerBound ) >> 1 );
float arrElement = uniformNormalizedTs[index];
if( arrElement < normalizedT )
lowerBound = index + 1;
else if( arrElement > normalizedT )
upperBound = index - 1;
else
return index / (float) ( uniformNormalizedTs.Length - 1 );
}
float inverseLerp = ( normalizedT - uniformNormalizedTs[lowerBound] ) / ( uniformNormalizedTs[lowerBound - 1] - uniformNormalizedTs[lowerBound] );
return ( lowerBound - inverseLerp ) / ( uniformNormalizedTs.Length - 1 );
}
}
public class PointCache
{
public readonly Vector3[] positions, normals, tangents, bitangents;
public readonly BezierPoint.ExtraData[] extraDatas;
public readonly bool loop;
public PointCache( Vector3[] positions, Vector3[] normals, Vector3[] tangents, Vector3[] bitangents, BezierPoint.ExtraData[] extraDatas, bool loop )
{
this.positions = positions;
this.normals = normals;
this.tangents = tangents;
this.bitangents = bitangents;
this.extraDatas = extraDatas;
this.loop = loop;
}
public Vector3 GetPoint( float percentage ) { return LerpArray( positions, percentage ); }
public Vector3 GetNormal( float percentage ) { return LerpArray( normals, percentage ); }
public Vector3 GetTangent( float percentage ) { return LerpArray( tangents, percentage ); }
public Vector3 GetBitangent( float percentage ) { return LerpArray( bitangents, percentage ); }
public BezierPoint.ExtraData GetExtraData( float percentage ) { return GetExtraData( percentage, defaultExtraDataLerpFunction ); }
public BezierPoint.ExtraData GetExtraData( float percentage, ExtraDataLerpFunction lerpFunction )
{
if( !loop )
{
if( percentage <= 0f )
return extraDatas[0];
else if( percentage >= 1f )
return extraDatas[extraDatas.Length - 1];
}
else
{
if( percentage < 0f )
percentage += 1f;
if( percentage >= 1f )
percentage -= 1f;
}
float t = percentage * ( loop ? extraDatas.Length : ( extraDatas.Length - 1 ) );
int startIndex = (int) t;
int endIndex = startIndex + 1;
if( endIndex == extraDatas.Length )
endIndex = 0;
return lerpFunction( extraDatas[startIndex], extraDatas[endIndex], t - startIndex );
}
private Vector3 LerpArray( Vector3[] array, float percentage )
{
if( !loop )
{
if( percentage <= 0f )
return array[0];
else if( percentage >= 1f )
return array[array.Length - 1];
}
else
{
if( percentage < 0f )
percentage += 1f;
if( percentage >= 1f )
percentage -= 1f;
}
float t = percentage * ( loop ? array.Length : ( array.Length - 1 ) );
int startIndex = (int) t;
int endIndex = startIndex + 1;
if( endIndex == array.Length )
endIndex = 0;
return Vector3.LerpUnclamped( array[startIndex], array[endIndex], t - startIndex );
}
}
}
public partial class BezierPoint
{
public enum HandleMode { Free, Aligned, Mirrored };
[System.Serializable]
public struct ExtraData
{
public float c1, c2, c3, c4;
public ExtraData( float c1 = 0f, float c2 = 0f, float c3 = 0f, float c4 = 0f )
{
this.c1 = c1;
this.c2 = c2;
this.c3 = c3;
this.c4 = c4;
}
public static ExtraData Lerp( ExtraData a, ExtraData b, float t )
{
t = Mathf.Clamp01( t );
return new ExtraData(
a.c1 + ( b.c1 - a.c1 ) * t,
a.c2 + ( b.c2 - a.c2 ) * t,
a.c3 + ( b.c3 - a.c3 ) * t,
a.c4 + ( b.c4 - a.c4 ) * t );
}
public static ExtraData LerpUnclamped( ExtraData a, ExtraData b, float t )
{
return new ExtraData(
a.c1 + ( b.c1 - a.c1 ) * t,
a.c2 + ( b.c2 - a.c2 ) * t,
a.c3 + ( b.c3 - a.c3 ) * t,
a.c4 + ( b.c4 - a.c4 ) * t );
}
public static implicit operator ExtraData( Vector2 v ) { return new ExtraData( v.x, v.y ); }
public static implicit operator ExtraData( Vector3 v ) { return new ExtraData( v.x, v.y, v.z ); }
public static implicit operator ExtraData( Vector4 v ) { return new ExtraData( v.x, v.y, v.z, v.w ); }
public static implicit operator ExtraData( Quaternion q ) { return new ExtraData( q.x, q.y, q.z, q.w ); }
public static implicit operator ExtraData( Rect r ) { return new ExtraData( r.xMin, r.yMin, r.width, r.height ); }
#if UNITY_2017_2_OR_NEWER
public static implicit operator ExtraData( Vector2Int v ) { return new ExtraData( v.x, v.y ); }
public static implicit operator ExtraData( Vector3Int v ) { return new ExtraData( v.x, v.y, v.z ); }
public static implicit operator ExtraData( RectInt r ) { return new ExtraData( r.xMin, r.yMin, r.width, r.height ); }
#endif
public static implicit operator Vector2( ExtraData v ) { return new Vector2( v.c1, v.c2 ); }
public static implicit operator Vector3( ExtraData v ) { return new Vector3( v.c1, v.c2, v.c3 ); }
public static implicit operator Vector4( ExtraData v ) { return new Vector4( v.c1, v.c2, v.c3, v.c4 ); }
public static implicit operator Quaternion( ExtraData v ) { return new Quaternion( v.c1, v.c2, v.c3, v.c4 ); }
public static implicit operator Rect( ExtraData v ) { return new Rect( v.c1, v.c2, v.c3, v.c4 ); }
#if UNITY_2017_2_OR_NEWER
public static implicit operator Vector2Int( ExtraData v ) { return new Vector2Int( Mathf.RoundToInt( v.c1 ), Mathf.RoundToInt( v.c2 ) ); }
public static implicit operator Vector3Int( ExtraData v ) { return new Vector3Int( Mathf.RoundToInt( v.c1 ), Mathf.RoundToInt( v.c2 ), Mathf.RoundToInt( v.c3 ) ); }
public static implicit operator RectInt( ExtraData v ) { return new RectInt( Mathf.RoundToInt( v.c1 ), Mathf.RoundToInt( v.c2 ), Mathf.RoundToInt( v.c3 ), Mathf.RoundToInt( v.c4 ) ); }
#endif
public static bool operator ==( ExtraData d1, ExtraData d2 ) { return d1.c1 == d2.c1 && d1.c2 == d2.c2 && d1.c3 == d2.c3 && d1.c4 == d2.c4; }
public static bool operator !=( ExtraData d1, ExtraData d2 ) { return d1.c1 != d2.c1 || d1.c2 != d2.c2 || d1.c3 != d2.c3 || d1.c4 != d2.c4; }
public override bool Equals( object obj ) { return obj is ExtraData && this == (ExtraData) obj; }
public override int GetHashCode() { return unchecked((int) ( ( ( ( 17 * 23 + c1 ) * 23 + c2 ) * 23 + c3 ) * 23 + c4 )); }
public override string ToString() { return ( (Vector4) this ).ToString(); }
}
}
}

View file

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 4cf39235e4779904896b58210ade2e37
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,36 @@
= Bezier Solution =
Online documentation & example code available at: https://github.com/yasirkula/UnityBezierSolution
E-mail: yasirkula@gmail.com
### ABOUT
This plugin helps you create bezier splines either visually in editor or by code during gameplay. Includes some utility functions like finding the closest point on the spline or travelling the spline with constant speed. It is built upon Catlike Coding's spline tutorial: https://catlikecoding.com/unity/tutorials/curves-and-splines/
### HOW TO
To create a new spline in the editor, click "GameObject - Bezier Spline". Now you can select the end points of the spline in the Scene view and move/rotate/scale or delete/duplicate them as you wish (each end point also has 2 control points that can be moved around). Most variables have explanatory tooltips.
You can tweak the Scene view gizmos via "Project Settings/yasirkula/Bezier Solution" page (on older versions, this menu is located at "Preferences" window).
The plugin comes with some additional components that may help you move objects or particles along splines. These components are located in the Utilities folder:
- BezierWalkerWithSpeed: Moves an object along a spline with constant speed. There are 3 travel modes: Once, Ping Pong and Loop. If Look At is Forward, the object will always face forwards. If it is SplineExtraData, the extra data stored in the spline's end points is used to determine the rotation. You can modify this extra data from the points' Inspector. The smoothness of the rotation can be adjusted via Rotation Lerp Modifier. Normalized T determines the starting point. Each time the object completes a lap, its On Path Completed () event is invoked. To see this component in action without entering Play mode, click the "Simulate In Editor" button.
- BezierWalkerWithTime: Travels a spline in Travel Time seconds. Movement Lerp Modifier parameter defines the smoothness applied to the position of the object. If High Quality is enabled, the spline will be traversed with constant speed but the calculations can be more expensive.
- BezierWalkerLocomotion: Allows you to move a number of objects together with this object on a spline. This component must be attached to an object with a BezierWalker component (tail objects don't need a BezierWalker, though). Look At, Movement Lerp Modifier and Rotation Lerp Modifier parameters affect the tail objects. If tail objects jitter too much, enabling High Quality may help greatly but the calculations can be more expensive.
- ParticlesFollowBezier: Moves particles of a Particle System in the direction of a spline. It is recommended to set the Simulation Space of the Particle System to Local for increased performance. This component affects particles in one of two ways:
-- Strict: particles will strictly follow the spline. They will always be aligned to the spline and will reach the end of the spline at the end of their lifetime. This mode performs slightly better than Relaxed mode
-- Relaxed: properties of the particle system like speed, Noise and Shape will affect the movement of the particles. Particles in this mode will usually look more interesting. If you want the particles to stick with the spline, though, set their speed to 0
- BezierAttachment: Snaps an object to the specified point of the spline. You can snap the object's position and/or rotation values, optionally with some offsets. Rotation can be snapped in one of two ways:
-- Use Spline Normals: spline's normal vectors will be used to determine the object's rotation
-- Use End Point Rotations: the Transform rotation values of the spline's end points will be used to determine the object's rotation
- BezierLineRenderer: Automatically positions a Line Renderer's points so that its shape matches the target spline's shape. It is possible to match the shape of only a portion of the spline by tweaking the Spline Sample Range property. If Line Renderer's "Use World Space" property is enabled, then its points will be placed at the spline's current position. Otherwise, the points will be placed relative to the Line Renderer's position and they will rotate/scale with the Line Renderer.
- BendMeshAlongBezier: Modifies a MeshFilter's mesh to bend it in the direction of a spline (make sure that the spline's normals are perpendicular to the spline; Auto Calculate Normals may help). If High Quality is enabled, evenly spaced bezier points will be used so that the mesh bends uniformly but the calculations will be more expensive. If Auto Refresh is enabled, the mesh will be refreshed automatically when the spline is modified (at runtime, this has the same effect with disabling the component but in edit mode, disabling the component will restore the original mesh instead). Mesh's normal and tangent vectors can optionally be recalculated in one of two ways:
-- Modify Originals: the original mesh's normal and tangent vectors will be rotated with the spline
-- Recalculate From Scratch: Unity's RecalculateNormals and/or RecalculateTangents functions will be invoked to recalculate these vectors from scratch
Note that this component doesn't add new vertices to the original mesh, so if the original mesh doesn't have enough vertices in its bend axis, then the bent mesh will have jagged edges on complex splines.

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 90c5928df0356a746a1423cce53181b9
timeCreated: 1562520040
licenseType: Store
TextScriptImporter:
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 86440575d46397c488152ba57ee62ed4
folderAsset: yes
timeCreated: 1473251123
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,607 @@
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.SceneManagement;
#if UNITY_2018_3_OR_NEWER
using PrefabStage = UnityEditor.Experimental.SceneManagement.PrefabStage;
using PrefabStageUtility = UnityEditor.Experimental.SceneManagement.PrefabStageUtility;
#endif
#endif
namespace BezierSolution
{
[AddComponentMenu( "Bezier Solution/Bend Mesh Along Bezier" )]
[HelpURL( "https://github.com/yasirkula/UnityBezierSolution" )]
[RequireComponent( typeof( MeshFilter ) )]
[ExecuteInEditMode]
public class BendMeshAlongBezier : MonoBehaviour
{
public enum VectorMode { DontModify = 0, ModifyOriginals = 1, RecalculateFromScratch = 2 };
public enum Axis { X = 0, Y = 1, Z = 2 };
#pragma warning disable 0649
[SerializeField]
private BezierSpline m_spline;
public BezierSpline spline
{
get { return m_spline; }
set
{
if( m_spline != value )
{
if( m_spline )
m_spline.onSplineChanged -= OnSplineChanged;
m_spline = value;
if( m_spline && isActiveAndEnabled )
{
m_spline.onSplineChanged -= OnSplineChanged;
m_spline.onSplineChanged += OnSplineChanged;
OnSplineChanged( m_spline, DirtyFlags.All );
}
}
}
}
[SerializeField]
[MinMaxRange( 0f, 1f )]
private Vector2 m_splineSampleRange = new Vector2( 0f, 1f );
public Vector2 SplineSampleRange
{
get { return m_splineSampleRange; }
set
{
value.x = Mathf.Clamp01( value.x );
value.y = Mathf.Clamp01( value.y );
if( m_splineSampleRange != value )
{
m_splineSampleRange = value;
OnSplineChanged( m_spline, DirtyFlags.All );
}
}
}
[Header( "Bend Options" )]
[SerializeField]
private bool m_highQuality = false;
public bool highQuality
{
get { return m_highQuality; }
set
{
if( m_highQuality != value )
{
m_highQuality = value;
OnSplineChanged( m_spline, DirtyFlags.All );
}
}
}
[SerializeField]
private Axis m_bendAxis = Axis.Y;
public Axis bendAxis
{
get { return m_bendAxis; }
set
{
if( m_bendAxis != value )
{
m_bendAxis = value;
RecalculateVertexRange();
OnSplineChanged( m_spline, DirtyFlags.All );
}
}
}
[SerializeField]
[Range( 0f, 360f )]
private float m_extraRotation = 0f;
public float extraRotation
{
get { return m_extraRotation; }
set
{
value = Mathf.Clamp( value, 0f, 360f );
if( m_extraRotation != value )
{
m_extraRotation = value;
OnSplineChanged( m_spline, DirtyFlags.All );
}
}
}
[SerializeField]
private bool m_invertDirection = false;
public bool invertDirection
{
get { return m_invertDirection; }
set
{
if( m_invertDirection != value )
{
m_invertDirection = value;
OnSplineChanged( m_spline, DirtyFlags.All );
}
}
}
[SerializeField]
private Vector2 m_thicknessMultiplier = Vector2.one;
public Vector2 thicknessMultiplier
{
get { return m_thicknessMultiplier; }
set
{
if( m_thicknessMultiplier != value )
{
m_thicknessMultiplier = value;
OnSplineChanged( m_spline, DirtyFlags.All );
}
}
}
[Header( "Vertex Attributes" )]
[SerializeField]
private VectorMode m_normalsMode = VectorMode.ModifyOriginals;
public VectorMode normalsMode
{
get { return m_normalsMode; }
set
{
if( m_normalsMode != value )
{
m_normalsMode = value;
if( mesh )
{
if( m_normalsMode == VectorMode.DontModify && originalNormals != null )
{
mesh.normals = originalNormals;
originalNormals = null;
}
if( m_normalsMode != VectorMode.ModifyOriginals )
normals = null;
}
OnSplineChanged( m_spline, DirtyFlags.All );
}
}
}
[SerializeField]
private VectorMode m_tangentsMode = VectorMode.ModifyOriginals;
public VectorMode tangentsMode
{
get { return m_tangentsMode; }
set
{
if( m_tangentsMode != value )
{
m_tangentsMode = value;
if( mesh )
{
if( m_tangentsMode == VectorMode.DontModify && originalTangents != null )
{
mesh.tangents = originalTangents;
originalTangents = null;
}
if( m_tangentsMode != VectorMode.ModifyOriginals )
tangents = null;
}
OnSplineChanged( m_spline, DirtyFlags.All );
}
}
}
[Header( "Other Settings" )]
[SerializeField]
private bool m_autoRefresh = true;
public bool autoRefresh
{
get { return m_autoRefresh; }
set
{
if( m_autoRefresh != value )
{
m_autoRefresh = value;
OnSplineChanged( m_spline, DirtyFlags.All );
}
}
}
#if UNITY_EDITOR
[SerializeField]
private bool executeInEditMode = false;
[SerializeField, HideInInspector]
private BezierSpline prevSpline;
[SerializeField, HideInInspector]
private VectorMode prevNormalsMode, prevTangentsMode;
[SerializeField, HideInInspector]
private bool prevHighQuality;
#endif
[SerializeField, HideInInspector]
private Mesh originalMesh; // If this isn't serialized, then sometimes exceptions occur on undo/redo
#pragma warning restore 0649
private MeshFilter meshFilter;
private Mesh mesh;
private Vector3[] vertices, originalVertices;
private Vector3[] normals, originalNormals;
private Vector4[] tangents, originalTangents;
private float minVertex, _1OverVertexRange;
private void OnEnable()
{
#if UNITY_EDITOR
// Restore normals and tangents after assembly reload if they are set to DontModify because otherwise they become null automatically (i.e. information gets lost)
if( mesh && originalMesh )
{
if( m_normalsMode == VectorMode.DontModify )
mesh.normals = originalMesh.normals;
if( m_tangentsMode == VectorMode.DontModify )
mesh.tangents = originalMesh.tangents;
}
EditorSceneManager.sceneSaving -= OnSceneSaving;
EditorSceneManager.sceneSaving += OnSceneSaving;
EditorSceneManager.sceneSaved -= OnSceneSaved;
EditorSceneManager.sceneSaved += OnSceneSaved;
#endif
if( m_spline )
{
m_spline.onSplineChanged -= OnSplineChanged;
m_spline.onSplineChanged += OnSplineChanged;
OnSplineChanged( m_spline, DirtyFlags.All );
}
}
private void OnDisable()
{
if( m_spline )
m_spline.onSplineChanged -= OnSplineChanged;
#if UNITY_EDITOR
EditorSceneManager.sceneSaving -= OnSceneSaving;
EditorSceneManager.sceneSaved -= OnSceneSaved;
if( !EditorApplication.isPlaying )
OnDestroy();
#endif
}
private void OnDestroy()
{
MeshFilter _meshFilter = meshFilter;
meshFilter = null;
if( _meshFilter && originalMesh )
_meshFilter.sharedMesh = originalMesh;
if( mesh )
DestroyImmediate( mesh );
#if UNITY_EDITOR && UNITY_2018_3_OR_NEWER
// This allows removing the 'modified' flag of Mesh Filter's Mesh property but these sorts of things
// may cause new problems in edge cases so it is commented out
//if( !EditorApplication.isPlaying && _meshFilter && originalMesh )
//{
// // Revert modified status of the prefab instance's MeshFilter Mesh if possible
// MeshFilter prefabMeshFilter = null;
// if( PrefabUtility.GetPrefabInstanceStatus( _meshFilter ) == PrefabInstanceStatus.Connected )
// prefabMeshFilter = PrefabUtility.GetCorrespondingObjectFromSource( _meshFilter ) as MeshFilter;
// if( prefabMeshFilter && prefabMeshFilter.sharedMesh == originalMesh )
// PrefabUtility.RevertPropertyOverride( new SerializedObject( _meshFilter ).FindProperty( "m_Mesh" ), InteractionMode.AutomatedAction );
//}
#endif
}
public void Activate()
{
enabled = true;
}
public void Deactivate()
{
OnDestroy();
enabled = false;
}
#if UNITY_EDITOR
private void OnValidate()
{
EditorApplication.update -= OnValidateImplementation;
EditorApplication.update += OnValidateImplementation;
}
// Calling this code inside OnValidate throws "SendMessage cannot be called during Awake, CheckConsistency, or OnValidate" warnings
private void OnValidateImplementation()
{
EditorApplication.update -= OnValidateImplementation;
if( !this )
return;
BezierSpline _spline = m_spline;
m_spline = prevSpline;
spline = prevSpline = _spline;
bool _highQuality = m_highQuality;
m_highQuality = prevHighQuality;
highQuality = prevHighQuality = _highQuality;
VectorMode _normalsMode = m_normalsMode;
m_normalsMode = prevNormalsMode;
normalsMode = prevNormalsMode = _normalsMode;
VectorMode _tangentsMode = m_tangentsMode;
m_tangentsMode = prevTangentsMode;
tangentsMode = prevTangentsMode = _tangentsMode;
RecalculateVertexRange();
if( !executeInEditMode && !EditorApplication.isPlaying )
OnDestroy();
else if( isActiveAndEnabled )
OnSplineChanged( m_spline, DirtyFlags.All );
SceneView.RepaintAll();
}
private void OnSceneSaving( UnityEngine.SceneManagement.Scene scene, string path )
{
// Restore original mesh before saving the scene
if( scene == gameObject.scene )
OnDestroy();
}
private void OnSceneSaved( UnityEngine.SceneManagement.Scene scene )
{
// Restore modified mesh after saving the scene
if( scene == gameObject.scene && isActiveAndEnabled )
OnSplineChanged( m_spline, DirtyFlags.All );
}
#endif
private void OnSplineChanged( BezierSpline spline, DirtyFlags dirtyFlags )
{
#if UNITY_EDITOR
if( !executeInEditMode && !EditorApplication.isPlaying )
return;
if( BuildPipeline.isBuildingPlayer )
return;
#if UNITY_2018_3_OR_NEWER
// Don't execute the script in prefab mode
PrefabStage openPrefabStage = PrefabStageUtility.GetCurrentPrefabStage();
if( openPrefabStage != null && openPrefabStage.IsPartOfPrefabContents( gameObject ) )
return;
#endif
#endif
if( m_autoRefresh && ( dirtyFlags & ( DirtyFlags.SplineShapeChanged | DirtyFlags.NormalsChanged ) ) != DirtyFlags.None )
Refresh();
}
private void Initialize()
{
meshFilter = GetComponent<MeshFilter>();
if( meshFilter.sharedMesh ) // It can sometimes be null during undo&redo which causes issues
originalMesh = meshFilter.sharedMesh;
if( !originalMesh )
return;
if( mesh )
DestroyImmediate( mesh );
mesh = Instantiate( originalMesh );
meshFilter.sharedMesh = mesh;
#if UNITY_EDITOR
if( !EditorApplication.isPlaying )
mesh.hideFlags = HideFlags.DontSave;
#endif
originalVertices = mesh.vertices;
originalNormals = null;
originalTangents = null;
RecalculateVertexRange();
}
private void RecalculateVertexRange()
{
if( originalVertices == null )
return;
minVertex = float.PositiveInfinity;
float maxVertex = float.NegativeInfinity;
switch( m_bendAxis )
{
case Axis.X:
for( int i = 0; i < originalVertices.Length; i++ )
{
float vertex = originalVertices[i].x;
if( vertex < minVertex )
minVertex = originalVertices[i].x;
if( vertex > maxVertex )
maxVertex = originalVertices[i].x;
}
break;
case Axis.Y:
for( int i = 0; i < originalVertices.Length; i++ )
{
float vertex = originalVertices[i].y;
if( vertex < minVertex )
minVertex = originalVertices[i].y;
if( vertex > maxVertex )
maxVertex = originalVertices[i].y;
}
break;
case Axis.Z:
for( int i = 0; i < originalVertices.Length; i++ )
{
float vertex = originalVertices[i].z;
if( vertex < minVertex )
minVertex = originalVertices[i].z;
if( vertex > maxVertex )
maxVertex = originalVertices[i].z;
}
break;
}
_1OverVertexRange = 1f / ( maxVertex - minVertex );
}
public void Refresh()
{
if( !m_spline )
return;
if( !meshFilter || ( meshFilter.sharedMesh && meshFilter.sharedMesh != mesh && meshFilter.sharedMesh != originalMesh ) )
Initialize();
if( !originalMesh )
return;
if( vertices == null || vertices.Length != originalVertices.Length )
vertices = new Vector3[originalVertices.Length];
if( m_normalsMode == VectorMode.ModifyOriginals )
{
if( originalNormals == null )
originalNormals = originalMesh.normals;
if( originalNormals == null || originalNormals.Length < originalVertices.Length ) // If somehow above statement returned null
normals = null;
else if( normals == null || normals.Length != originalNormals.Length )
normals = new Vector3[originalNormals.Length];
}
else
normals = null;
if( m_tangentsMode == VectorMode.ModifyOriginals )
{
if( originalTangents == null )
originalTangents = originalMesh.tangents;
if( originalTangents == null || originalTangents.Length < originalVertices.Length ) // If somehow above statement returned null
tangents = null;
else if( tangents == null || tangents.Length != originalTangents.Length )
tangents = new Vector4[originalTangents.Length];
}
else
tangents = null;
Vector2 _splineSampleRange = m_splineSampleRange;
if( m_invertDirection )
{
float temp = _splineSampleRange.x;
_splineSampleRange.x = _splineSampleRange.y;
_splineSampleRange.y = temp;
}
bool isSampleRangeForwards = _splineSampleRange.x <= _splineSampleRange.y;
float splineSampleLength = _splineSampleRange.y - _splineSampleRange.x;
bool dontInvertModifiedVertexAttributes = ( m_thicknessMultiplier.x > 0f && m_thicknessMultiplier.y > 0f );
BezierSpline.EvenlySpacedPointsHolder evenlySpacedPoints = m_highQuality ? m_spline.evenlySpacedPoints : null;
Vector3 initialPoint = m_spline.GetPoint( 0f );
for( int i = 0; i < originalVertices.Length; i++ )
{
Vector3 vertex = originalVertices[i];
float vertexPosition;
Vector3 vertexOffset;
switch( m_bendAxis )
{
case Axis.X:
vertexPosition = vertex.x;
vertexOffset = new Vector3( vertex.z * m_thicknessMultiplier.x, 0f, vertex.y * m_thicknessMultiplier.y );
break;
case Axis.Y:
default:
vertexPosition = vertex.y;
vertexOffset = new Vector3( vertex.x * m_thicknessMultiplier.x, 0f, vertex.z * m_thicknessMultiplier.y );
break;
case Axis.Z:
vertexPosition = vertex.z;
vertexOffset = new Vector3( vertex.y * m_thicknessMultiplier.x, 0f, vertex.x * m_thicknessMultiplier.y );
break;
}
float normalizedT = _splineSampleRange.x + ( vertexPosition - minVertex ) * _1OverVertexRange * splineSampleLength; // Remap from [minVertex,maxVertex] to _splineSampleRange
if( m_highQuality )
normalizedT = evenlySpacedPoints.GetNormalizedTAtPercentage( normalizedT );
BezierSpline.Segment segment = m_spline.GetSegmentAt( normalizedT );
Vector3 point = segment.GetPoint() - initialPoint;
Vector3 tangent = isSampleRangeForwards ? segment.GetTangent() : -segment.GetTangent();
Quaternion rotation = Quaternion.AngleAxis( m_extraRotation, tangent ) * Quaternion.LookRotation( segment.GetNormal(), tangent );
Vector3 direction = rotation * vertexOffset;
vertices[i] = point + direction;
if( normals != null ) // The only case this happens is when Normals Mode is ModifyOriginals and the original mesh has normals
normals[i] = rotation * ( dontInvertModifiedVertexAttributes ? originalNormals[i] : -originalNormals[i] );
if( tangents != null ) // The only case this happens is when Tangents Mode is ModifyOriginals and the original mesh has tangents
{
float tangentW = originalTangents[i].w;
tangents[i] = rotation * ( dontInvertModifiedVertexAttributes ? originalTangents[i] : -originalTangents[i] );
tangents[i].w = tangentW;
}
}
mesh.vertices = vertices;
if( m_normalsMode == VectorMode.ModifyOriginals )
mesh.normals = normals;
if( m_tangentsMode == VectorMode.ModifyOriginals )
mesh.tangents = tangents;
if( m_normalsMode == VectorMode.RecalculateFromScratch )
{
mesh.RecalculateNormals();
#if UNITY_EDITOR
// Cache original normals so that we can reset normals in OnValidate when normals are reset back to DontModify
if( originalNormals == null )
originalNormals = originalMesh.normals;
#endif
}
if( m_tangentsMode == VectorMode.RecalculateFromScratch )
{
mesh.RecalculateTangents();
#if UNITY_EDITOR
// Cache original tangents so that we can reset tangents in OnValidate when tangents are reset back to DontModify
if( originalTangents == null )
originalTangents = originalMesh.tangents;
#endif
}
mesh.RecalculateBounds();
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 0e815427364673446939224ffdf5e5fd
timeCreated: 1620245307
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,231 @@
using UnityEngine;
namespace BezierSolution
{
[AddComponentMenu( "Bezier Solution/Bezier Attachment" )]
[HelpURL( "https://github.com/yasirkula/UnityBezierSolution" )]
[ExecuteInEditMode]
public class BezierAttachment : MonoBehaviour
{
public enum RotationMode { No = 0, UseSplineNormals = 1, UseEndPointRotations = 2 };
#pragma warning disable 0649
[SerializeField]
private BezierSpline m_spline;
public BezierSpline spline
{
get { return m_spline; }
set
{
if( m_spline != value )
{
if( m_spline )
m_spline.onSplineChanged -= OnSplineChanged;
m_spline = value;
if( m_spline && isActiveAndEnabled )
{
m_spline.onSplineChanged -= OnSplineChanged;
m_spline.onSplineChanged += OnSplineChanged;
OnSplineChanged( m_spline, DirtyFlags.All );
}
}
}
}
[SerializeField]
[Range( 0f, 1f )]
private float m_normalizedT = 0f;
public float normalizedT
{
get { return m_normalizedT; }
set
{
value = Mathf.Clamp01( value );
if( m_normalizedT != value )
{
m_normalizedT = value;
if( isActiveAndEnabled )
OnSplineChanged( m_spline, DirtyFlags.All );
}
}
}
[Header( "Position" )]
[SerializeField]
private bool m_updatePosition = true;
public bool updatePosition
{
get { return m_updatePosition; }
set
{
if( m_updatePosition != value )
{
m_updatePosition = value;
if( m_updatePosition && isActiveAndEnabled )
OnSplineChanged( m_spline, DirtyFlags.SplineShapeChanged );
}
}
}
[SerializeField]
private Vector3 m_positionOffset;
public Vector3 positionOffset
{
get { return m_positionOffset; }
set
{
if( m_positionOffset != value )
{
m_positionOffset = value;
if( m_updatePosition && isActiveAndEnabled )
OnSplineChanged( m_spline, DirtyFlags.SplineShapeChanged );
}
}
}
[Header( "Rotation" )]
[SerializeField]
private RotationMode m_updateRotation = RotationMode.UseSplineNormals;
public RotationMode updateRotation
{
get { return m_updateRotation; }
set
{
if( m_updateRotation != value )
{
m_updateRotation = value;
if( m_updateRotation != RotationMode.No && isActiveAndEnabled )
OnSplineChanged( m_spline, DirtyFlags.SplineShapeChanged );
}
}
}
[SerializeField]
private Vector3 m_rotationOffset;
public Vector3 rotationOffset
{
get { return m_rotationOffset; }
set
{
if( m_rotationOffset != value )
{
m_rotationOffset = value;
if( m_updateRotation != RotationMode.No && isActiveAndEnabled )
OnSplineChanged( m_spline, DirtyFlags.SplineShapeChanged );
}
}
}
#if UNITY_EDITOR
[Header( "Other Settings" )]
[SerializeField]
private bool executeInEditMode = false;
[SerializeField, HideInInspector]
private BezierSpline prevSpline;
#endif
#pragma warning restore 0649
private void OnEnable()
{
if( m_spline )
{
m_spline.onSplineChanged -= OnSplineChanged;
m_spline.onSplineChanged += OnSplineChanged;
OnSplineChanged( m_spline, DirtyFlags.All );
}
}
private void OnDisable()
{
if( m_spline )
m_spline.onSplineChanged -= OnSplineChanged;
}
#if UNITY_EDITOR
private void OnValidate()
{
UnityEditor.Undo.RecordObject( transform, "Modify BezierAttachment" );
BezierSpline _spline = m_spline;
m_spline = prevSpline;
spline = prevSpline = _spline;
if( isActiveAndEnabled )
OnSplineChanged( m_spline, DirtyFlags.All );
}
private void LateUpdate()
{
if( transform.hasChanged )
OnSplineChanged( m_spline, DirtyFlags.All );
}
#endif
private void OnSplineChanged( BezierSpline spline, DirtyFlags dirtyFlags )
{
#if UNITY_EDITOR
if( !executeInEditMode && !UnityEditor.EditorApplication.isPlaying )
return;
#endif
RefreshInternal( dirtyFlags );
}
public void Refresh()
{
RefreshInternal( DirtyFlags.All );
}
private void RefreshInternal( DirtyFlags dirtyFlags )
{
if( !m_spline || m_spline.Count < 2 )
return;
if( !m_updatePosition && m_updateRotation == RotationMode.No )
return;
BezierSpline.Segment segment = m_spline.GetSegmentAt( m_normalizedT );
switch( m_updateRotation )
{
case RotationMode.UseSplineNormals:
if( m_rotationOffset == Vector3.zero )
transform.rotation = Quaternion.LookRotation( segment.GetTangent(), segment.GetNormal() );
else
transform.rotation = Quaternion.LookRotation( segment.GetTangent(), segment.GetNormal() ) * Quaternion.Euler( m_rotationOffset );
break;
case RotationMode.UseEndPointRotations:
if( m_rotationOffset == Vector3.zero )
transform.rotation = Quaternion.LerpUnclamped( segment.point1.rotation, segment.point2.rotation, segment.localT );
else
transform.rotation = Quaternion.LerpUnclamped( segment.point1.rotation, segment.point2.rotation, segment.localT ) * Quaternion.Euler( m_rotationOffset );
break;
}
if( m_updatePosition && ( dirtyFlags & DirtyFlags.SplineShapeChanged ) == DirtyFlags.SplineShapeChanged )
{
if( m_positionOffset == Vector3.zero )
transform.position = segment.GetPoint();
else
transform.position = segment.GetPoint() + transform.rotation * m_positionOffset;
}
#if UNITY_EDITOR
transform.hasChanged = false;
#endif
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 9b6258aafd9a87344833937e5e546638
timeCreated: 1620400687
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,206 @@
using UnityEngine;
namespace BezierSolution
{
[AddComponentMenu( "Bezier Solution/Bezier Line Renderer" )]
[HelpURL( "https://github.com/yasirkula/UnityBezierSolution" )]
[RequireComponent( typeof( LineRenderer ) )]
[ExecuteInEditMode]
public class BezierLineRenderer : MonoBehaviour
{
#pragma warning disable 0649
[SerializeField]
private BezierSpline m_spline;
public BezierSpline spline
{
get { return m_spline; }
set
{
if( m_spline != value )
{
if( m_spline )
m_spline.onSplineChanged -= OnSplineChanged;
m_spline = value;
if( m_spline && isActiveAndEnabled )
{
m_spline.onSplineChanged -= OnSplineChanged;
m_spline.onSplineChanged += OnSplineChanged;
OnSplineChanged( m_spline, DirtyFlags.All );
}
}
}
}
[SerializeField]
[MinMaxRange( 0f, 1f )]
private Vector2 m_splineSampleRange = new Vector2( 0f, 1f );
public Vector2 SplineSampleRange
{
get { return m_splineSampleRange; }
set
{
value.x = Mathf.Clamp01( value.x );
value.y = Mathf.Clamp01( value.y );
if( m_splineSampleRange != value )
{
m_splineSampleRange = value;
if( isActiveAndEnabled )
OnSplineChanged( m_spline, DirtyFlags.All );
}
}
}
[Header( "Line Options" )]
[SerializeField]
[Range( 0, 30 )]
private int m_smoothness = 5;
public int smoothness
{
get { return m_smoothness; }
set
{
if( m_smoothness != value )
{
m_smoothness = value;
if( isActiveAndEnabled )
OnSplineChanged( m_spline, DirtyFlags.All );
}
}
}
#if UNITY_EDITOR
[Header( "Other Settings" )]
[SerializeField]
private bool executeInEditMode = false;
[SerializeField, HideInInspector]
private BezierSpline prevSpline;
#endif
#pragma warning restore 0649
private LineRenderer lineRenderer;
private Vector3[] lineRendererPoints;
#if UNITY_EDITOR
private bool lineRendererUseWorldSpace = true;
#endif
private void OnEnable()
{
if( m_spline )
{
m_spline.onSplineChanged -= OnSplineChanged;
m_spline.onSplineChanged += OnSplineChanged;
OnSplineChanged( m_spline, DirtyFlags.All );
}
}
private void OnDisable()
{
if( m_spline )
m_spline.onSplineChanged -= OnSplineChanged;
}
#if UNITY_EDITOR
private void Update()
{
if( lineRenderer && lineRenderer.useWorldSpace != lineRendererUseWorldSpace )
{
lineRendererUseWorldSpace = !lineRendererUseWorldSpace;
if( isActiveAndEnabled )
OnSplineChanged( m_spline, DirtyFlags.All );
}
}
private void OnValidate()
{
BezierSpline _spline = m_spline;
m_spline = prevSpline;
spline = prevSpline = _spline;
if( isActiveAndEnabled )
OnSplineChanged( m_spline, DirtyFlags.All );
}
#endif
private void OnSplineChanged( BezierSpline spline, DirtyFlags dirtyFlags )
{
#if UNITY_EDITOR
if( !executeInEditMode && !UnityEditor.EditorApplication.isPlaying )
return;
#endif
if( ( dirtyFlags & DirtyFlags.SplineShapeChanged ) == DirtyFlags.SplineShapeChanged )
Refresh( m_smoothness );
}
public void Refresh( int smoothness )
{
if( !m_spline || m_spline.Count < 2 )
return;
if( !lineRenderer )
lineRenderer = GetComponent<LineRenderer>();
smoothness = Mathf.Clamp( smoothness, 1, 30 );
int numberOfPoints = ( m_spline.Count - 1 ) * smoothness;
if( !m_spline.loop )
numberOfPoints++; // spline.GetPoint( 1f )
else
numberOfPoints += smoothness; // Final point is connected to the first point via lineRenderer.loop, so no "numberOfPoints++" here
if( lineRendererPoints == null || lineRendererPoints.Length != numberOfPoints )
lineRendererPoints = new Vector3[numberOfPoints];
if( m_splineSampleRange.x <= 0f && m_splineSampleRange.y >= 1f )
{
int pointIndex = 0;
float smoothnessStep = 1f / smoothness;
for( int i = 0; i < m_spline.Count - 1; i++ )
{
BezierSpline.Segment segment = new BezierSpline.Segment( m_spline[i], m_spline[i + 1], 0f );
for( int j = 0; j < smoothness; j++, pointIndex++ )
lineRendererPoints[pointIndex] = segment.GetPoint( j * smoothnessStep );
}
if( !m_spline.loop )
lineRendererPoints[numberOfPoints - 1] = m_spline.GetPoint( 1f );
else
{
BezierSpline.Segment segment = new BezierSpline.Segment( m_spline[m_spline.Count - 1], m_spline[0], 0f );
for( int j = 0; j < smoothness; j++, pointIndex++ )
lineRendererPoints[pointIndex] = segment.GetPoint( j * smoothnessStep );
}
}
else
{
float smoothnessStep = ( m_splineSampleRange.y - m_splineSampleRange.x ) / ( numberOfPoints - 1 );
for( int i = 0; i < numberOfPoints; i++ )
lineRendererPoints[i] = spline.GetPoint( m_splineSampleRange.x + i * smoothnessStep );
}
#if UNITY_EDITOR
lineRendererUseWorldSpace = lineRenderer.useWorldSpace;
#endif
if( !lineRenderer.useWorldSpace )
{
Vector3 initialPoint = m_spline.GetPoint( 0f );
for( int i = 0; i < numberOfPoints; i++ )
lineRendererPoints[i] -= initialPoint;
}
lineRenderer.positionCount = lineRendererPoints.Length;
lineRenderer.SetPositions( lineRendererPoints );
lineRenderer.loop = m_spline.loop && m_splineSampleRange.x <= 0f && m_splineSampleRange.y >= 1f;
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 09bf7d81c21c8564abb7c13d3e848e94
timeCreated: 1620206953
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,23 @@
using UnityEngine;
namespace BezierSolution
{
public enum TravelMode { Once = 0, Loop = 1, PingPong = 2 };
public enum LookAtMode { None = 0, Forward = 1, SplineExtraData = 2 }
public abstract class BezierWalker : MonoBehaviour
{
public abstract BezierSpline Spline { get; }
public abstract bool MovingForward { get; }
public abstract float NormalizedT { get; set; }
public abstract void Execute( float deltaTime );
public static readonly ExtraDataLerpFunction extraDataLerpAsQuaternionFunction = InterpolateExtraDataAsQuaternion;
private static BezierPoint.ExtraData InterpolateExtraDataAsQuaternion( BezierPoint.ExtraData data1, BezierPoint.ExtraData data2, float normalizedT )
{
return Quaternion.LerpUnclamped( data1, data2, normalizedT );
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2e3fd6f386de3644ba3090712795517d
timeCreated: 1542623772
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,155 @@
using System.Collections.Generic;
using UnityEngine;
namespace BezierSolution
{
[AddComponentMenu( "Bezier Solution/Bezier Walker Locomotion" )]
[HelpURL( "https://github.com/yasirkula/UnityBezierSolution" )]
public class BezierWalkerLocomotion : BezierWalker
{
public BezierWalker walker;
#pragma warning disable 0649
[SerializeField]
private List<Transform> tailObjects;
public List<Transform> Tail { get { return tailObjects; } }
[SerializeField]
private List<float> tailObjectDistances;
public List<float> TailDistances { get { return tailObjectDistances; } }
#pragma warning restore 0649
public bool highQuality = true; // true by default because when it is set to false, tail objects can jitter too much
public float movementLerpModifier = 10f;
public float rotationLerpModifier = 10f;
public LookAtMode lookAt = LookAtMode.Forward;
public override BezierSpline Spline { get { return walker.Spline; } }
public override bool MovingForward { get { return walker.MovingForward; } }
public override float NormalizedT
{
get { return walker.NormalizedT; }
set { walker.NormalizedT = value; }
}
private void Start()
{
if( !walker )
{
Debug.LogError( "Need to attach BezierWalkerLocomotion to a BezierWalker!" );
Destroy( this );
}
if( tailObjects.Count != tailObjectDistances.Count )
{
Debug.LogError( "One distance per tail object is needed!" );
Destroy( this );
}
}
private void LateUpdate()
{
Execute( Time.deltaTime );
}
public override void Execute( float deltaTime )
{
BezierSpline spline = Spline;
float t = highQuality ? spline.evenlySpacedPoints.GetPercentageAtNormalizedT( NormalizedT ) : NormalizedT;
bool forward = MovingForward;
for( int i = 0; i < tailObjects.Count; i++ )
{
Transform tailObject = tailObjects[i];
Vector3 tailPosition;
float tailNormalizedT;
if( highQuality )
{
if( forward )
t -= tailObjectDistances[i] / spline.evenlySpacedPoints.splineLength;
else
t += tailObjectDistances[i] / spline.evenlySpacedPoints.splineLength;
tailNormalizedT = spline.evenlySpacedPoints.GetNormalizedTAtPercentage( t );
tailPosition = spline.GetPoint( tailNormalizedT );
}
else
{
tailPosition = spline.MoveAlongSpline( ref t, forward ? -tailObjectDistances[i] : tailObjectDistances[i] );
tailNormalizedT = t;
}
tailObject.position = Vector3.Lerp( tailObject.position, tailPosition, movementLerpModifier * deltaTime );
if( lookAt == LookAtMode.Forward )
{
BezierSpline.Segment segment = spline.GetSegmentAt( tailNormalizedT );
tailObject.rotation = Quaternion.Lerp( tailObject.rotation, Quaternion.LookRotation( forward ? segment.GetTangent() : -segment.GetTangent(), segment.GetNormal() ), rotationLerpModifier * deltaTime );
}
else if( lookAt == LookAtMode.SplineExtraData )
tailObject.rotation = Quaternion.Lerp( tailObject.rotation, spline.GetExtraData( tailNormalizedT, extraDataLerpAsQuaternionFunction ), rotationLerpModifier * deltaTime );
}
}
public void AddToTail( Transform transform, float distanceToPreviousObject )
{
if( transform == null )
{
Debug.LogError( "Object is null!" );
return;
}
tailObjects.Add( transform );
tailObjectDistances.Add( distanceToPreviousObject );
}
public void InsertIntoTail( int index, Transform transform, float distanceToPreviousObject )
{
if( transform == null )
{
Debug.LogError( "Object is null!" );
return;
}
tailObjects.Insert( index, transform );
tailObjectDistances.Insert( index, distanceToPreviousObject );
}
public void RemoveFromTail( Transform transform )
{
if( transform == null )
{
Debug.LogError( "Object is null!" );
return;
}
for( int i = 0; i < tailObjects.Count; i++ )
{
if( tailObjects[i] == transform )
{
tailObjects.RemoveAt( i );
tailObjectDistances.RemoveAt( i );
return;
}
}
}
#if UNITY_EDITOR
private void Reset()
{
BezierWalker[] walkerComponents = GetComponents<BezierWalker>();
for( int i = 0; i < walkerComponents.Length; i++ )
{
if( !( walkerComponents[i] is BezierWalkerLocomotion ) && ( (MonoBehaviour) walkerComponents[i] ).enabled )
{
walker = walkerComponents[i];
break;
}
}
}
#endif
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 17b675957a920ef4e8da909ede6d0d04
timeCreated: 1542623444
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,126 @@
using UnityEngine;
using UnityEngine.Events;
namespace BezierSolution
{
[AddComponentMenu( "Bezier Solution/Bezier Walker With Speed" )]
[HelpURL( "https://github.com/yasirkula/UnityBezierSolution" )]
public class BezierWalkerWithSpeed : BezierWalker
{
public BezierSpline spline;
public TravelMode travelMode;
public float speed = 5f;
[SerializeField]
[Range( 0f, 1f )]
private float m_normalizedT = 0f;
public override BezierSpline Spline { get { return spline; } }
public override float NormalizedT
{
get { return m_normalizedT; }
set { m_normalizedT = value; }
}
//public float movementLerpModifier = 10f;
public float rotationLerpModifier = 10f;
public LookAtMode lookAt = LookAtMode.Forward;
private bool isGoingForward = true;
public override bool MovingForward { get { return ( speed > 0f ) == isGoingForward; } }
public UnityEvent onPathCompleted = new UnityEvent();
private bool onPathCompletedCalledAt1 = false;
private bool onPathCompletedCalledAt0 = false;
private void Update()
{
Execute( Time.deltaTime );
}
public override void Execute( float deltaTime )
{
float targetSpeed = ( isGoingForward ) ? speed : -speed;
Vector3 targetPos = spline.MoveAlongSpline( ref m_normalizedT, targetSpeed * deltaTime );
transform.position = targetPos;
//transform.position = Vector3.Lerp( transform.position, targetPos, movementLerpModifier * deltaTime );
bool movingForward = MovingForward;
if( lookAt == LookAtMode.Forward )
{
BezierSpline.Segment segment = spline.GetSegmentAt( m_normalizedT );
Quaternion targetRotation;
if( movingForward )
targetRotation = Quaternion.LookRotation( segment.GetTangent(), segment.GetNormal() );
else
targetRotation = Quaternion.LookRotation( -segment.GetTangent(), segment.GetNormal() );
transform.rotation = Quaternion.Lerp( transform.rotation, targetRotation, rotationLerpModifier * deltaTime );
}
else if( lookAt == LookAtMode.SplineExtraData )
transform.rotation = Quaternion.Lerp( transform.rotation, spline.GetExtraData( m_normalizedT, extraDataLerpAsQuaternionFunction ), rotationLerpModifier * deltaTime );
if( movingForward )
{
if( m_normalizedT >= 1f )
{
if( travelMode == TravelMode.Once )
m_normalizedT = 1f;
else if( travelMode == TravelMode.Loop )
m_normalizedT -= 1f;
else
{
m_normalizedT = 2f - m_normalizedT;
isGoingForward = !isGoingForward;
}
if( !onPathCompletedCalledAt1 )
{
onPathCompletedCalledAt1 = true;
#if UNITY_EDITOR
if( UnityEditor.EditorApplication.isPlaying )
#endif
onPathCompleted.Invoke();
}
}
else
{
onPathCompletedCalledAt1 = false;
}
}
else
{
if( m_normalizedT <= 0f )
{
if( travelMode == TravelMode.Once )
m_normalizedT = 0f;
else if( travelMode == TravelMode.Loop )
m_normalizedT += 1f;
else
{
m_normalizedT = -m_normalizedT;
isGoingForward = !isGoingForward;
}
if( !onPathCompletedCalledAt0 )
{
onPathCompletedCalledAt0 = true;
#if UNITY_EDITOR
if( UnityEditor.EditorApplication.isPlaying )
#endif
onPathCompleted.Invoke();
}
}
else
{
onPathCompletedCalledAt0 = false;
}
}
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 148310ac13c958d4c93f53cdfe985375
timeCreated: 1473251134
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,127 @@
using UnityEngine;
using UnityEngine.Events;
namespace BezierSolution
{
[AddComponentMenu( "Bezier Solution/Bezier Walker With Time" )]
[HelpURL( "https://github.com/yasirkula/UnityBezierSolution" )]
public class BezierWalkerWithTime : BezierWalker
{
public BezierSpline spline;
public TravelMode travelMode;
public float travelTime = 5f;
[SerializeField]
[Range( 0f, 1f )]
private float m_normalizedT = 0f;
public bool highQuality = false;
public override BezierSpline Spline { get { return spline; } }
public override float NormalizedT
{
get { return m_normalizedT; }
set { m_normalizedT = value; }
}
public float movementLerpModifier = 10f;
public float rotationLerpModifier = 10f;
public LookAtMode lookAt = LookAtMode.Forward;
private bool isGoingForward = true;
public override bool MovingForward { get { return isGoingForward; } }
public UnityEvent onPathCompleted = new UnityEvent();
private bool onPathCompletedCalledAt1 = false;
private bool onPathCompletedCalledAt0 = false;
private void Update()
{
Execute( Time.deltaTime );
}
public override void Execute( float deltaTime )
{
float _normalizedT = highQuality ? spline.evenlySpacedPoints.GetNormalizedTAtPercentage( m_normalizedT ) : m_normalizedT;
transform.position = Vector3.Lerp( transform.position, spline.GetPoint( _normalizedT ), movementLerpModifier * deltaTime );
if( lookAt == LookAtMode.Forward )
{
BezierSpline.Segment segment = spline.GetSegmentAt( _normalizedT );
Quaternion targetRotation;
if( isGoingForward )
targetRotation = Quaternion.LookRotation( segment.GetTangent(), segment.GetNormal() );
else
targetRotation = Quaternion.LookRotation( -segment.GetTangent(), segment.GetNormal() );
transform.rotation = Quaternion.Lerp( transform.rotation, targetRotation, rotationLerpModifier * deltaTime );
}
else if( lookAt == LookAtMode.SplineExtraData )
transform.rotation = Quaternion.Lerp( transform.rotation, spline.GetExtraData( _normalizedT, extraDataLerpAsQuaternionFunction ), rotationLerpModifier * deltaTime );
if( isGoingForward )
{
m_normalizedT += deltaTime / travelTime;
if( m_normalizedT > 1f )
{
if( travelMode == TravelMode.Once )
m_normalizedT = 1f;
else if( travelMode == TravelMode.Loop )
m_normalizedT -= 1f;
else
{
m_normalizedT = 2f - m_normalizedT;
isGoingForward = false;
}
if( !onPathCompletedCalledAt1 )
{
onPathCompletedCalledAt1 = true;
#if UNITY_EDITOR
if( UnityEditor.EditorApplication.isPlaying )
#endif
onPathCompleted.Invoke();
}
}
else
{
onPathCompletedCalledAt1 = false;
}
}
else
{
m_normalizedT -= deltaTime / travelTime;
if( m_normalizedT < 0f )
{
if( travelMode == TravelMode.Once )
m_normalizedT = 0f;
else if( travelMode == TravelMode.Loop )
m_normalizedT += 1f;
else
{
m_normalizedT = -m_normalizedT;
isGoingForward = true;
}
if( !onPathCompletedCalledAt0 )
{
onPathCompletedCalledAt0 = true;
#if UNITY_EDITOR
if( UnityEditor.EditorApplication.isPlaying )
#endif
onPathCompleted.Invoke();
}
}
else
{
onPathCompletedCalledAt0 = false;
}
}
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 46d12b9f97514694e962a3395a73e638
timeCreated: 1473251134
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,106 @@
using System.Collections.Generic;
using UnityEngine;
namespace BezierSolution
{
[AddComponentMenu( "Bezier Solution/Particles Follow Bezier" )]
[HelpURL( "https://github.com/yasirkula/UnityBezierSolution" )]
[RequireComponent( typeof( ParticleSystem ) )]
[ExecuteInEditMode]
public class ParticlesFollowBezier : MonoBehaviour
{
private const int MAX_PARTICLE_COUNT = 25000;
public enum FollowMode { Relaxed, Strict };
public BezierSpline spline;
public FollowMode followMode = FollowMode.Relaxed;
private Transform cachedTransform;
private ParticleSystem cachedPS;
private ParticleSystem.MainModule cachedMainModule;
private ParticleSystem.Particle[] particles;
private List<Vector4> particleData;
private void Awake()
{
cachedTransform = transform;
cachedPS = GetComponent<ParticleSystem>();
cachedMainModule = cachedPS.main;
particles = new ParticleSystem.Particle[cachedMainModule.maxParticles];
if( followMode == FollowMode.Relaxed )
particleData = new List<Vector4>( particles.Length );
}
#if UNITY_EDITOR
private void OnEnable()
{
Awake();
}
#endif
#if UNITY_EDITOR
private void LateUpdate()
{
if( !UnityEditor.EditorApplication.isPlaying )
FixedUpdate();
}
#endif
private void FixedUpdate()
{
if( spline == null || cachedPS == null )
return;
if( particles.Length < cachedMainModule.maxParticles && particles.Length < MAX_PARTICLE_COUNT )
System.Array.Resize( ref particles, Mathf.Min( cachedMainModule.maxParticles, MAX_PARTICLE_COUNT ) );
bool isLocalSpace = cachedMainModule.simulationSpace != ParticleSystemSimulationSpace.World;
int aliveParticles = cachedPS.GetParticles( particles );
Vector3 initialPoint = spline.GetPoint( 0f );
if( followMode == FollowMode.Relaxed )
{
if( particleData == null )
particleData = new List<Vector4>( particles.Length );
cachedPS.GetCustomParticleData( particleData, ParticleSystemCustomData.Custom1 );
// Credit: https://forum.unity3d.com/threads/access-to-the-particle-system-lifecycle-events.328918/#post-2295977
for( int i = 0; i < aliveParticles; i++ )
{
Vector4 particleDat = particleData[i];
Vector3 point = spline.GetPoint( 1f - ( particles[i].remainingLifetime / particles[i].startLifetime ) );
if( !isLocalSpace )
point = cachedTransform.TransformPoint( point - initialPoint );
// Move particles alongside the spline
if( particleDat.w != 0f )
particles[i].position += point - (Vector3) particleDat;
particleDat = point;
particleDat.w = 1f;
particleData[i] = particleDat;
}
cachedPS.SetCustomParticleData( particleData, ParticleSystemCustomData.Custom1 );
}
else
{
for( int i = 0; i < aliveParticles; i++ )
{
Vector3 point = spline.GetPoint( 1f - ( particles[i].remainingLifetime / particles[i].startLifetime ) ) - initialPoint;
if( !isLocalSpace )
point = cachedTransform.TransformPoint( point );
particles[i].position = point;
}
}
cachedPS.SetParticles( particles, aliveParticles );
}
}
}

View file

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 954f54b0dafe0cf488e4e15934cae013
timeCreated: 1510521621
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

View file

@ -0,0 +1,96 @@
fileFormatVersion: 2
guid: 55bb46a7614176b4c941a5caf846f7e8
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 11
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

View file

@ -534,6 +534,17 @@ AnimationClip:
path: Holder/LowerTorso path: Holder/LowerTorso
classID: 212 classID: 212
script: {fileID: 0} script: {fileID: 0}
- curve:
- time: 0
value: {fileID: -4339478730206458095, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3}
- time: 0.1
value: {fileID: -4756013695868691969, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3}
- time: 0.26666668
value: {fileID: -4901794926734046506, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3}
attribute: m_Sprite
path: Holder/Head
classID: 212
script: {fileID: 0}
m_SampleRate: 60 m_SampleRate: 60
m_WrapMode: 0 m_WrapMode: 0
m_Bounds: m_Bounds:
@ -653,6 +664,13 @@ AnimationClip:
typeID: 212 typeID: 212
customType: 23 customType: 23
isPPtrCurve: 1 isPPtrCurve: 1
- serializedVersion: 2
path: 862337961
attribute: 0
script: {fileID: 0}
typeID: 212
customType: 23
isPPtrCurve: 1
pptrCurveMapping: pptrCurveMapping:
- {fileID: 8448038167059441282, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} - {fileID: 8448038167059441282, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3}
- {fileID: -8827699967261475670, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} - {fileID: -8827699967261475670, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3}
@ -688,6 +706,9 @@ AnimationClip:
- {fileID: -1720273043946688001, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} - {fileID: -1720273043946688001, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3}
- {fileID: 3897377649561355716, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} - {fileID: 3897377649561355716, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3}
- {fileID: -1720273043946688001, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} - {fileID: -1720273043946688001, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3}
- {fileID: -4339478730206458095, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3}
- {fileID: -4756013695868691969, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3}
- {fileID: -4901794926734046506, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3}
m_AnimationClipSettings: m_AnimationClipSettings:
serializedVersion: 2 serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0} m_AdditiveReferencePoseClip: {fileID: 0}

View file

@ -525,6 +525,17 @@ AnimationClip:
path: Holder/LowerTorso path: Holder/LowerTorso
classID: 212 classID: 212
script: {fileID: 0} script: {fileID: 0}
- curve:
- time: 0
value: {fileID: -4339478730206458095, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3}
- time: 0.1
value: {fileID: -4756013695868691969, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3}
- time: 0.26666668
value: {fileID: -4901794926734046506, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3}
attribute: m_Sprite
path: Holder/Head
classID: 212
script: {fileID: 0}
m_SampleRate: 60 m_SampleRate: 60
m_WrapMode: 0 m_WrapMode: 0
m_Bounds: m_Bounds:
@ -637,6 +648,13 @@ AnimationClip:
typeID: 212 typeID: 212
customType: 23 customType: 23
isPPtrCurve: 1 isPPtrCurve: 1
- serializedVersion: 2
path: 862337961
attribute: 0
script: {fileID: 0}
typeID: 212
customType: 23
isPPtrCurve: 1
- serializedVersion: 2 - serializedVersion: 2
path: 354493626 path: 354493626
attribute: 1 attribute: 1
@ -679,6 +697,9 @@ AnimationClip:
- {fileID: -1720273043946688001, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} - {fileID: -1720273043946688001, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3}
- {fileID: 3897377649561355716, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} - {fileID: 3897377649561355716, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3}
- {fileID: -1720273043946688001, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} - {fileID: -1720273043946688001, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3}
- {fileID: -4339478730206458095, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3}
- {fileID: -4756013695868691969, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3}
- {fileID: -4901794926734046506, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3}
m_AnimationClipSettings: m_AnimationClipSettings:
serializedVersion: 2 serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0} m_AdditiveReferencePoseClip: {fileID: 0}

View file

@ -404,6 +404,22 @@ AnimationClip:
m_PostInfinity: 2 m_PostInfinity: 2
m_RotationOrder: 4 m_RotationOrder: 4
path: Holder/LowerTorso path: Holder/LowerTorso
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: {x: -2.36, y: -1.87, z: 0}
inSlope: {x: 0, y: 0, z: 0}
outSlope: {x: 0, y: 0, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0, y: 0.33333334, z: 0.33333334}
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
path: Holder/toeFX
m_ScaleCurves: [] m_ScaleCurves: []
m_FloatCurves: m_FloatCurves:
- curve: - curve:
@ -444,6 +460,34 @@ AnimationClip:
path: Holder/RightArm/Hand path: Holder/RightArm/Hand
classID: 1 classID: 1
script: {fileID: 0} script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: Infinity
outSlope: Infinity
tangentMode: 103
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 0.033333335
value: 0
inSlope: Infinity
outSlope: Infinity
tangentMode: 103
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_IsActive
path: Holder/toeFX
classID: 1
script: {fileID: 0}
m_PPtrCurves: m_PPtrCurves:
- curve: - curve:
- time: 0 - time: 0
@ -655,6 +699,13 @@ AnimationClip:
typeID: 1 typeID: 1
customType: 0 customType: 0
isPPtrCurve: 0 isPPtrCurve: 0
- serializedVersion: 2
path: 3009155107
attribute: 2086281974
script: {fileID: 0}
typeID: 1
customType: 0
isPPtrCurve: 0
- serializedVersion: 2 - serializedVersion: 2
path: 2827832259 path: 2827832259
attribute: 0 attribute: 0
@ -704,6 +755,13 @@ AnimationClip:
typeID: 212 typeID: 212
customType: 23 customType: 23
isPPtrCurve: 1 isPPtrCurve: 1
- serializedVersion: 2
path: 3009155107
attribute: 1
script: {fileID: 0}
typeID: 4
customType: 0
isPPtrCurve: 0
pptrCurveMapping: pptrCurveMapping:
- {fileID: 21300000, guid: c5b59e91368953049893b676adf67b31, type: 3} - {fileID: 21300000, guid: c5b59e91368953049893b676adf67b31, type: 3}
- {fileID: 21300000, guid: 90f0b2f80c7edac43b09f918f1ff580b, type: 3} - {fileID: 21300000, guid: 90f0b2f80c7edac43b09f918f1ff580b, type: 3}
@ -2052,6 +2110,91 @@ AnimationClip:
path: Holder/LowerTorso path: Holder/LowerTorso
classID: 4 classID: 4
script: {fileID: 0} script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: -2.36
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalPosition.x
path: Holder/toeFX
classID: 4
script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: -1.87
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalPosition.y
path: Holder/toeFX
classID: 4
script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalPosition.z
path: Holder/toeFX
classID: 4
script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: Infinity
outSlope: Infinity
tangentMode: 103
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 0.033333335
value: 0
inSlope: Infinity
outSlope: Infinity
tangentMode: 103
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_IsActive
path: Holder/toeFX
classID: 1
script: {fileID: 0}
m_EulerEditorCurves: m_EulerEditorCurves:
- curve: - curve:
serializedVersion: 2 serializedVersion: 2

View file

@ -433,6 +433,22 @@ AnimationClip:
m_PostInfinity: 2 m_PostInfinity: 2
m_RotationOrder: 4 m_RotationOrder: 4
path: Holder/Torso path: Holder/Torso
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: {x: -2.441, y: -1.702, z: 0}
inSlope: {x: 0, y: 0, z: 0}
outSlope: {x: 0, y: 0, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0, y: 0.33333334, z: 0.33333334}
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
path: Holder/toeFX
m_ScaleCurves: [] m_ScaleCurves: []
m_FloatCurves: m_FloatCurves:
- curve: - curve:
@ -473,6 +489,34 @@ AnimationClip:
path: Holder/RightArm/Hand path: Holder/RightArm/Hand
classID: 1 classID: 1
script: {fileID: 0} script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: Infinity
outSlope: Infinity
tangentMode: 103
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 0.033333335
value: 0
inSlope: Infinity
outSlope: Infinity
tangentMode: 103
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_IsActive
path: Holder/toeFX
classID: 1
script: {fileID: 0}
m_PPtrCurves: m_PPtrCurves:
- curve: - curve:
- time: 0 - time: 0
@ -679,6 +723,13 @@ AnimationClip:
typeID: 1 typeID: 1
customType: 0 customType: 0
isPPtrCurve: 0 isPPtrCurve: 0
- serializedVersion: 2
path: 3009155107
attribute: 2086281974
script: {fileID: 0}
typeID: 1
customType: 0
isPPtrCurve: 0
- serializedVersion: 2 - serializedVersion: 2
path: 862337961 path: 862337961
attribute: 0 attribute: 0
@ -728,6 +779,13 @@ AnimationClip:
typeID: 212 typeID: 212
customType: 23 customType: 23
isPPtrCurve: 1 isPPtrCurve: 1
- serializedVersion: 2
path: 3009155107
attribute: 1
script: {fileID: 0}
typeID: 4
customType: 0
isPPtrCurve: 0
pptrCurveMapping: pptrCurveMapping:
- {fileID: 1450434439674949499, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} - {fileID: 1450434439674949499, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3}
- {fileID: -2516537432793170592, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} - {fileID: -2516537432793170592, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3}
@ -2155,6 +2213,91 @@ AnimationClip:
path: Holder/Torso path: Holder/Torso
classID: 4 classID: 4
script: {fileID: 0} script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: -2.441
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalPosition.x
path: Holder/toeFX
classID: 4
script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: -1.702
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalPosition.y
path: Holder/toeFX
classID: 4
script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalPosition.z
path: Holder/toeFX
classID: 4
script: {fileID: 0}
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: Infinity
outSlope: Infinity
tangentMode: 103
weightedMode: 0
inWeight: 0
outWeight: 0
- serializedVersion: 3
time: 0.033333335
value: 0
inSlope: Infinity
outSlope: Infinity
tangentMode: 103
weightedMode: 0
inWeight: 0
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_IsActive
path: Holder/toeFX
classID: 1
script: {fileID: 0}
m_EulerEditorCurves: m_EulerEditorCurves:
- curve: - curve:
serializedVersion: 2 serializedVersion: 2

Binary file not shown.

Before

Width:  |  Height:  |  Size: 419 KiB

After

Width:  |  Height:  |  Size: 452 KiB

View file

@ -7,10 +7,10 @@ TextureImporter:
second: platform_0 second: platform_0
- first: - first:
213: -6047660829741247071 213: -6047660829741247071
second: platform_1 second: kick_fx
- first: - first:
213: -1664293819527379378 213: -1664293819527379378
second: platform_2 second: toe_fx
- first: - first:
213: -4901794926734046506 213: -4901794926734046506
second: kicker_head_0 second: kicker_head_0
@ -206,7 +206,7 @@ TextureImporter:
maxTextureSize: 2048 maxTextureSize: 2048
textureSettings: textureSettings:
serializedVersion: 2 serializedVersion: 2
filterMode: 1 filterMode: 0
aniso: 1 aniso: 1
mipBias: 0 mipBias: 0
wrapU: 1 wrapU: 1
@ -1452,6 +1452,48 @@ TextureImporter:
indices: indices:
edges: [] edges: []
weights: [] weights: []
- serializedVersion: 2
name: kick_fx
rect:
serializedVersion: 2
x: 532
y: 566
width: 184
height: 120
alignment: 0
pivot: {x: 0.5, y: 0.5}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: 1a59a396484621ca0800000000000000
internalID: -6047660829741247071
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: toe_fx
rect:
serializedVersion: 2
x: 720
y: 334
width: 241
height: 264
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: e464135c69d37e8e0800000000000000
internalID: -1664293819527379378
vertices: []
indices:
edges: []
weights: []
outline: [] outline: []
physicsShape: [] physicsShape: []
bones: [] bones: []

View file

@ -775,7 +775,7 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 1, y: 0.5} m_AnchorMin: {x: 1, y: 0.5}
m_AnchorMax: {x: 1, y: 0.5} m_AnchorMax: {x: 1, y: 0.5}
m_AnchoredPosition: {x: -50, y: 0} m_AnchoredPosition: {x: -95, y: 0}
m_SizeDelta: {x: 39.99997, y: 40} m_SizeDelta: {x: 39.99997, y: 40}
m_Pivot: {x: 1, y: 0.5} m_Pivot: {x: 1, y: 0.5}
--- !u!114 &121871281 --- !u!114 &121871281
@ -915,7 +915,7 @@ RectTransform:
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 1, y: 0.5} m_AnchorMin: {x: 1, y: 0.5}
m_AnchorMax: {x: 1, y: 0.5} m_AnchorMax: {x: 1, y: 0.5}
m_AnchoredPosition: {x: -5, y: 0} m_AnchoredPosition: {x: -50, y: 0}
m_SizeDelta: {x: 39.99997, y: 40} m_SizeDelta: {x: 39.99997, y: 40}
m_Pivot: {x: 1, y: 0.5} m_Pivot: {x: 1, y: 0.5}
--- !u!114 &129013734 --- !u!114 &129013734
@ -1000,6 +1000,139 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 129013732} m_GameObject: {fileID: 129013732}
m_CullTransparentMesh: 1 m_CullTransparentMesh: 1
--- !u!1 &151246936
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 151246937}
- component: {fileID: 151246940}
- component: {fileID: 151246939}
- component: {fileID: 151246938}
m_Layer: 5
m_Name: FullscreenBTN
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &151246937
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 151246936}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 1981150264}
m_Father: {fileID: 1709317943}
m_RootOrder: 5
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 1, y: 0.5}
m_AnchorMax: {x: 1, y: 0.5}
m_AnchoredPosition: {x: -5, y: 0}
m_SizeDelta: {x: 39.99997, y: 40}
m_Pivot: {x: 1, y: 0.5}
--- !u!114 &151246938
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 151246936}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
m_Mode: 0
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_PressedColor: {r: 0.7490196, g: 1, b: 1, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 151246939}
m_OnClick:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 1423699437}
m_TargetAssemblyTypeName: RhythmHeavenMania.Editor.Editor, Assembly-CSharp
m_MethodName: Fullscreen
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
--- !u!114 &151246939
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 151246936}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 10
--- !u!222 &151246940
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 151246936}
m_CullTransparentMesh: 1
--- !u!1 &151438063 --- !u!1 &151438063
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -9686,6 +9819,7 @@ MonoBehaviour:
MusicSelectBTN: {fileID: 1055877579} MusicSelectBTN: {fileID: 1055877579}
EditorSettingsBTN: {fileID: 3236232} EditorSettingsBTN: {fileID: 3236232}
EditorThemeBTN: {fileID: 528192061} EditorThemeBTN: {fileID: 528192061}
FullScreenBTN: {fileID: 151246938}
--- !u!114 &1423699438 --- !u!114 &1423699438
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -11116,6 +11250,7 @@ RectTransform:
- {fileID: 1783491358} - {fileID: 1783491358}
- {fileID: 121871280} - {fileID: 121871280}
- {fileID: 129013733} - {fileID: 129013733}
- {fileID: 151246937}
m_Father: {fileID: 1110073995} m_Father: {fileID: 1110073995}
m_RootOrder: 1 m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
@ -12655,6 +12790,81 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1964271230} m_GameObject: {fileID: 1964271230}
m_CullTransparentMesh: 1 m_CullTransparentMesh: 1
--- !u!1 &1981150263
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1981150264}
- component: {fileID: 1981150266}
- component: {fileID: 1981150265}
m_Layer: 5
m_Name: Graphic
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1981150264
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1981150263}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 151246937}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 40, y: 40}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1981150265
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1981150263}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.3254717, g: 1, b: 0.4334381, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: 55bb46a7614176b4c941a5caf846f7e8, type: 3}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!222 &1981150266
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1981150263}
m_CullTransparentMesh: 1
--- !u!1 &1997273392 --- !u!1 &1997273392
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -13047,8 +13257,7 @@ GameObject:
- component: {fileID: 2047408676} - component: {fileID: 2047408676}
- component: {fileID: 2047408675} - component: {fileID: 2047408675}
- component: {fileID: 2047408674} - component: {fileID: 2047408674}
- component: {fileID: 2047408677} - component: {fileID: 2047408679}
- component: {fileID: 2047408678}
m_Layer: 0 m_Layer: 0
m_Name: Main Camera m_Name: Main Camera
m_TagString: MainCamera m_TagString: MainCamera
@ -13121,7 +13330,7 @@ Transform:
m_Father: {fileID: 0} m_Father: {fileID: 0}
m_RootOrder: 0 m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &2047408677 --- !u!114 &2047408679
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0} m_CorrespondingSourceObject: {fileID: 0}
@ -13130,21 +13339,30 @@ MonoBehaviour:
m_GameObject: {fileID: 2047408673} m_GameObject: {fileID: 2047408673}
m_Enabled: 1 m_Enabled: 1
m_EditorHideFlags: 0 m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a66fbd5ffe9b9d64da304996f1919f40, type: 3} m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &2047408678
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2047408673}
m_Enabled: 0
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e55bddfe16e69224c8c4b4eb165695d4, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
m_RenderShadows: 1
m_RequiresDepthTextureOption: 2
m_RequiresOpaqueTextureOption: 2
m_CameraType: 0
m_Cameras: []
m_RendererIndex: -1
m_VolumeLayerMask:
serializedVersion: 2
m_Bits: 1
m_VolumeTrigger: {fileID: 0}
m_VolumeFrameworkUpdateModeOption: 2
m_RenderPostProcessing: 0
m_Antialiasing: 0
m_AntialiasingQuality: 2
m_StopNaN: 0
m_Dithering: 0
m_ClearDepth: 1
m_AllowXRRendering: 1
m_RequiresDepthTexture: 0
m_RequiresColorTexture: 0
m_Version: 2
--- !u!1 &2051557110 --- !u!1 &2051557110
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View file

@ -51,13 +51,13 @@ namespace RhythmHeavenMania
public void Init() public void Init()
{ {
this.transform.localScale = new Vector3(3000, 3000); this.transform.localScale = new Vector3(30000000, 30000000);
SpriteRenderer sp = this.gameObject.AddComponent<SpriteRenderer>(); SpriteRenderer sp = this.gameObject.AddComponent<SpriteRenderer>();
sp.enabled = false; sp.enabled = false;
sp.color = Color.black; sp.color = Color.black;
sp.sprite = Resources.Load<Sprite>("Sprites/GeneralPurpose/Square"); sp.sprite = Resources.Load<Sprite>("Sprites/GeneralPurpose/Square");
sp.sortingOrder = 30000; sp.sortingOrder = 30000;
this.gameObject.layer = 3; // this.gameObject.layer = 3;
if (txt != null) if (txt != null)
{ {

View file

@ -27,13 +27,14 @@ namespace RhythmHeavenMania.Games
autoPlayEnabledOnStart = GameManager.instance.autoplay; autoPlayEnabledOnStart = GameManager.instance.autoplay;
} }
private void CheckForAce(float normalizedBeat) private void CheckForAce(float normalizedBeat, bool autoPlay = false)
{ {
if (aceTimes == 0) if (aceTimes == 0)
{ {
if (GameManager.instance.autoplay && normalizedBeat > 0.99f) if (GameManager.instance.autoplay && normalizedBeat > 0.99f || autoPlay && normalizedBeat > 0.99f)
{ {
OnAce(); OnAce();
if (!autoPlay)
AceVisuals(); AceVisuals();
// aceTimes++; // aceTimes++;
} }
@ -52,9 +53,9 @@ namespace RhythmHeavenMania.Games
} }
// could possibly add support for custom early, perfect, and end times if needed. // could possibly add support for custom early, perfect, and end times if needed.
public void StateCheck(float normalizedBeat) public void StateCheck(float normalizedBeat, bool autoPlay = false)
{ {
CheckForAce(normalizedBeat); CheckForAce(normalizedBeat, autoPlay);
if (normalizedBeat > Minigame.EarlyTime() && normalizedBeat < Minigame.PerfectTime() && lastState == 0) if (normalizedBeat > Minigame.EarlyTime() && normalizedBeat < Minigame.PerfectTime() && lastState == 0)
{ {
MakeEligible(true, false, false); MakeEligible(true, false, false);

View file

@ -10,9 +10,10 @@ namespace RhythmHeavenMania.Games.SpaceSoccer
public class Ball : MonoBehaviour public class Ball : MonoBehaviour
{ {
[Header("Components")] [Header("Components")]
[SerializeField] private Kicker kicker; [HideInInspector] public Kicker kicker;
[SerializeField] private GameObject holder; [SerializeField] private GameObject holder;
[SerializeField] private GameObject spriteHolder; [SerializeField] private GameObject spriteHolder;
[SerializeField] private GameObject kickFX;
[Space(10)] [Space(10)]
[SerializeField] private BezierCurve3D dispenseCurve; [SerializeField] private BezierCurve3D dispenseCurve;
[SerializeField] private BezierCurve3D kickCurve; [SerializeField] private BezierCurve3D kickCurve;
@ -30,8 +31,13 @@ namespace RhythmHeavenMania.Games.SpaceSoccer
public GameEvent toe = new GameEvent(); public GameEvent toe = new GameEvent();
private bool lastKickLeft; private bool lastKickLeft;
public void Kick() private void Start()
{ {
}
public void Kick(bool player)
{
if (player)
Jukebox.PlayOneShotGame("spaceSoccer/ballHit"); Jukebox.PlayOneShotGame("spaceSoccer/ballHit");
lastSpriteRot = spriteHolder.transform.eulerAngles.z; lastSpriteRot = spriteHolder.transform.eulerAngles.z;
@ -54,6 +60,8 @@ namespace RhythmHeavenMania.Games.SpaceSoccer
kickCurve.transform.localScale = new Vector3(1, 1); kickCurve.transform.localScale = new Vector3(1, 1);
} }
kickCurve.KeyPoints[0].transform.position = holder.transform.position; kickCurve.KeyPoints[0].transform.position = holder.transform.position;
HitFX();
} }
public void HighKick() public void HighKick()
@ -68,6 +76,9 @@ namespace RhythmHeavenMania.Games.SpaceSoccer
highKicked.startBeat = Conductor.instance.songPositionInBeats; highKicked.startBeat = Conductor.instance.songPositionInBeats;
highKickCurve.KeyPoints[0].transform.position = holder.transform.position; highKickCurve.KeyPoints[0].transform.position = holder.transform.position;
HitFX();
} }
public void Toe() public void Toe()
@ -91,6 +102,9 @@ namespace RhythmHeavenMania.Games.SpaceSoccer
{ {
toeCurve.KeyPoints[1].transform.localPosition = new Vector3(6.49f, 0); toeCurve.KeyPoints[1].transform.localPosition = new Vector3(6.49f, 0);
} }
HitFX();
} }
private void Update() private void Update()
@ -98,6 +112,10 @@ namespace RhythmHeavenMania.Games.SpaceSoccer
if (dispensing) if (dispensing)
{ {
float normalizedBeatAnim = Conductor.instance.GetLoopPositionFromBeat(dispensedBeat, 2.35f); float normalizedBeatAnim = Conductor.instance.GetLoopPositionFromBeat(dispensedBeat, 2.35f);
dispenseCurve.KeyPoints[0].transform.position = new Vector3(kicker.transform.position.x - 6f, kicker.transform.position.y - 6f);
dispenseCurve.KeyPoints[1].transform.position = new Vector3(kicker.transform.position.x - 1f, kicker.transform.position.y - 6f);
holder.transform.localPosition = dispenseCurve.GetPoint(normalizedBeatAnim); holder.transform.localPosition = dispenseCurve.GetPoint(normalizedBeatAnim);
spriteHolder.transform.eulerAngles = new Vector3(0, 0, Mathf.Lerp(0f, -1440f, normalizedBeatAnim)); spriteHolder.transform.eulerAngles = new Vector3(0, 0, Mathf.Lerp(0f, -1440f, normalizedBeatAnim));
@ -112,16 +130,20 @@ namespace RhythmHeavenMania.Games.SpaceSoccer
else if (kicked.enabled) else if (kicked.enabled)
{ {
float normalizedBeatAnim = Conductor.instance.GetLoopPositionFromBeat(kicked.startBeat, 1.5f); float normalizedBeatAnim = Conductor.instance.GetLoopPositionFromBeat(kicked.startBeat, 1.5f);
holder.transform.localPosition = kickCurve.GetPoint(normalizedBeatAnim);
if (!lastKickLeft) if (!lastKickLeft)
{ {
kickCurve.KeyPoints[1].transform.position = new Vector3(kicker.transform.position.x + 0.5f, kicker.transform.position.y - 6f);
spriteHolder.transform.eulerAngles = new Vector3(0, 0, Mathf.Lerp(lastSpriteRot, lastSpriteRot - 360f, normalizedBeatAnim)); spriteHolder.transform.eulerAngles = new Vector3(0, 0, Mathf.Lerp(lastSpriteRot, lastSpriteRot - 360f, normalizedBeatAnim));
} }
else else
{ {
kickCurve.KeyPoints[1].transform.position = new Vector3(kicker.transform.position.x - 2.5f, kicker.transform.position.y - 6f);
spriteHolder.transform.eulerAngles = new Vector3(0, 0, Mathf.Lerp(lastSpriteRot, lastSpriteRot + 360f, normalizedBeatAnim)); spriteHolder.transform.eulerAngles = new Vector3(0, 0, Mathf.Lerp(lastSpriteRot, lastSpriteRot + 360f, normalizedBeatAnim));
} }
holder.transform.localPosition = kickCurve.GetPoint(normalizedBeatAnim);
/*if (PlayerInput.Pressed()) /*if (PlayerInput.Pressed())
{ {
if (state.perfect) if (state.perfect)
@ -141,6 +163,9 @@ namespace RhythmHeavenMania.Games.SpaceSoccer
else if (highKicked.enabled) else if (highKicked.enabled)
{ {
float normalizedBeatAnim = Conductor.instance.GetLoopPositionFromBeat(highKicked.startBeat, 1.8f); float normalizedBeatAnim = Conductor.instance.GetLoopPositionFromBeat(highKicked.startBeat, 1.8f);
highKickCurve.KeyPoints[1].transform.position = new Vector3(kicker.transform.position.x - 3.5f, kicker.transform.position.y - 6f);
holder.transform.localPosition = highKickCurve.GetPoint(normalizedBeatAnim); holder.transform.localPosition = highKickCurve.GetPoint(normalizedBeatAnim);
spriteHolder.transform.eulerAngles = new Vector3(0, 0, Mathf.Lerp(lastSpriteRot, lastSpriteRot + 360f, normalizedBeatAnim)); spriteHolder.transform.eulerAngles = new Vector3(0, 0, Mathf.Lerp(lastSpriteRot, lastSpriteRot + 360f, normalizedBeatAnim));
@ -165,9 +190,28 @@ namespace RhythmHeavenMania.Games.SpaceSoccer
else if (toe.enabled) else if (toe.enabled)
{ {
float normalizedBeatAnim = Conductor.instance.GetLoopPositionFromBeat(toe.startBeat, 1.85f); float normalizedBeatAnim = Conductor.instance.GetLoopPositionFromBeat(toe.startBeat, 1.85f);
if (!lastKickLeft)
{
toeCurve.KeyPoints[1].transform.position = new Vector3(kicker.transform.position.x + 0.5f, kicker.transform.position.y - 6f);
}
else
{
toeCurve.KeyPoints[1].transform.position = new Vector3(kicker.transform.position.x - 0.7f, kicker.transform.position.y - 6f);
}
holder.transform.localPosition = toeCurve.GetPoint(normalizedBeatAnim); holder.transform.localPosition = toeCurve.GetPoint(normalizedBeatAnim);
spriteHolder.transform.eulerAngles = new Vector3(0, 0, Mathf.Lerp(lastSpriteRot, -860f, normalizedBeatAnim)); spriteHolder.transform.eulerAngles = new Vector3(0, 0, Mathf.Lerp(lastSpriteRot, -860f, normalizedBeatAnim));
} }
holder.transform.position = new Vector3(holder.transform.position.x, holder.transform.position.y, kicker.transform.localPosition.z);
}
private void HitFX()
{
GameObject kickfx = Instantiate(kickFX.gameObject, SpaceSoccer.instance.transform);
kickfx.SetActive(true);
kickfx.transform.position = holder.transform.position;
} }
} }
} }

View file

@ -15,14 +15,27 @@ namespace RhythmHeavenMania.Games.SpaceSoccer
public bool kickLeft; public bool kickLeft;
public float dispenserBeat; public float dispenserBeat;
public int kickTimes = 0; public int kickTimes = 0;
public bool player;
[Header("Components")] [Header("Components")]
private Animator anim; private Animator anim;
public Ball ball; public Ball ball;
public Transform rightLeg;
public Transform leftLeg;
private void Start() private void Start()
{ {
anim = GetComponent<Animator>(); anim = GetComponent<Animator>();
GameObject rightLeg = new GameObject();
rightLeg.transform.SetParent(this.transform);
rightLeg.transform.position = new Vector3(-0.67f, -1.48f);
GameObject leftLeg = new GameObject("leftLeg");
leftLeg.transform.SetParent(this.transform);
leftLeg.transform.position = new Vector3(0f, -1.48f);
this.rightLeg = rightLeg.transform;
this.leftLeg = leftLeg.transform;
} }
public override void OnAce() public override void OnAce()
@ -56,6 +69,7 @@ namespace RhythmHeavenMania.Games.SpaceSoccer
kickTimes++; kickTimes++;
aceTimes = 0; aceTimes = 0;
if (player)
Jukebox.PlayOneShotGame("spaceSoccer/kick"); Jukebox.PlayOneShotGame("spaceSoccer/kick");
if (highKick) if (highKick)
@ -86,7 +100,7 @@ namespace RhythmHeavenMania.Games.SpaceSoccer
if (highKick == false) if (highKick == false)
{ {
if (ball != null && hit) if (ball != null && hit)
ball.Kick(); ball.Kick(player);
} }
else else
{ {
@ -109,13 +123,16 @@ namespace RhythmHeavenMania.Games.SpaceSoccer
anim.Play("HighKickRight_0", 0, 0); anim.Play("HighKickRight_0", 0, 0);
} }
if (ball && hit) if (hit && ball)
{ {
Jukebox.PlayOneShotGame("spaceSoccer/highkicktoe1_hit");
ball.HighKick(); ball.HighKick();
if (player)
Jukebox.PlayOneShotGame("spaceSoccer/highkicktoe1_hit");
} }
else else
{ {
if (player)
Jukebox.PlayOneShotGame("spaceSoccer/highkicktoe1"); Jukebox.PlayOneShotGame("spaceSoccer/highkicktoe1");
} }
@ -133,15 +150,20 @@ namespace RhythmHeavenMania.Games.SpaceSoccer
anim.Play("ToeRight", 0, 0); anim.Play("ToeRight", 0, 0);
} }
if (player)
{
if (hit && ball) if (hit && ball)
{ {
Jukebox.PlayOneShotGame("spaceSoccer/highkicktoe3_hit"); Jukebox.PlayOneShotGame("spaceSoccer/highkicktoe3_hit");
ball.Toe();
} }
else else
{ {
Jukebox.PlayOneShotGame("spaceSoccer/highkicktoe3"); Jukebox.PlayOneShotGame("spaceSoccer/highkicktoe3");
} }
}
if (hit && ball)
ball.Toe();
kickPrepare = false; kickPrepare = false;
ResetState(); ResetState();
@ -149,7 +171,6 @@ namespace RhythmHeavenMania.Games.SpaceSoccer
private void Update() private void Update()
{ {
if (kickTimes % 2 == 0) if (kickTimes % 2 == 0)
{ {
kickLeft = false; kickLeft = false;
@ -193,9 +214,11 @@ namespace RhythmHeavenMania.Games.SpaceSoccer
if (ball.dispensing) if (ball.dispensing)
{ {
float normalizedBeat = Conductor.instance.GetLoopPositionFromBeat(ball.dispensedBeat, 2f); float normalizedBeat = Conductor.instance.GetLoopPositionFromBeat(ball.dispensedBeat, 2f);
StateCheck(normalizedBeat); StateCheck(normalizedBeat, !player);
CheckIfFall(normalizedBeat); CheckIfFall(normalizedBeat);
if (player)
{
if (PlayerInput.Pressed()) if (PlayerInput.Pressed())
{ {
if (state.perfect) if (state.perfect)
@ -208,12 +231,15 @@ namespace RhythmHeavenMania.Games.SpaceSoccer
} }
} }
} }
}
else if (ball.kicked.enabled) else if (ball.kicked.enabled)
{ {
float normalizedBeat = Conductor.instance.GetLoopPositionFromBeat(ball.kicked.startBeat, 1f); float normalizedBeat = Conductor.instance.GetLoopPositionFromBeat(ball.kicked.startBeat, 1f);
StateCheck(normalizedBeat); StateCheck(normalizedBeat, !player);
CheckIfFall(normalizedBeat); CheckIfFall(normalizedBeat);
if (player)
{
if (PlayerInput.Pressed()) if (PlayerInput.Pressed())
{ {
if (state.perfect) if (state.perfect)
@ -226,25 +252,31 @@ namespace RhythmHeavenMania.Games.SpaceSoccer
} }
} }
} }
}
else if (ball.highKicked.enabled) else if (ball.highKicked.enabled)
{ {
float normalizedBeat = Conductor.instance.GetLoopPositionFromBeat(ball.highKicked.startBeat, 1.5f); float normalizedBeat = Conductor.instance.GetLoopPositionFromBeat(ball.highKicked.startBeat, 1.5f);
if (!kickPrepare) if (!kickPrepare)
{ {
float normalizedBeatPrepare = Conductor.instance.GetLoopPositionFromBeat(ball.highKicked.startBeat, 1f); float normalizedBeatPrepare = Conductor.instance.GetLoopPositionFromBeat(ball.highKicked.startBeat, 1f);
StateCheck(normalizedBeatPrepare); StateCheck(normalizedBeatPrepare, !player);
CheckIfFall(normalizedBeat); CheckIfFall(normalizedBeat);
if (player)
{
if (PlayerInput.AltPressed()) if (PlayerInput.AltPressed())
{ {
Kick(false, true); Kick(false, true);
} }
} }
}
else else
{ {
StateCheck(normalizedBeat); StateCheck(normalizedBeat, !player);
CheckIfFall(normalizedBeat); CheckIfFall(normalizedBeat);
if (player)
{
if (PlayerInput.AltPressedUp()) if (PlayerInput.AltPressedUp())
{ {
if (state.perfect) if (state.perfect)
@ -258,12 +290,15 @@ namespace RhythmHeavenMania.Games.SpaceSoccer
} }
} }
} }
}
else if (ball.toe.enabled) else if (ball.toe.enabled)
{ {
float normalizedBeat = Conductor.instance.GetLoopPositionFromBeat(ball.toe.startBeat, 1.5f); float normalizedBeat = Conductor.instance.GetLoopPositionFromBeat(ball.toe.startBeat, 1.5f);
StateCheck(normalizedBeat); StateCheck(normalizedBeat, !player);
CheckIfFall(normalizedBeat); CheckIfFall(normalizedBeat);
if (player)
{
if (PlayerInput.Pressed()) if (PlayerInput.Pressed())
{ {
if (state.perfect) if (state.perfect)
@ -277,7 +312,10 @@ namespace RhythmHeavenMania.Games.SpaceSoccer
} }
} }
} }
}
else else
{
if (player)
{ {
if (PlayerInput.Pressed()) if (PlayerInput.Pressed())
{ {
@ -285,6 +323,7 @@ namespace RhythmHeavenMania.Games.SpaceSoccer
} }
} }
} }
}
private void KickCheck(bool hit, bool overrideState = false) private void KickCheck(bool hit, bool overrideState = false)
{ {

View file

@ -10,7 +10,7 @@ namespace RhythmHeavenMania.Games.SpaceSoccer
{ {
[Header("Components")] [Header("Components")]
[SerializeField] private GameObject ballRef; [SerializeField] private GameObject ballRef;
[SerializeField] private Kicker kicker; [SerializeField] private List<Kicker> kickers;
[SerializeField] private GameObject Background; [SerializeField] private GameObject Background;
[SerializeField] private Sprite[] backgroundSprite; [SerializeField] private Sprite[] backgroundSprite;
@ -26,7 +26,7 @@ namespace RhythmHeavenMania.Games.SpaceSoccer
private void Start() private void Start()
{ {
for (int x = 0; x < Random.Range(9, 12); x++) /*for (int x = 0; x < Random.Range(9, 12); x++)
{ {
for (int y = 0; y < Random.Range(6, 9); y++) for (int y = 0; y < Random.Range(6, 9); y++)
{ {
@ -37,7 +37,7 @@ namespace RhythmHeavenMania.Games.SpaceSoccer
test.transform.localPosition = new Vector3(Random.Range(-15f, 15f), Random.Range(-15f, 15f)); test.transform.localPosition = new Vector3(Random.Range(-15f, 15f), Random.Range(-15f, 15f));
test.transform.localScale = new Vector3(0.52f, 0.52f); test.transform.localScale = new Vector3(0.52f, 0.52f);
} }
} }*/
} }
private void Update() private void Update()
@ -45,22 +45,27 @@ namespace RhythmHeavenMania.Games.SpaceSoccer
if (ballDispensed) if (ballDispensed)
{ {
} }
} }
public void Dispense(float beat) public void Dispense(float beat)
{ {
for (int i = 0; i < kickers.Count; i++)
{
Kicker kicker = kickers[i];
if (i == 0) kicker.player = true;
if (kicker.ball != null) return; if (kicker.ball != null) return;
ballDispensed = true; ballDispensed = true;
GameObject ball = Instantiate(ballRef, this.transform); GameObject ball = Instantiate(ballRef, transform);
Ball ball_ = ball.GetComponent<Ball>(); Ball ball_ = ball.GetComponent<Ball>();
ball_.kicker = kicker;
ball_.dispensedBeat = beat; ball_.dispensedBeat = beat;
ball_.dispensing = true; ball_.dispensing = true;
kicker.ball = ball_; kicker.ball = ball_;
kicker.dispenserBeat = beat; kicker.dispenserBeat = beat;
kicker.kickTimes = 0; kicker.kickTimes = 0;
}
MultiSound.Play(new MultiSound.Sound[] MultiSound.Play(new MultiSound.Sound[]
{ {

View file

@ -46,11 +46,13 @@ namespace RhythmHeavenMania.Editor
[SerializeField] private Button MusicSelectBTN; [SerializeField] private Button MusicSelectBTN;
[SerializeField] private Button EditorSettingsBTN; [SerializeField] private Button EditorSettingsBTN;
[SerializeField] private Button EditorThemeBTN; [SerializeField] private Button EditorThemeBTN;
[SerializeField] private Button FullScreenBTN;
[Header("Properties")] [Header("Properties")]
private bool changedMusic = false; private bool changedMusic = false;
private string currentRemixPath = ""; private string currentRemixPath = "";
private int lastEditorObjectsCount = 0; private int lastEditorObjectsCount = 0;
private bool fullscreen;
public static Editor instance { get; private set; } public static Editor instance { get; private set; }
@ -85,6 +87,7 @@ namespace RhythmHeavenMania.Editor
Tooltip.AddTooltip(MusicSelectBTN.gameObject, "Music Select"); Tooltip.AddTooltip(MusicSelectBTN.gameObject, "Music Select");
Tooltip.AddTooltip(EditorSettingsBTN.gameObject, "Editor Settings <color=#adadad>[Ctrl+Shift+O]</color>"); Tooltip.AddTooltip(EditorSettingsBTN.gameObject, "Editor Settings <color=#adadad>[Ctrl+Shift+O]</color>");
Tooltip.AddTooltip(EditorThemeBTN.gameObject, "Editor Theme"); Tooltip.AddTooltip(EditorThemeBTN.gameObject, "Editor Theme");
Tooltip.AddTooltip(FullScreenBTN.gameObject, "Preview <color=#adadad>[Tab]</color>");
UpdateEditorStatus(true); UpdateEditorStatus(true);
} }
@ -105,6 +108,11 @@ namespace RhythmHeavenMania.Editor
GetComponent<BoxSelection>().enabled = true; GetComponent<BoxSelection>().enabled = true;
}*/ }*/
if (Input.GetKeyDown(KeyCode.Tab))
{
Fullscreen();
}
if (Input.GetKeyDown(KeyCode.Delete)) if (Input.GetKeyDown(KeyCode.Delete))
{ {
List<TimelineEventObj> ev = new List<TimelineEventObj>(); List<TimelineEventObj> ev = new List<TimelineEventObj>();
@ -368,6 +376,25 @@ namespace RhythmHeavenMania.Editor
#endregion #endregion
public void Fullscreen()
{
if (fullscreen == false)
{
MainCanvas.enabled = false;
EditorCamera.enabled = false;
GameManager.instance.GameCamera.targetTexture = null;
// GameManager.instance.GameCamera.transform.parent.GetChild(1).GetComponent<Camera>().enabled = false;
fullscreen = true;
}
else
{
MainCanvas.enabled = true;
EditorCamera.enabled = true;
GameManager.instance.GameCamera.targetTexture = ScreenRenderTexture;
// GameManager.instance.GameCamera.transform.parent.GetChild(1).GetComponent<Camera>().enabled = true;
fullscreen = false;
}
}
private void UpdateEditorStatus(bool updateTime) private void UpdateEditorStatus(bool updateTime)
{ {

View file

@ -39,7 +39,7 @@ GraphicsSettings:
- {fileID: 10783, guid: 0000000000000000f000000000000000, type: 0} - {fileID: 10783, guid: 0000000000000000f000000000000000, type: 0}
m_PreloadedShaders: [] m_PreloadedShaders: []
m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0}
m_CustomRenderPipeline: {fileID: 11400000, guid: 101cb6f0eda36514fa0bb49e41c8fae1, type: 2} m_CustomRenderPipeline: {fileID: 0}
m_TransparencySortMode: 0 m_TransparencySortMode: 0
m_TransparencySortAxis: {x: 0, y: 0, z: 1} m_TransparencySortAxis: {x: 0, y: 0, z: 1}
m_DefaultRenderingPath: 1 m_DefaultRenderingPath: 1