using System.Collections.Generic; using UnityEngine; /// /// Ray perception component. Attach this to agents to enable "local perception" /// via the use of ray casts directed outward from the agent. /// public class RayPerception : MonoBehaviour { List perceptionBuffer = new List(); Vector3 endPosition; RaycastHit hit; /// /// Creates perception vector to be used as part of an observation of an agent. /// /// The partial vector observation corresponding to the set of rays /// Radius of rays /// Anlges of rays (starting from (1,0) on unit circle). /// List of tags which correspond to object types agent can see /// Starting heigh offset of ray from center of agent. /// Ending height offset of ray from center of agent. public List Perceive(float rayDistance, float[] rayAngles, string[] detectableObjects, float startOffset, float endOffset) { perceptionBuffer.Clear(); // For each ray sublist stores categorial information on detected object // along with object distance. foreach (float angle in rayAngles) { endPosition = transform.TransformDirection( PolarToCartesian(rayDistance, angle)); endPosition.y = endOffset; if (Application.isEditor) { Debug.DrawRay(transform.position + new Vector3(0f, startOffset, 0f), endPosition, Color.black, 0.01f, true); } float[] subList = new float[detectableObjects.Length + 2]; if (Physics.SphereCast(transform.position + new Vector3(0f, startOffset, 0f), 0.5f, endPosition, out hit, rayDistance)) { for (int i = 0; i < detectableObjects.Length; i++) { if (hit.collider.gameObject.CompareTag(detectableObjects[i])) { subList[i] = 1; subList[detectableObjects.Length + 1] = hit.distance / rayDistance; break; } } } else { subList[detectableObjects.Length] = 1f; } perceptionBuffer.AddRange(subList); } return perceptionBuffer; } /// /// Converts polar coordinate to cartesian coordinate. /// public static Vector3 PolarToCartesian(float radius, float angle) { float x = radius * Mathf.Cos(DegreeToRadian(angle)); float z = radius * Mathf.Sin(DegreeToRadian(angle)); return new Vector3(x, 0f, z); } /// /// Converts degrees to radians. /// public static float DegreeToRadian(float degree) { return degree * Mathf.PI / 180f; } }