Created
August 28, 2017 17:59
-
-
Save mandarinx/1d57dc7d1afd2c92d57eab5c0e60d251 to your computer and use it in GitHub Desktop.
Trails
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
// tester part here, scroll for smartTrail class | |
public class testSmartTrail : MonoBehaviour { | |
[Header("Line parameters")] | |
public float maxDuration=1.5f; | |
public float maxDistance=8; | |
public float minStepDistance=.0625f; | |
[Space] | |
public bool update=true; | |
public bool step; | |
float tm; | |
float stepTime; | |
smartTrail trail; | |
public bool useLineRenderer = true; | |
LineRenderer lr; | |
void Reset(){ | |
trail = null; | |
} | |
void OnValidate(){ | |
maxDistance = Mathf.Max(maxDistance, 0); | |
maxDuration = Mathf.Max(maxDuration, 0); | |
minStepDistance = Mathf.Max(minStepDistance, 0); | |
trail.setParams(maxDistance,maxDuration,minStepDistance); | |
} | |
void OnDrawGizmos(){ | |
if(trail==null || trail.lPoints.Count==0) | |
trail = new smartTrail(maxDistance, maxDuration, minStepDistance); | |
float dt = Mathf.Clamp(time-tm, 0, .03f); | |
tm = time; | |
bool ends=false; // only first or last point's position changed, can be used for optimization | |
bool full=false; // have to reapply whole array | |
if(update || step){ | |
stepTime += dt; | |
if(step) {update=false; step=false;} | |
trail.updateLine(transform.position, time, out ends, out full); | |
} | |
// draw it | |
if(useLineRenderer){ | |
if(lr==null) | |
lr = gameObject.AddComponent<LineRenderer>(); | |
lr.positionCount = trail.lPoints.Count; | |
for(int p=0;p<lr.positionCount;p++) | |
lr.SetPosition(p, trail.lPoints[p]); | |
}else{ | |
var exLR = GetComponent<LineRenderer>(); | |
DestroyImmediate(exLR); | |
} | |
} | |
public static float time {get{ | |
#if UNITY_EDITOR | |
if(!Application.isPlaying) | |
return (float)UnityEditor.EditorApplication.timeSinceStartup; | |
#endif | |
return Time.time; | |
}} | |
} | |
// smart trail class can be in its own .CS file | |
[System.Serializable] | |
public class smartTrail { | |
float maxDistance, maxDuration, minStepDistance, minStepDistanceSQ; | |
public List<Vector2> lPoints; | |
List<float> lTimes; | |
float curLength; | |
Vector2 lastAddedPoint; | |
bool hasLast; | |
public smartTrail(float maxDistance, float maxDuration, float minStepDistance=.0625f){ | |
setParams(maxDistance,maxDuration,minStepDistance); | |
} | |
public void setParams(float maxDistance, float maxDuration, float minStepDistance=.0625f){ | |
this.maxDistance = maxDistance; | |
this.maxDuration = maxDuration; | |
this.minStepDistance = minStepDistance; | |
minStepDistanceSQ = minStepDistance*minStepDistance; | |
} | |
public void updateLine(Vector2 point, float now, out bool endUpd, out bool fullUpd){ | |
endUpd = false; | |
fullUpd = false; | |
if(lPoints==null || lPoints.Count==0) { | |
lPoints = new List<Vector2>(){point}; | |
lTimes = new List<float>(){now}; | |
hasLast = true; | |
lastAddedPoint = point; | |
curLength = 0; | |
return; | |
} | |
float newAddDist = 0; | |
Vector2 lastPoint = lPoints[lPoints.Count-1]; | |
newAddDist = ((hasLast ? lastAddedPoint : lastPoint) - point).sqrMagnitude; | |
if(newAddDist<minStepDistanceSQ){ | |
lPoints[lPoints.Count-1] = point; | |
lTimes[lPoints.Count-1] = now; | |
endUpd = (lastPoint-point).sqrMagnitude>.1f; | |
if(lPoints.Count>1 && clipDuration(ref fullUpd)) | |
endUpd = true; | |
return; | |
} | |
newAddDist = Mathf.Sqrt(newAddDist); | |
curLength += newAddDist; | |
lastAddedPoint = point; | |
lPoints.Add(point); | |
lTimes.Add(now); | |
hasLast = true; | |
endUpd = true; | |
clipDuration(ref fullUpd); | |
clipLength(); | |
fullUpd = true; | |
} | |
void clipLength(){ | |
if(lPoints.Count<2) return; | |
float extraLength = curLength - maxDistance; | |
if(extraLength<0) return; | |
//safety | |
int lTries = 10000; | |
while(extraLength>0){ | |
lTries--; if(lTries==0) return; | |
Vector2 lastDir = lPoints[1]-lPoints[0]; | |
float lastDist = lastDir.magnitude; | |
if(lastDist<extraLength && lPoints.Count>2){ | |
lPoints.RemoveAt(0); | |
lTimes.RemoveAt(0); | |
extraLength -= lastDist; | |
curLength -= lastDist; | |
}else{ | |
lPoints[0] += lastDir.normalized * extraLength; | |
curLength -= extraLength; | |
extraLength = 0; | |
} | |
} | |
} | |
bool clipDuration(ref bool fullUpd){ | |
float lineDuration = lTimes[lTimes.Count-1] - lTimes[0]; | |
if(lineDuration>maxDuration){ | |
float extra = lineDuration - maxDuration; | |
int dTries = 10000; | |
while(extra>0 && lPoints.Count>1 && curLength>minStepDistance){ | |
dTries--; if(dTries==0) return true; | |
Vector2 dir = lPoints[1] - lPoints[0]; | |
float dur = lTimes[1] - lTimes[0]; | |
float dist = dir.magnitude; | |
fullUpd = true; | |
lPoints.RemoveAt(0); | |
lTimes.RemoveAt(0); | |
curLength = Mathf.Max(curLength - dist, minStepDistance); | |
extra -= dur; | |
} | |
return true; | |
} | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment