Neodroid  0.2.0
Machine Learning Environment Prototyping Tool
SeekAndAvoidEvaluation.cs
Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
4 using UnityEngine;
5 using Random = UnityEngine.Random;
6 
7 namespace droid.Runtime.Prototyping.Evaluation {
12  [SerializeField] Transform _actor = null;
13  [SerializeField] GameObject _avoidable = null;
14  List<GameObject> _avoidables = null;
15  [SerializeField] GameObject _collectible = null;
16  List<GameObject> _collectibles = null;
17  [SerializeField] int _end_game_radius = 10;
18  Vector3 _initial_actor_position = Vector3.zero;
19  [SerializeField] int _num_avoidables = 50;
20  [SerializeField] int _num_collectibles = 50;
21  [SerializeField] int _penalty = -1;
22  [SerializeField] int _reward = 1;
23  float _score;
24  [SerializeField] int _spawn_radius = 10;
25  List<Vector3> _spawned_locations = null;
26 
30  public override String PrototypingTypeName { get { return "SeekAndAvoidListener"; } }
31 
36  public override Single InternalEvaluate() {
37  // The game ends if the number of good balls is 0, or if the robot is too far from start
38  var actor = this._actor;
39  if (actor != null) {
40  var dist = Vector3.Distance(this._initial_actor_position, actor.position);
41  var game_objects = this._collectibles;
42  var is_over = game_objects != null && (game_objects.Count == 0 || dist > this._end_game_radius);
43 
44  if (is_over) {
45  this.ParentEnvironment.Terminate($"Ending Game: Dist {dist} radius {this._spawn_radius}");
46  }
47  }
48 
49  return this._score;
50  }
51 
55  public override void InternalReset() {
56  if (!Application.isPlaying) {
57  return;
58  }
59 
60  var actor = this._actor;
61  if (actor != null) {
62  this._initial_actor_position = actor.position;
63  var remote_sensor = this._actor.GetComponentInChildren<ChildColliderSensor<Collider, Collision>>();
64  if (!remote_sensor) {
65  var col = this._actor.GetComponentInChildren<Collider>();
66  if (col) {
67  remote_sensor = col.gameObject.AddComponent<ChildColliderSensor<Collider, Collision>>();
68  }
69  }
70 
71  if (remote_sensor) {
72  remote_sensor.Caller = this;
73  remote_sensor.OnTriggerEnterDelegate = this.OnChildTriggerEnter;
74  remote_sensor.OnCollisionEnterDelegate = this.OnChildTriggerEnter;
75  }
76  }
77 
78  this.ClearEnvironment();
79  this.SpawnCollectibles();
80  this.SpawnAvoidables();
81  }
82 
83  void OnChildTriggerEnter(GameObject child_game_object, Collision collision) {
84  this.OnChildTriggerEnter(child_game_object, collision.collider);
85  }
86 
87  void OnChildTriggerEnter(GameObject child_game_object, Collider collider1) {
88  #if NEODROID_DEBUG
89  if (this.Debugging) {
90  print($"{child_game_object} is colliding with {collider1}");
91  }
92  #endif
93 
94  var collectible = this._collectible;
95  if (collectible != null && collider1.gameObject.name.Contains(collectible.name)) {
96  this._collectibles.Remove(collider1.gameObject);
97  Destroy(collider1.gameObject);
98  this._score += this._reward;
99  }
100 
101  var game_object = this._avoidable;
102  if (game_object != null && collider1.gameObject.name.Contains(game_object.name)) {
103  this._avoidables.Remove(collider1.gameObject);
104  this._score += this._penalty;
105  Destroy(collider1.gameObject);
106  }
107  }
108 
109  void SpawnCollectibles() {
110  for (var i = 0; i < this._num_collectibles; i++) {
111  var game_object = this._collectible;
112  if (game_object != null) {
113  var collectible = this.RandomSpawn(this._collectible, this._initial_actor_position);
114  this._collectibles.Add(collectible);
115  }
116  }
117  }
118 
119  void SpawnAvoidables() {
120  for (var i = 0; i < this._num_avoidables; i++) {
121  var game_object = this._avoidable;
122  if (game_object != null) {
123  var avoidable = this.RandomSpawn(this._avoidable, this._initial_actor_position);
124  this._avoidables.Add(avoidable);
125  }
126  }
127  }
128 
129  GameObject RandomSpawn(GameObject prefab, Vector3 position) {
130  this._spawned_locations.Add(position);
131 
132  if (prefab != null) {
133  Vector3 location;
134  do {
135  location = this._actor.transform.position;
136  location.x += Random.Range(-this._spawn_radius, this._spawn_radius);
137  location.y = position.y + 1f;
138  location.z += Random.Range(-this._spawn_radius, this._spawn_radius);
139  } while (this._spawned_locations.Contains(location));
140 
141  this._spawned_locations.Add(location);
142 
143  return Instantiate(prefab, location, Quaternion.identity, this.ParentEnvironment.Transform);
144  }
145 
146  return null;
147  }
148 
149  void ClearEnvironment() {
150  if (this._spawned_locations != null) {
151  this._spawned_locations.Clear();
152  } else {
153  this._spawned_locations = new List<Vector3>();
154  }
155 
156  if (this._collectibles != null) {
157  foreach (var obj in this._collectibles) {
158  Destroy(obj);
159  }
160 
161  this._collectibles.Clear();
162  } else {
163  this._collectibles = new List<GameObject>();
164  }
165 
166  if (this._avoidables != null) {
167  foreach (var obj in this._avoidables) {
168  Destroy(obj);
169  }
170 
171  this._avoidables.Clear();
172  } else {
173  this._avoidables = new List<GameObject>();
174  }
175  }
176  }
177 }