9 namespace Valve.VR.InteractionSystem
14 public int segmentCount = 60;
15 public float thickness = 0.01f;
17 [Tooltip(
"The amount of time in seconds to predict the motion of the projectile." )]
18 public float arcDuration = 3.0f;
20 [Tooltip(
"The amount of time in seconds between each segment of the projectile." )]
21 public float segmentBreak = 0.025f;
23 [Tooltip(
"The speed at which the line segments of the arc move." )]
24 public float arcSpeed = 0.2f;
26 public Material material;
29 public int traceLayerMask = 0;
32 private LineRenderer[] lineRenderers;
33 private float arcTimeOffset = 0.0f;
34 private float prevThickness = 0.0f;
35 private int prevSegmentCount = 0;
36 private bool showArc =
true;
37 private Vector3 startPos;
38 private Vector3 projectileVelocity;
39 private bool useGravity =
true;
40 private Transform arcObjectsTransfrom;
41 private bool arcInvalid =
false;
47 arcTimeOffset = Time.time;
54 if ( thickness != prevThickness || segmentCount != prevSegmentCount )
56 CreateLineRendererObjects();
57 prevThickness = thickness;
58 prevSegmentCount = segmentCount;
64 private void CreateLineRendererObjects()
67 if ( arcObjectsTransfrom != null )
69 Destroy( arcObjectsTransfrom.gameObject );
72 GameObject arcObjectsParent =
new GameObject(
"ArcObjects" );
73 arcObjectsTransfrom = arcObjectsParent.transform;
74 arcObjectsTransfrom.SetParent( this.transform );
77 lineRenderers =
new LineRenderer[segmentCount];
78 for (
int i = 0; i < segmentCount; ++i )
80 GameObject newObject =
new GameObject(
"LineRenderer_" + i );
81 newObject.transform.SetParent( arcObjectsTransfrom );
83 lineRenderers[i] = newObject.AddComponent<LineRenderer>();
85 lineRenderers[i].receiveShadows =
false;
86 lineRenderers[i].reflectionProbeUsage = UnityEngine.Rendering.ReflectionProbeUsage.Off;
87 lineRenderers[i].lightProbeUsage = UnityEngine.Rendering.LightProbeUsage.Off;
88 lineRenderers[i].shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
89 lineRenderers[i].material = material;
91 lineRenderers[i].SetWidth( thickness, thickness );
93 lineRenderers[i].startWidth = thickness;
94 lineRenderers[i].endWidth = thickness;
96 lineRenderers[i].enabled =
false;
102 public void SetArcData( Vector3 position, Vector3 velocity,
bool gravity,
bool pointerAtBadAngle )
105 projectileVelocity = velocity;
106 useGravity = gravity;
108 if ( arcInvalid && !pointerAtBadAngle )
110 arcTimeOffset = Time.time;
112 arcInvalid = pointerAtBadAngle;
120 if ( lineRenderers == null )
122 CreateLineRendererObjects();
133 HideLineSegments( 0, segmentCount );
142 public bool DrawArc( out RaycastHit hitInfo )
144 float timeStep = arcDuration / segmentCount;
146 float currentTimeOffset = ( Time.time - arcTimeOffset ) * arcSpeed;
149 if ( currentTimeOffset > ( timeStep + segmentBreak ) )
151 arcTimeOffset = Time.time;
152 currentTimeOffset = 0.0f;
155 float segmentStartTime = currentTimeOffset;
157 float arcHitTime = FindProjectileCollision( out hitInfo );
162 lineRenderers[0].enabled =
true;
163 lineRenderers[0].SetPosition( 0, GetArcPositionAtTime( 0.0f ) );
164 lineRenderers[0].SetPosition( 1, GetArcPositionAtTime( arcHitTime < timeStep ? arcHitTime : timeStep ) );
166 HideLineSegments( 1, segmentCount );
171 int loopStartSegment = 0;
172 if ( segmentStartTime > segmentBreak )
174 float firstSegmentEndTime = currentTimeOffset - segmentBreak;
175 if ( arcHitTime < firstSegmentEndTime )
177 firstSegmentEndTime = arcHitTime;
179 DrawArcSegment( 0, 0.0f, firstSegmentEndTime );
181 loopStartSegment = 1;
184 bool stopArc =
false;
185 int currentSegment = 0;
186 if ( segmentStartTime < arcHitTime )
188 for ( currentSegment = loopStartSegment; currentSegment < segmentCount; ++currentSegment )
191 float segmentEndTime = segmentStartTime + timeStep;
192 if ( segmentEndTime >= arcDuration )
194 segmentEndTime = arcDuration;
198 if ( segmentEndTime >= arcHitTime )
200 segmentEndTime = arcHitTime;
204 DrawArcSegment( currentSegment, segmentStartTime, segmentEndTime );
206 segmentStartTime += timeStep + segmentBreak;
209 if ( stopArc || segmentStartTime >= arcDuration || segmentStartTime >= arcHitTime )
221 HideLineSegments( currentSegment + 1, segmentCount );
224 return arcHitTime != float.MaxValue;
229 private void DrawArcSegment(
int index,
float startTime,
float endTime )
231 lineRenderers[index].enabled =
true;
232 lineRenderers[index].SetPosition( 0, GetArcPositionAtTime( startTime ) );
233 lineRenderers[index].SetPosition( 1, GetArcPositionAtTime( endTime ) );
238 public void SetColor( Color color )
240 for (
int i = 0; i < segmentCount; ++i )
243 lineRenderers[i].SetColors( color, color );
245 lineRenderers[i].startColor = color;
246 lineRenderers[i].endColor = color;
253 private float FindProjectileCollision( out RaycastHit hitInfo )
255 float timeStep = arcDuration / segmentCount;
256 float segmentStartTime = 0.0f;
258 hitInfo =
new RaycastHit();
260 Vector3 segmentStartPos = GetArcPositionAtTime( segmentStartTime );
261 for (
int i = 0; i < segmentCount; ++i )
263 float segmentEndTime = segmentStartTime + timeStep;
264 Vector3 segmentEndPos = GetArcPositionAtTime( segmentEndTime );
266 if ( Physics.Linecast( segmentStartPos, segmentEndPos, out hitInfo, traceLayerMask ) )
270 Util.DrawCross( hitInfo.point, Color.red, 0.5f );
271 float segmentDistance = Vector3.Distance( segmentStartPos, segmentEndPos );
272 float hitTime = segmentStartTime + ( timeStep * ( hitInfo.distance / segmentDistance ) );
277 segmentStartTime = segmentEndTime;
278 segmentStartPos = segmentEndPos;
281 return float.MaxValue;
286 public Vector3 GetArcPositionAtTime(
float time )
288 Vector3 gravity = useGravity ? Physics.gravity : Vector3.zero;
290 Vector3 arcPos = startPos + ( ( projectileVelocity * time ) + ( 0.5f * time * time ) * gravity );
296 private void HideLineSegments(
int startSegment,
int endSegment )
298 if ( lineRenderers != null )
300 for (
int i = startSegment; i < endSegment; ++i )
302 lineRenderers[i].enabled =
false;