using UnityEngine; using UnityEngine.UI; using UnityEngine.AI; using System.Collections.Generic; using System.IO; using System; [DefaultExecutionOrder(61)] [RequireComponent(typeof(InstantiatePrefab), typeof(WriteInCSV), typeof(ReadFromCSV))] public class SpatialTimeSimulation : MonoBehaviour { // Waypoints and Rotations [HideInInspector] public Tuple, List, List, List>[][] timePosRotList; // Private Journey Settings private int currentStartPoint; private float startTime; // Global GameObjects private GameObject[][] humansGO; private NavMeshAgent[][] humansNMA; private Animator[][] humansA; // Playback variables private int[] maxIJ; private int indexChangeRate; [HideInInspector] public bool rewind, pause, play; //PlaybackController // Slider Settings public Slider slider; public GameObject buttons; private float prevSliderValue; // Thief Settings //private Vector3 stealHere; // Spatial time visualization private List[][] positions; public float thickness = 0.1f; public Material material; public Color color; private void Start() { // Get information from InstatiatePrefab humansGO = gameObject.GetComponent().humanGameObject; humansA = gameObject.GetComponent().humanAnimator; humansNMA = gameObject.GetComponent().humanNavMeshAgent; positions = new List[humansGO.Length][]; //stealHere = gameObject.GetComponent().stealHere; // Read from CSV file and save time, position, rotation in matrix int index = gameObject.GetComponent().index; string dir = Directory.GetCurrentDirectory(); string reference = @"\Assets\Data_position\Walk" + index + ".csv"; timePosRotList = gameObject.GetComponent().ReadFromCSVFile(dir + reference); // Add 0.5f + time to y // Disable components and add LineRenderer currentStartPoint = 0; for (int i = 0; i < humansGO.Length; ++i) { positions[i] = new List[humansGO[i].Length]; for (int j = 0; j < humansGO[i].Length; ++j) { // A shortcut to use the position data immediately for the LineRenderer positions[i][j] = new List(); foreach (var position in timePosRotList[i][j].Item2) { positions[i][j].Add(new Vector3(position.x, 0.5f + timePosRotList[i][j].Item1[currentStartPoint], position.z)); currentStartPoint++; } currentStartPoint = 0; // Every component should be disabled except the humans game object, bc the LineRenderer operates there humansGO[i][j].SetActive(true); humansA[i][j].enabled = false; humansNMA[i][j].enabled = false; foreach(Transform child in humansGO[i][j].transform) { child.gameObject.SetActive(false); } // Add the LineRenderer to the gameobject LineRenderer drawPath = humansGO[i][j].AddComponent(); //drawPath.material = new Material(Shader.Find("Sprites/Default")); //drawPath.material = new Material(Shader.Find("Particles/Standard Unlit")); //drawPath.material = new Material(Shader.Find("VolumetricLine/LineStrip-TextureAlphaBlended")); drawPath.material = material; drawPath.startColor = color; drawPath.endColor = color; drawPath.startWidth = thickness; drawPath.endWidth = thickness; drawPath.numCapVertices = 90; drawPath.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; drawPath.receiveShadows = false; drawPath.positionCount = currentStartPoint + 1; drawPath.SetPosition(currentStartPoint, positions[i][j][currentStartPoint]); } } // Set the Slider settings if (slider == null) { Debug.Log("No Slider instance attached"); return; } maxIJ = GetHumanWithLongestScreenTime(); float maxTime = (float)Math.Round(timePosRotList[maxIJ[0]][maxIJ[1]].Item1[timePosRotList[maxIJ[0]][maxIJ[1]].Item1.Count - 1], 2); slider.minValue = 0; slider.maxValue = (maxTime / Time.deltaTime); slider.wholeNumbers = true; prevSliderValue = slider.value; // Don't show buttons if (buttons.activeSelf) buttons.SetActive(false); currentStartPoint++; slider.value = currentStartPoint; startTime = Time.time; } private void FixedUpdate() { if (pause) indexChangeRate = 0; if (play) indexChangeRate = 1; if (rewind) indexChangeRate = -1; if (play || rewind) { if ((currentStartPoint + indexChangeRate) < timePosRotList[maxIJ[0]][maxIJ[1]].Item2.Count && (currentStartPoint + indexChangeRate) >= 0) { if (slider.value - prevSliderValue == -1 || slider.value - prevSliderValue == 0 || slider.value - prevSliderValue == 1) // rewind || play { prevSliderValue = slider.value; currentStartPoint += indexChangeRate; slider.value = currentStartPoint; } else { prevSliderValue = slider.value; currentStartPoint = (int)slider.value; } SetTransform(currentStartPoint); } else if (slider.value - prevSliderValue != -1 || slider.value - prevSliderValue != 0 || slider.value - prevSliderValue != 1) { currentStartPoint = (int)slider.value; } } else { currentStartPoint = (int)slider.value; SetTransform(currentStartPoint); } } private void SetTransform(int currentStartPoint) { for (int i = 0; i < humansGO.Length; ++i) { for (int j = 0; j < humansGO[i].Length; ++j) { LineRenderer drawPath = humansGO[i][j].GetComponent(); // if so ArgumentOutOfRangeException if ((currentStartPoint + indexChangeRate) >= (timePosRotList[i][j].Item2.Count - 1) || (currentStartPoint + indexChangeRate) < 0) { if((currentStartPoint + indexChangeRate) >= (timePosRotList[i][j].Item2.Count - 1)) { drawPath.positionCount = positions[i][j].Count; drawPath.SetPositions(positions[i][j].ToArray()); } continue; } if (currentStartPoint < timePosRotList[i][j].Item2.Count) { // We need to specify the Length of the positionCount variable drawPath.positionCount = currentStartPoint + 1; // We copy the positions list and remove every element after the currentStartPoint from the copy List tmpLst = new List(positions[i][j]); tmpLst.RemoveRange(currentStartPoint + 1, positions[i][j].Count - currentStartPoint - 1); drawPath.SetPositions(tmpLst.ToArray()); } } } } private int[] GetHumanWithLongestScreenTime() { int[] maxIJ = new int[2] { 0, 0 }; float currentMaxTime = 0; for (int i = 0; i < humansGO.Length; ++i) { for (int j = 0; j < humansGO[i].Length; ++j) { if (currentMaxTime < timePosRotList[i][j].Item1.Count) { currentMaxTime = timePosRotList[i][j].Item1.Count; maxIJ[0] = i; maxIJ[1] = j; } } } return maxIJ; } }