0
\$\begingroup\$

I am making a snake AI with Unity ML Agents. There will be lots of snakes who will eat and dodge each other.

A 3D RayPerceptionSensor detects everything, but there is a specific case where a problem happens.

My snake has 30 cube children, each having tags as beads. There are other snakes similar to that.

I want the ray perception to not detect the snake's own child objects, but to detect everything else.

How can I make that happen?

\$\endgroup\$
3
  • \$\begingroup\$ How are you going to prevent the snake crashing into itself when it is not allowed to see itself? Depending on the amount of snakes, you could give each snake a unique tag as well and in the DetectableTags list, you add all of them except your own. Or from RayPerceptionOutput.RayOutput you can use HitGameObject and compare it if that belongs to your child body part. \$\endgroup\$ Commented Jul 18, 2024 at 10:08
  • \$\begingroup\$ Snake won't die because it crash in itself . I am making a game similar to slither.io .Also the code structure of all the snake is same as mine so it won't work different tags strategy \$\endgroup\$ Commented Jul 18, 2024 at 11:39
  • \$\begingroup\$ OK guys I solved it ! , I made my own custom raycast ! You can also make it by seeing how rayperception sensor works ! \$\endgroup\$ Commented Jul 20, 2024 at 6:10

1 Answer 1

0
\$\begingroup\$

Ray perception sensor works like this suppose there are 2 tags wall , goal . No of rays is 3

so each ray will have a list of 1's and 0's:

  • Ray 1 - [(hashitwall) , (hashitgoal) , (hitnothing), (hitdistanceratio)

  • Ray 2 - [(hashitwall) , (hashitgoal) , (hitnothing), (hitdistanceratio)

  • Ray 3 - [(hashitwall) , (hashitgoal) , (hitnothing), (hitdistanceratio)

Let's say ray1 hit wall only , ray2 hit goal only ray3 hit nothing

  • Ray1 - [1,0,0,0.2f]
  • Ray2 - [0,1,0,0.5f]
  • Ray3 - [0,0,1,0]

Then we will combine these list into 1 list finallist = [1,0,0,0.2f , 0,1,0,0.5f , 0,0,1,0]

Strangely but AI is excellent in finding patterns and it will definately find pattern here

using System.Collections.Generic;
using Unity.MLAgents.Policies;
using UnityEngine;


public class CustomRaycast3D : MonoBehaviour
{
    [SerializeField] private List<string> detectableTags;
    [SerializeField] private float angle = 90;
    [SerializeField] private int numberOfRays = 20;
    [SerializeField] private float rayDistance = 10f;
    [SerializeField] private float sphereCastRadius = 0.5f;
    [SerializeField] private BehaviorParameters behaviorParameters;


    private void Awake()
    {
        behaviorParameters.BrainParameters.VectorObservationSize = numberOfRays * (detectableTags.Count + 2) + 3;
    }

    private void Update()
    {
        CastRays();
    }

    public List<float> CastRays()
    {
        List<float> finalOutput = new List<float>();

        for (int i = 0; i < numberOfRays; i++)
        {
            float rayAngle = i * angle / (numberOfRays - 1) - angle / 2;
            Vector3 rayDirection = Quaternion.Euler(0, rayAngle, 0) * transform.forward;
            Ray ray = new Ray(transform.position, rayDirection);

            List<float> oneHot = new List<float>();

            if(Physics.SphereCast(ray , sphereCastRadius , out RaycastHit hit , rayDistance))
            {
                foreach (string currentTag in detectableTags)
                {
                    oneHot.Add(hit.collider.gameObject.CompareTag(currentTag) ? 1.0f : 0.0f);

                    if (hit.collider.gameObject.CompareTag("BodyPart") && currentTag == "BodyPart")
                    {
                        Transform hitParentTransform = hit.collider.transform.parent;
                        Transform ourParentTransform = transform.parent.transform.parent;
                        if (hitParentTransform.gameObject == ourParentTransform.gameObject)
                        {
                            oneHot[oneHot.Count - 1] = 0f;
                        }
                    }
                }

                oneHot.Add(0f); //No collision is false
                oneHot.Add(hit.distance / rayDistance);
            }
            else
            {
                foreach (string tag in detectableTags)
                {
                    oneHot.Add(0f);
                }
                oneHot.Add(1f); //No collision is true
                oneHot.Add(0f);
            }

            finalOutput.AddRange(oneHot);
        }
        return finalOutput;
    }


    private void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        for (int i = 0; i < numberOfRays; i++)
        {
            float rayAngle = i * angle / (numberOfRays - 1) - angle / 2;
            Vector3 rayDirection = Quaternion.Euler(0, rayAngle, 0) * transform.forward;
            Ray ray = new Ray(transform.position, rayDirection);
            Gizmos.DrawRay(ray.origin, ray.direction * rayDistance);
            Gizmos.DrawWireSphere(ray.origin + ray.direction * rayDistance, sphereCastRadius);
        }
    }

    private void DebugName(List<float> list)
    {
        Debug.Log(list.Count);
        List<string> stringList = list.ConvertAll(f => f.ToString());
        string listString = string.Join(", ", stringList);
        Debug.Log(listString);
    }
}
\$\endgroup\$
4
  • \$\begingroup\$ To understand this you need to know how raycast is working internally in rayperception sensor you can ask AI \$\endgroup\$ Commented Jul 20, 2024 at 6:12
  • \$\begingroup\$ So how does this prevent the ray from hitting children of the snake body? \$\endgroup\$ Commented Jul 21, 2024 at 6:09
  • \$\begingroup\$ if (hit.collider.gameObject.CompareTag("BodyPart") && currentTag == "BodyPart") { Transform hitParentTransform = hit.collider.transform.parent; Transform ourParentTransform = transform.parent.transform.parent; if (hitParentTransform.gameObject == ourParentTransform.gameObject) { oneHot[oneHot.Count - 1] = 0f; } } \$\endgroup\$ Commented Jul 27, 2024 at 6:59
  • \$\begingroup\$ You have all the data , now's it's pretty simple to sort them as you want . The biggest challenge was to make custom raycast 3d . Now you have the data , it's easy to sort them out \$\endgroup\$ Commented Jul 27, 2024 at 7:00

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.