TargetManager.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. //***********************************************************
  2. // Filename: TargetManager.cs
  3. // Author: Niclas
  4. // Last changes: 08 August 2018
  5. // Content: This file generates new targets with several parameters
  6. //***********************************************************
  7. using System.Collections;
  8. using System.Collections.Generic;
  9. using UnityEngine;
  10. /// <summary>
  11. /// This class is responsible for generating new targets with various constrains on button press and tracking the experiment progress
  12. /// </summary>
  13. public class TargetManager : MonoBehaviour, IButton {
  14. // true if the experiment is ongoing
  15. public bool isExpActive = false;
  16. // Area in which new targets can be generated
  17. private GameObject area;
  18. // Bounds of the area
  19. private Bounds areaBounds;
  20. // The number of targets that will be spawned in this experiment
  21. public int numberOfTargets = 0;
  22. // Prefab used to generate a new target
  23. public GameObject targetPrefab;
  24. // The gameobject of prefab instance which is already placed in the scene
  25. public GameObject lastTarget;
  26. // Constrains for generating the next target
  27. // The maximum rotation of the direction of targets in either way
  28. public float maxAngle = 10;
  29. // minimum and maximum distance of the next target to the current one
  30. public float minDistance = 1;
  31. public float maxDistance = 3;
  32. // The maximum y rotation of the next target
  33. public float maxTargetRotation = 360;
  34. // Directional Vector from which the direction in which the next target spawns will be calculated
  35. private Vector3 dirOfNextPos = Vector3.right;
  36. // 0 for starting target, >0 for "true" targets; doubles as target count
  37. private int currentTargetId = 0;
  38. // Use this for initialization
  39. void Start() {
  40. // Set base Target which only used to calculate the postion of the first "real" Target
  41. if (lastTarget == null) {
  42. lastTarget = new GameObject();
  43. }
  44. area = GameObject.FindGameObjectWithTag("ExpPlane");
  45. areaBounds = area.GetComponent<MeshFilter>().mesh.bounds;
  46. }
  47. // Update is called once per frame
  48. void Update() {
  49. // Debug Listener for KeyPress
  50. if (Input.GetKeyDown(KeyCode.Space)) {
  51. OnButtonUp();
  52. }
  53. }
  54. /// <summary>
  55. /// Spawns Target at desired position and rotation as child of area
  56. /// </summary>
  57. private void SpawnTarget() {
  58. currentTargetId++;
  59. GameObject target = Instantiate(targetPrefab);
  60. target.transform.SetParent(area.transform, false);
  61. target.transform.localPosition = RandomRestrictedPosition();
  62. target.transform.rotation = RandomYRotation();
  63. target.GetComponent<TestTarget>().id = currentTargetId;
  64. lastTarget = target;
  65. // Fire event that a new target has been spawned
  66. TargetSpawnedEvent tse = new TargetSpawnedEvent();
  67. tse.targetId = currentTargetId;
  68. tse.targetTransform = target.transform;
  69. tse.FireEvent();
  70. }
  71. /// <summary>
  72. /// Generates a random rotation with nullvector as base, is separate to allow possible restrictions in rotation
  73. /// </summary>
  74. /// <returns>Returns a Quaternion containing a random rotation within constrains</returns>
  75. private Quaternion RandomYRotation() {
  76. Vector3 euler = Vector3.zero;
  77. euler.y = Random.Range((-maxTargetRotation / 2) - 90, (maxTargetRotation / 2) - 90);
  78. return Quaternion.Euler(euler);
  79. }
  80. /// <summary>
  81. /// Returns a randomly selected position in the area and calls for a check if it is valid
  82. /// </summary>
  83. /// <returns>Returns a within constrains random and valid position</returns>
  84. private Vector3 RandomRestrictedPosition() {
  85. Vector3 nextPos = lastTarget.transform.localPosition;
  86. float rot = Random.Range(-maxAngle, maxAngle);
  87. Vector3 moveTarget = Quaternion.AngleAxis(rot, Vector3.up) * dirOfNextPos;
  88. // TODO: improve so it rotates based on lastTarget rotation
  89. moveTarget = moveTarget.normalized * Random.Range(minDistance, maxDistance);
  90. nextPos += moveTarget;
  91. nextPos.y = 0;
  92. return ValidatePosition(nextPos);
  93. }
  94. /// <summary>
  95. /// Checks if next Position is in the areas bounds and set it inside if needed
  96. /// </summary>
  97. /// <param name="position">The position that should be checked if it lies within constrains</param>
  98. /// <returns>Returns the position with, if necessary, corrections</returns>
  99. private Vector3 ValidatePosition(Vector3 position) {
  100. if (!areaBounds.Contains(position)) {
  101. Debug.Log("OutOfBounds! ClosestPos: " + areaBounds.ClosestPoint(position));
  102. position = areaBounds.ClosestPoint(position) + ((areaBounds.ClosestPoint(position) - position).normalized * maxDistance);
  103. dirOfNextPos = dirOfNextPos * -1;
  104. }
  105. return position;
  106. }
  107. /// <summary>
  108. /// Called when the corresponding button on the controller this script is put into, is released
  109. /// </summary>
  110. public void OnButtonUp() {
  111. if (isExpActive) {
  112. Destroy(lastTarget);
  113. if (currentTargetId == numberOfTargets) {
  114. isExpActive = false;
  115. ExperimentEndEvent eee = new ExperimentEndEvent();
  116. eee.FireEvent();
  117. } else {
  118. SpawnTarget();
  119. }
  120. }
  121. }
  122. // unused; necessary to match signature
  123. public void OnButtonDown(GameObject controllerObject, int controllerIdentificator) {
  124. }
  125. }