using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MalbersAnimations.Utilities;
namespace MalbersAnimations.Weapons
{
/// Uses a Line Renderer to Predict and Paint a Trajectory
[AddComponentMenu("Malbers/Damage/DisplayTrajectory")]
public class MDisplayTrajectory : MonoBehaviour
{
private IThrower Thrower;
[RequiredField, Tooltip("Reference for the line renderer")]
public LineRenderer line;
[Tooltip("Reference to Place a Transform at the End of the Line Renderer")]
public GameObject HitPoint;
[Tooltip("Start width of the line renderer")]
public float StartWidth = 0.3f;//Width of Line where it starts
[Tooltip("End width of the line renderer")]
public float EndWidth = 0.1f;//Width of Line where it ends
[Tooltip("Start Color of the line renderer")]
public Color startColor = Color.blue;//Color of Line where it starts
[Tooltip("End Color of the line renderer")]
public Color endColor = Color.green;//Color of Line where it ends
[Tooltip("Line renderer steps")]
public float Step = 0.1f;
[Tooltip("Max Steps")]
public int MaxSteps = 50;
private List Trajectory = new List();
public bool ShowTrayectory { get; set; }
private void Reset()
{
line = GetComponent();
if (line == null)
line = gameObject.AddComponent();
Thrower = GetComponent();
SetLineRenderer();
}
private void OnEnable()
{
SetLineRenderer();
if (HitPoint && HitPoint.IsPrefab())
HitPoint = Instantiate(HitPoint,transform);
if (line.sharedMaterial == null)
line.material = new Material(Shader.Find("Sprites/Default"));
if (Thrower == null)
Thrower = GetComponent();
if (Thrower != null)
Thrower.Predict += DisplayTraj;
}
private void OnDisable() { if (Thrower != null) Thrower.Predict -= DisplayTraj; }
private void Update()
{
if (ShowTrayectory)
{
DisplayTrajectory(Thrower.AimOriginPos, Thrower.Velocity);
}
}
void SetLineRenderer()
{
line.startWidth = StartWidth;
line.endWidth = EndWidth;
var gradient = new Gradient();
gradient.SetKeys(
new GradientColorKey[] { new GradientColorKey(startColor, 0.0f), new GradientColorKey(endColor, 1.0f) },
new GradientAlphaKey[] { new GradientAlphaKey(startColor.a, 0.0f), new GradientAlphaKey(endColor.a, 1.0f) }
);
line.colorGradient = gradient;
line.useWorldSpace = true;
line.receiveShadows = false;
line.enabled = false;
line.positionCount = 0;
}
private void DisplayTraj(bool show)
{
ShowTrayectory = show;
line.enabled = show;
if (HitPoint) HitPoint.SetActive(show);
if (!ShowTrayectory)
{
line.enabled = false;
line.positionCount = 0;
}
}
public virtual void DisplayTrajectory(Vector3 Origin, Vector3 ProjectileVelocity)
{
if (ProjectileVelocity == Vector3.zero)
{
if (HitPoint) HitPoint.SetActive(false);
line.enabled = false;
line.positionCount = 0;
return;
}
else
{
if (HitPoint) HitPoint.SetActive(true);
line.enabled = true;
Trajectory = TrajectoryPoints(Origin, ProjectileVelocity);
DisplayRenderer();
}
}
private List TrajectoryPoints(Vector3 start, Vector3 velocity)
{
var points = new List();
if (Step <= 0) return points;
points.Add(start);
Vector3 prev = start;
var hit = new RaycastHit() { normal = Vector3.up};
for (int i = 1; i < MaxSteps; i++)
{
float time = Step * i;
Vector3 pos = start + velocity * time + Thrower.Gravity * time * time / 2;
if (Physics.Linecast(prev, pos, out hit, Thrower.Layer, Thrower.TriggerInteraction))
{
if (!hit.collider.transform.IsChildOf(Thrower.Owner.transform))
{
points.Add(hit.point);
break;
}
}
points.Add(pos);
prev = pos;
}
if (HitPoint)
{
HitPoint.transform.position = hit.point;
HitPoint.transform.up = hit.normal;
}
return points;
}
public void DisplayRenderer()
{
for (int i = 1; i < Trajectory.Count; i++) //Debug Lines for the Prediction
Debug.DrawLine(Trajectory[i - 1], Trajectory[i], Color.yellow);
line.positionCount = Trajectory.Count;
line.SetPositions(Trajectory.ToArray());
}
}
#if UNITY_EDITOR
[UnityEditor.CustomEditor(typeof(MDisplayTrajectory))]
[UnityEditor.CanEditMultipleObjects]
public class MDisplayTrajectoryEd : UnityEditor.Editor
{
UnityEditor.SerializedProperty line, StartWidth, EndWidth, startColor, endColor, Step, MaxSteps, Hit;
public static GUIStyle StyleBlue => MTools.Style(new Color(0, 0.5f, 1f, 0.3f));
private void OnEnable()
{
line = serializedObject.FindProperty("line");
StartWidth = serializedObject.FindProperty("StartWidth");
EndWidth = serializedObject.FindProperty("EndWidth");
startColor = serializedObject.FindProperty("startColor");
endColor = serializedObject.FindProperty("endColor");
Step = serializedObject.FindProperty("Step");
MaxSteps = serializedObject.FindProperty("MaxSteps");
Hit = serializedObject.FindProperty("HitPoint");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
MalbersEditor.DrawDescription("Displays the Trajectory of a projectile, using a list of points");
UnityEditor.EditorGUILayout.BeginVertical(UnityEditor.EditorStyles.helpBox);
{
UnityEditor.EditorGUILayout.PropertyField(Hit);
UnityEditor.EditorGUILayout.PropertyField(line);
UnityEditor.EditorGUILayout.BeginHorizontal();
{
UnityEditor.EditorGUILayout.PropertyField(StartWidth, GUILayout.MinWidth(40));
UnityEditor.EditorGUIUtility.labelWidth = 50;
UnityEditor.EditorGUILayout.PropertyField(EndWidth, new GUIContent("End"), GUILayout.MinWidth(30));
UnityEditor.EditorGUIUtility.labelWidth = 0;
}
UnityEditor.EditorGUILayout.EndHorizontal();
UnityEditor.EditorGUILayout.BeginHorizontal();
{
UnityEditor.EditorGUILayout.PropertyField(startColor, GUILayout.MinWidth(40));
UnityEditor.EditorGUIUtility.labelWidth = 50;
UnityEditor.EditorGUILayout.PropertyField(endColor, new GUIContent("End"), GUILayout.MinWidth(30));
UnityEditor.EditorGUIUtility.labelWidth = 0;
}
UnityEditor.EditorGUILayout.EndHorizontal();
UnityEditor.EditorGUILayout.BeginHorizontal();
{
UnityEditor.EditorGUILayout.PropertyField(Step, GUILayout.MinWidth(40));
UnityEditor.EditorGUIUtility.labelWidth = 50;
UnityEditor.EditorGUILayout.PropertyField(MaxSteps, new GUIContent("Max"), GUILayout.MinWidth(30));
UnityEditor.EditorGUIUtility.labelWidth = 0;
}
UnityEditor.EditorGUILayout.EndHorizontal();
}
UnityEditor.EditorGUILayout.EndVertical();
serializedObject.ApplyModifiedProperties();
}
}
#endif
}