RPG.CORE COMBAT - I have a (dysfunctional) system to move agents in formation

Intent:

Create a class to handle formation movement that establishes a “Leader” agent who sets the initial destination and will be followed by other selected agents positioned relative to the Leader based on “Rank”.

Current Progress:

I have a class: Formation.cs. In this class I have populated a couple lists of positions, all deriving from an input Vector3. The agents are selected, the issue to MoveAsUnit goes through. The intended location is marked and registers properly for all three classes involved in this drama. Then…

Problem:

I have a list of selected units that prints out correctly (maybe, something keeps itching my brain) but only one unit moves (Leader) to the appointed destination. The others are still on their phones. Further confounding me is that someone (more than one someone, I suspect) starts looking for an element out of the range of the List. If any agent is selected other than Leader the function just fails as soon as it looks to formation for instruction.

I know that I am misunderstanding the process needed to accomplish what I want. If you have read this far, you might as well amuse yourself with a peek at the code. Roll your eyes, do the heavy sigh thing and unload some heckling my direction.

First call to action comes from PlayerControl.cs (read: PlayerController.cs )

public bool UnitIsMoving()
{
movecast = reagon.Movecast();

 if (movecast.point != null)
 {
     if (control.action.Select.IsPressed())
     {
         movement.MoveToDestination(movecast.point);
         target.GetComponent<Collider>().gameObject.GetComponent<EnemyHighlighter>().HideHighlighter();
         return true;
     }
     else if (control.action.Alternate.WasReleasedThisFrame())
     {
         movement.MoveAsUnit(movecast.point);
         return true;
     }  
 }

 return false;

}

That is picked up by MovementManager.cs (read: Mover.cs )

public void MoveToDestination(Vector3 targetPosition)
{
     agent.destination = targetPosition;
     EnableAgentMovement();
 }

public void MoveAsUnit(Vector3 point)
 {
   scheduler.StartAction(this);    
  ClearPath();
  formation.FallInStep(point);
}

Then to a bit of code that would have Euclid spontaneously erupt into flames of stupidity.

 public class ReadyUnit
 {
     public PlayerControl player { get; set; }
     public int rank { get; set; }
 }
public class Formation : MonoBehaviour
{
    enum order
    {
        loose,
        column
    }
 
    [SerializeField] order arrangement = order.loose;
    [Range(1, 15)][SerializeField] int rank;
    ReadyUnit unit;
    public static List<ReadyUnit> readyUnitList = new List<ReadyUnit>();
    int currentRank;

    private void Start()
    {
        if (IsLeader())
        {
            currentRank = 0;
        }
        else
        {
            currentRank = rank;
        }

        unit = new ReadyUnit { player = gameObject.GetComponent<PlayerControl>(), rank = currentRank };
        Selector.Instance.UnitSelectedEvent += OnUnitSelected;
    }

    void OnUnitSelected(object sender, EventArgs e)
    {
        readyUnitList.Clear();
        if (Selector.Instance.GetSelectedPlayersList().Contains(gameObject.GetComponent<PlayerControl>()) ) 
        {
            readyUnitList.Add(unit);
        }
    }

    void SortUnitsByRank()
    {
        readyUnitList.Sort((leftHand, rightHand) => leftHand.rank.CompareTo(rightHand.rank));
    }

    public void FallInStep(Vector3 point)
    {
        if (point == null)
        {
            return;
        }

        if (readyUnitList == null)
        {
            Debug.LogError("No ready units list available.");
            return;
        }

        SortUnitsByRank();
        MoveToPosition(point);
    }

    void MoveToPosition(Vector3 point)
    {
        Debug.Log("F - MoveToPosition(" + point + ")");
        switch (arrangement)
        {
            case order.loose:
                LooseArrangement(point);
                break;
            case order.column:
                ColumnArrangement(point);
                break;
        }
    }

    bool IsLeader()
    {
        return Selector.Instance.GetSelectedUnit() == gameObject.GetComponent<PlayerControl>();
    }

    void LooseArrangement(Vector3 point)
    {
        float offset = Random.Range(-5f, 5f);

        List<Vector3> positions = new List<Vector3>
        {
            point,
            point + new Vector3(offset, 0, offset),
            point + new Vector3(offset, 0, offset),
            point + new Vector3(offset, 0, offset),
            point + new Vector3(offset, 0, offset),
            point + new Vector3(offset, 0, offset),
            point + new Vector3(offset, 0, offset),
            point + new Vector3(offset, 0, offset),
            point + new Vector3(offset, 0, offset),
            point + new Vector3(offset, 0, offset),
            point + new Vector3(offset, 0, offset),
            point + new Vector3(offset, 0, offset)
        };

        for (int i = 0; i < positions.Count; i++) 
        {
            PlayerControl currentUnit = readyUnitList[i].player;
            currentUnit.GetComponent<MovementManager>().MoveToDestination(positions[i]);
        }
    }

    void ColumnArrangement(Vector3 point)
    {
        List<Vector3> positions = new List<Vector3>()
        {
            point,
            point + new Vector3(5, 0, 0),
            point + new Vector3(0, 0, -3),
            point + new Vector3(5, 0, -3),
            point + new Vector3(0, 0, -6),
            point + new Vector3(5, 0, -6),
            point + new Vector3(0, 0, -9),
            point + new Vector3(5, 0, -9),
            point + new Vector3(0, 0, -12),
            point + new Vector3(5, 0, -12),
            point + new Vector3(0, 0, -15),
            point + new Vector3(5, 0, -15),
        };

        for (int i = 0; i < positions.Count; i++)
        {
            PlayerControl currentUnit = readyUnitList[i].player;
            currentUnit.GetComponent<MovementManager>().MoveToDestination(positions[i]);
        }
    }
}

}

image

Console after ruthlessly mocking my attempts to move my little agents and agentettes (agentettes is a real word, trust me.);

I do have the whole Unity.3D.RPG series. If this is a subject addressed later in the lesson plan (later than RPG.Core Combat: 11.3) I will defer my attempts until I have reached said lecture. Otherwise, heckle-on Hecklers!

Update.

Clearing the list in OnUnitSelected is a terrible idea. We got some action after I stepped on this coiled pile of obvious. Still got some kinks to work out so I am still keeping this topic open for until I am satisfied.

And twenty minutes later I am pulling the trigger. Solved. If you replace the method
Formation.OnUnitSelected() with this newer, shinier, works-even-betterer version:

void OnUnitSelected(object sender, EventArgs e)
 {
     if (Selector.Instance.GetSelectedPlayersList().Contains(gameObject.GetComponent<PlayerControl>()) && 
         readyUnitList.Contains(unit) == false)
     {
         readyUnitList.Add(unit);
     }

     if (Selector.Instance.GetSelectedPlayersList().Contains(gameObject.GetComponent<PlayerControl>()) == false &&
         readyUnitList.Contains(unit))
     {
         readyUnitList.Remove(unit);
     }

     if (Selector.Instance.GetSelectedUnit() == gameObject.GetComponent<PlayerControl>())
     {
         currentRank = 0;
     }
     else
     {
         currentRank = rank;
     }

     SortUnitsByRank();
     index = 0;
 }

However, if anyone has some thoughts about how to make a formation (let’s say the Column formation) pivot on point, my eyes are wide and eager. To clarify I do not wish to rotate the individual units a direction but to rotate the alignment of the entire column.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms