0
\$\begingroup\$

I'm trying to write a system where I can run each enemy's NavMesh pathfinding in parallel, using Job System.

The problem I'm having is that I can't pass the NavMesh agent argument as it's a reference type.

InvalidOperationException: PathfindJob.agent is not a value type. Job structs may not contain any reference types.

I'm probably approaching this problem in a completely wrong way, but this is all I've come up with.

Here's the current Enemy code

using System.ComponentModel;
using Managers;
using Unity.Collections;
using Unity.Jobs;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Jobs;

namespace Characters
{
    [RequireComponent(typeof(Rigidbody))]
    public class Enemy : MonoBehaviour
    {
        [Header("Stats"), SerializeField] private int _health = 100;
        [SerializeField] private int _damage = 20;
        [SerializeField] private float _aggroRadius = 10f;

        private Rigidbody _body;
        private NavMeshAgent _agent;
        private Transform _target;

        private void Awake()
        {
            _body = GetComponent<Rigidbody>();
            _agent = GetComponent<NavMeshAgent>();
            _target = PlayerManager.GetInstance().GetPlayer();
        }

        private void OnDrawGizmosSelected()
        {
            Gizmos.color = Color.blue;
            Gizmos.DrawWireSphere(transform.position, _aggroRadius);
        }
    }

    public struct PathfindJob : IJobParallelForTransform
    {
        public Vector3 TargetPosition;
        public NavMeshAgent Agent;
        public float AggroRadius;

        public void Execute(int index, TransformAccess transform)
        {
            var distance = Vector3.Distance(TargetPosition, transform.position);

            if (distance < AggroRadius)
                Agent.SetDestination(TargetPosition);
        }    
    }
}

I'm scheduling the job from the GameManager class.

\$\endgroup\$
0
\$\begingroup\$

Currently Jobs are pretty limited in terms of thread-safety. There is no guarantee your NavMeshAgent can be accessed in a thread-safe manner at all. The actual limitation is that only value types and special objects such as NativeArrays are allowed to be processed inside of jobs as of now.

You might want to dig deeper into the sources and look for a NavMeshQuery if I recall correctly.

Alternatively you could write a job that would tag all agents that should start navigating somewhere else and use a hybrid system to fetch those tagged entities and execute the SetDestination method with the data from the tag component.


Edit: Keep in mind that the newest ECS package and Job/Burst infractructure is bleeding edge technology and considered not production ready. I am not quite sure about the rules and stance of StackExchange. Does the community allow discussions of tools/packages that are highly in flux? Any information shared might be obsolete pretty quick.

\$\endgroup\$
0
\$\begingroup\$

So, IIRC the only thing that you are doing in parallel with this is calculating the distance and setting the target. The actual Agent calculations happen in a different thread within the NavMesh system. All you are doing is (re)setting the NavMesh agent target over and over again - basically just passing in a Vector3 over and over.

What you (presumably) want is NavMesh actually be implemented in ECS, which is something entirely different. You could absolutely implement your own A* system in ECS as an exercise, but I suspect that won't get you closer to making a game.

Here is a video that does a good job showing the limits/capabilities of NavMesh agents without ECS.

https://www.youtube.com/watch?v=G9Otw12OUvE

There does appear to be some value to ECS + NavMesh by forcing query calculation. I found this GitHub repo: https://github.com/zulfajuniadi/unity-ecs-navmesh

Good luck!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.