0
\$\begingroup\$

I am trying to make an Rts game in unity and am trying to make it so that units can go to different destinations, I have a selection system that deactivates their Navmesh agents and the script that tells them where to go when they are not selected. they can go to different places if only one group/unit is moving, but if I try to make two groups/units move to different destinations they will just go to the first group's destination. How can I make two active pathfinding agents go to different destinations? or should I try to find a different method of pathfinding?

this is the code I'm using to move the units. but it isn't the only code affecting them. if there's nothing wrong here I can show the other script that's attached to them. I can also show the code for unit selction.

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class UnitMovement : MonoBehaviour
{
    Camera cam;
    NavMeshAgent myAgent;
    public LayerMask ground;
    public static List<NavMeshAgent> meshAgents = new List<NavMeshAgent>();

    void Start()
    {
        cam = Camera.main;
        myAgent = this.gameObject.GetComponent<NavMeshAgent>();
        
    }

    void Update()
    {
        if (meshAgents.Contains(myAgent))
        {
            //absolutely nothing   
        }
        else
        {
            meshAgents.Add(myAgent);
        }
        if (Input.GetMouseButtonDown(1) && meshAgents.Contains(myAgent))
        {
            if (meshAgents.IndexOf(myAgent) == 0)
            {
                RaycastHit hit;
                Ray ray = cam.ScreenPointToRay(Input.mousePosition);

                if (Physics.Raycast(ray, out hit, Mathf.Infinity, ground))
                {
                    if (UnitSelections.Instance.unitsSelected.Contains(this.gameObject))
                    {

                        
                        myAgent.SetDestination(hit.point);
                    }
                   
                }

                float angle = 60; // angular step
                int countOnCircle = (int)(360 / angle); // max number in one round
                int count = meshAgents.Count; // number of agents
                float step = 1; // circle number
                int i = 1; // agent serial number
                float randomizeAngle = Random.Range(0, angle);
                while (count > 1)
                {
                    var vec = Vector3.forward;
                    vec = Quaternion.Euler(0, angle * (countOnCircle - 1) + randomizeAngle, 0) * vec;
                    meshAgents[i].SetDestination(myAgent.destination + vec * (myAgent.radius + meshAgents[i].radius + 0.5f) * step);
                    countOnCircle--;
                    count--;
                    i++;
                    if (countOnCircle == 0)
                    {
                        if (step != 3 && step != 4 && step < 6 || step == 10) { angle /= 2f; }

                        countOnCircle = (int)(360 / angle);
                        step++;
                        randomizeAngle = Random.Range(0, angle);
                    }
                }

            }
        }
    }

    void OnDisable()
    {
        meshAgents.Clear();
    }
}

Script that disables movement when unit not selected

using UnityEngine;
using UnityEngine.AI;
public class Unit : MonoBehaviour
{
    
    void Start()
    {
        UnitSelections.Instance.unitList.Add(this.gameObject);
    }

    void Update()
    {
        if(UnitSelections.Instance.unitsSelected.Contains(this.gameObject))
        {
            this.gameObject.GetComponent<UnitMovement>().enabled = true;
            this.gameObject.GetComponent<NavMeshAgent>().enabled = true;
        }
        else if(!UnitSelections.Instance.unitsSelected.Contains(this.gameObject) && this.gameObject.GetComponent<NavMeshAgent>().hasPath == false)
        {
            this.gameObject.GetComponent<UnitMovement>().enabled = false;
            this.gameObject.GetComponent<NavMeshAgent>().enabled = false;
        }

        if (transform.position.y < 1)
        {
            transform.position = new Vector3(transform.position.x, 1, transform.position.z);
        }
    }


    private void OnDestroy()
    {
        UnitSelections.Instance.unitList.Remove(this.gameObject);
    }
}
\$\endgroup\$
2
  • \$\begingroup\$ It looks like you have the script on every single selectable/movable unit also trying to process issuing commands to all of those units. This adds inefficiency like having every active unit checking to see if it's the first in the list so it can command the others. I'd recommend separating those concerns. The scripts on each unit should handle only acting on commands, not issuing them to other units. Then you can have a single script instance elsewhere that handles issuing commands. I show an example of such an architecture in this answer. \$\endgroup\$
    – DMGregory
    Commented Aug 14, 2022 at 15:25
  • \$\begingroup\$ Thank you so much! \$\endgroup\$ Commented Aug 14, 2022 at 17:17

1 Answer 1

0
\$\begingroup\$

"It looks like you have the script on every single selectable/movable unit also trying to process issuing commands to all of those units. This adds inefficiency like having every active unit checking to see if it's the first in the list so it can command the others. I'd recommend separating those concerns. The scripts on each unit should handle only acting on commands, not issuing them to other units. Then you can have a single script instance elsewhere that handles issuing commands. I show an example of such an architecture in this answer" -DMgregory

\$\endgroup\$
1
  • \$\begingroup\$ This answer would be more useful if instead you showed the code you wrote to action this advice, rather than just copying a comment. \$\endgroup\$
    – DMGregory
    Commented Jun 14, 2023 at 21:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .