123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- //======= Copyright (c) Valve Corporation, All rights reserved. ===============
- //
- // Purpose: Displays the arc lines for teleporting and does the traces
- //
- //=============================================================================
- using UnityEngine;
- namespace Valve.VR.InteractionSystem
- {
- //-------------------------------------------------------------------------
- public class TeleportArc : MonoBehaviour
- {
- public int segmentCount = 60;
- public float thickness = 0.01f;
- [Tooltip("The amount of time in seconds to predict the motion of the projectile.")]
- public float arcDuration = 3.0f;
- [Tooltip("The amount of time in seconds between each segment of the projectile.")]
- public float segmentBreak = 0.025f;
- [Tooltip("The speed at which the line segments of the arc move.")]
- public float arcSpeed = 0.2f;
- public Material material;
- [HideInInspector]
- public int traceLayerMask = 0;
- //Private data
- private LineRenderer[] lineRenderers;
- private float arcTimeOffset = 0.0f;
- private float prevThickness = 0.0f;
- private int prevSegmentCount = 0;
- private bool showArc = true;
- private Vector3 startPos;
- private Vector3 projectileVelocity;
- private bool useGravity = true;
- private Transform arcObjectsTransfrom;
- private bool arcInvalid = false;
- private float scale = 1;
- //-------------------------------------------------
- void Start()
- {
- arcTimeOffset = Time.time;
- }
- //-------------------------------------------------
- void Update()
- {
- //scale arc to match player scale
- scale = Player.instance.transform.lossyScale.x;
- if (thickness != prevThickness || segmentCount != prevSegmentCount)
- {
- CreateLineRendererObjects();
- prevThickness = thickness;
- prevSegmentCount = segmentCount;
- }
- }
- //-------------------------------------------------
- private void CreateLineRendererObjects()
- {
- //Destroy any existing line renderer objects
- if (arcObjectsTransfrom != null)
- {
- Destroy(arcObjectsTransfrom.gameObject);
- }
- GameObject arcObjectsParent = new GameObject("ArcObjects");
- arcObjectsTransfrom = arcObjectsParent.transform;
- arcObjectsTransfrom.SetParent(this.transform);
- //Create new line renderer objects
- lineRenderers = new LineRenderer[segmentCount];
- for (int i = 0; i < segmentCount; ++i)
- {
- GameObject newObject = new GameObject("LineRenderer_" + i);
- newObject.transform.SetParent(arcObjectsTransfrom);
- lineRenderers[i] = newObject.AddComponent<LineRenderer>();
- lineRenderers[i].receiveShadows = false;
- lineRenderers[i].reflectionProbeUsage = UnityEngine.Rendering.ReflectionProbeUsage.Off;
- lineRenderers[i].lightProbeUsage = UnityEngine.Rendering.LightProbeUsage.Off;
- lineRenderers[i].shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
- lineRenderers[i].material = material;
- #if (UNITY_5_4)
- lineRenderers[i].SetWidth(thickness, thickness);
- #else
- lineRenderers[i].startWidth = thickness * scale;
- lineRenderers[i].endWidth = thickness * scale;
- #endif
- lineRenderers[i].enabled = false;
- }
- }
- //-------------------------------------------------
- public void SetArcData(Vector3 position, Vector3 velocity, bool gravity, bool pointerAtBadAngle)
- {
- startPos = position;
- projectileVelocity = velocity;
- useGravity = gravity;
- if (arcInvalid && !pointerAtBadAngle)
- {
- arcTimeOffset = Time.time;
- }
- arcInvalid = pointerAtBadAngle;
- }
- //-------------------------------------------------
- public void Show()
- {
- showArc = true;
- if (lineRenderers == null)
- {
- CreateLineRendererObjects();
- }
- }
- //-------------------------------------------------
- public void Hide()
- {
- //Hide the line segments if they were previously being shown
- if (showArc)
- {
- HideLineSegments(0, segmentCount);
- }
- showArc = false;
- }
- //-------------------------------------------------
- // Draws each segment of the arc individually
- //-------------------------------------------------
- public bool DrawArc(out RaycastHit hitInfo)
- {
- float timeStep = arcDuration / segmentCount;
- float currentTimeOffset = (Time.time - arcTimeOffset) * arcSpeed;
- //Reset the arc time offset when it has gone beyond a segment length
- if (currentTimeOffset > (timeStep + segmentBreak))
- {
- arcTimeOffset = Time.time;
- currentTimeOffset = 0.0f;
- }
- float segmentStartTime = currentTimeOffset;
- float arcHitTime = FindProjectileCollision(out hitInfo);
- if (arcInvalid)
- {
- //Only draw first segment
- lineRenderers[0].enabled = true;
- lineRenderers[0].SetPosition(0, GetArcPositionAtTime(0.0f));
- lineRenderers[0].SetPosition(1, GetArcPositionAtTime(arcHitTime < timeStep ? arcHitTime : timeStep));
- HideLineSegments(1, segmentCount);
- }
- else
- {
- //Draw the first segment outside the loop if needed
- int loopStartSegment = 0;
- if (segmentStartTime > segmentBreak)
- {
- float firstSegmentEndTime = currentTimeOffset - segmentBreak;
- if (arcHitTime < firstSegmentEndTime)
- {
- firstSegmentEndTime = arcHitTime;
- }
- DrawArcSegment(0, 0.0f, firstSegmentEndTime);
- loopStartSegment = 1;
- }
- bool stopArc = false;
- int currentSegment = 0;
- if (segmentStartTime < arcHitTime)
- {
- for (currentSegment = loopStartSegment; currentSegment < segmentCount; ++currentSegment)
- {
- //Clamp the segment end time to the arc duration
- float segmentEndTime = segmentStartTime + timeStep;
- if (segmentEndTime >= arcDuration)
- {
- segmentEndTime = arcDuration;
- stopArc = true;
- }
- if (segmentEndTime >= arcHitTime)
- {
- segmentEndTime = arcHitTime;
- stopArc = true;
- }
- DrawArcSegment(currentSegment, segmentStartTime, segmentEndTime);
- segmentStartTime += timeStep + segmentBreak;
- //If the previous end time or the next start time is beyond the duration then stop the arc
- if (stopArc || segmentStartTime >= arcDuration || segmentStartTime >= arcHitTime)
- {
- break;
- }
- }
- }
- else
- {
- currentSegment--;
- }
- //Hide the rest of the line segments
- HideLineSegments(currentSegment + 1, segmentCount);
- }
- return arcHitTime != float.MaxValue;
- }
- //-------------------------------------------------
- private void DrawArcSegment(int index, float startTime, float endTime)
- {
- lineRenderers[index].enabled = true;
- lineRenderers[index].SetPosition(0, GetArcPositionAtTime(startTime));
- lineRenderers[index].SetPosition(1, GetArcPositionAtTime(endTime));
- }
- //-------------------------------------------------
- public void SetColor(Color color)
- {
- for (int i = 0; i < segmentCount; ++i)
- {
- #if (UNITY_5_4)
- lineRenderers[i].SetColors(color, color);
- #else
- lineRenderers[i].startColor = color;
- lineRenderers[i].endColor = color;
- #endif
- }
- }
- //-------------------------------------------------
- private float FindProjectileCollision(out RaycastHit hitInfo)
- {
- float timeStep = arcDuration / segmentCount;
- float segmentStartTime = 0.0f;
- hitInfo = new RaycastHit();
- Vector3 segmentStartPos = GetArcPositionAtTime(segmentStartTime);
- for (int i = 0; i < segmentCount; ++i)
- {
- float segmentEndTime = segmentStartTime + timeStep;
- Vector3 segmentEndPos = GetArcPositionAtTime(segmentEndTime);
- if (Physics.Linecast(segmentStartPos, segmentEndPos, out hitInfo, traceLayerMask))
- {
- if (hitInfo.collider.GetComponent<IgnoreTeleportTrace>() == null)
- {
- Util.DrawCross(hitInfo.point, Color.red, 0.5f);
- float segmentDistance = Vector3.Distance(segmentStartPos, segmentEndPos);
- float hitTime = segmentStartTime + (timeStep * (hitInfo.distance / segmentDistance));
- return hitTime;
- }
- }
- segmentStartTime = segmentEndTime;
- segmentStartPos = segmentEndPos;
- }
- return float.MaxValue;
- }
- //-------------------------------------------------
- public Vector3 GetArcPositionAtTime(float time)
- {
- Vector3 gravity = useGravity ? Physics.gravity : Vector3.zero;
- Vector3 arcPos = startPos + ((projectileVelocity * time) + (0.5f * time * time) * gravity) * scale;
- return arcPos;
- }
- //-------------------------------------------------
- private void HideLineSegments(int startSegment, int endSegment)
- {
- if (lineRenderers != null)
- {
- for (int i = startSegment; i < endSegment; ++i)
- {
- lineRenderers[i].enabled = false;
- }
- }
- }
- }
- }
|