You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			312 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C#
		
	
			
		
		
	
	
			312 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C#
		
	
//======= 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;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |