Transform List not updating position of prefab.

my code is supposed to spawn prefab objects every couple of seconds. Those spawned prefabs are then to move towards different prefab objects (endPoints) already in the world. those endPoint objects are slowing moving and that is where the problem arises. The spawned prefabs do not update the position of the endPoints, so they end up traveling towards the starting position of the endPoints. The problem might be my poor understanding of lists because I have an enemy prefab that uses the same moveTowards code as the one located on the neutralAIMovement script to follow my player prefab without any issue.

I am using a for loop to iterate through each element in the factionRelationship list while at the same time passing the i value to the index variable listNumber located on the neutralAIMovement script.

One thing I did try is to start my scene with the prefab that will travel towards endPoint already in the world as opposed to instantiating it every couple of seconds. This gave the same result. Any help would be appreciated. Thanks in advance.

public class TradingAndTradeShips : MonoBehaviour
{
    public List<float> factionRelationship = new List<float>();
    public NeutralAIMovement tradeShipScript;
    public GameObject tradeShip;
    public float waitToSpawn;
    public int factionNumber;
    private bool continueLoop;

    void Start()
    {
        continueLoop = true;
        StartCoroutine(SpawnTradeShip());
    }
    IEnumerator SpawnTradeShip()
    {
        
        while (continueLoop)
        {
            for (int i = 0; i < factionRelationship.Count; i++)
            {
                if (factionRelationship *>= 50f)*

{
tradeShipScript.listNumber = i;
GameObject tradeObj = Instantiate(tradeShip, new Vector3(transform.position.x, transform.position.y, tradeShip.transform.position.z), tradeShip.transform.rotation);
}
yield return new WaitForSeconds(waitToSpawn);
}
}
}

public class NeutralAIMovement : MonoBehaviour {
public List tradeEndPointList = new List();
public TradingAndTradeShips homeRelationship;
public int listNumber;
public float speed, rotationSpeed;
void Start () {

}

void Update ()
{
Debug.Log(tradeEndPointList[listNumber].position);
transform.position = Vector2.MoveTowards(transform.position, tradeEndPointList[listNumber].position, speed * Time.deltaTime);
}

I think the problem is that the objects whose references are contained in your tradeEndPointList are not having their positions updated.

I would expect that somewhere you would have some code which does something like tradeEndPointList[index].position = someNewPosition; but it is not obvious from the code that you have provided.

If the tradeEndPointList is meant to be a list of prefabs with which to generate endpoints, then consider making a new list of the instantiated endpoint prefabs, but make sure that somewhere you are updating the endpoints.

It turned out that the problem was that the NeutralAIMovement component’s tradeEndPointList variable was assigned in the prefab, which means they were not the same objects as the ones in the scene. One solution is to group the end point instances under an empty game object, gather them in a script, then get that list from the script and assign it to the NeutralAIMovement when instantiating the tradeShip. In fact TradingAndTradeShips can just get the reference to the script once, and use it whenever instantiating a trade ship.

However, the logic can be greatly cleaned up if we analyse the required functionality. There are 3 main logic elements: instantiating trade ships, keeping track of trade end points, and moving towards your trade end point. Each can be separated from each other, and using references of the correct type, the code will be faster, simpler, and cleaner.

public class TradeEndPoints : MonoBehaviour {

    // you can set up the end points manually on an instance of the script in the scene, or with code - see Awake() method below
    [SerializeField] private List<Transform> tradeEndPoints = new List<Transform>();
    public Transform GetTradeEndPoint (int index) { return i < tradeEndPoints.Count ? tradeEndPoints *: null; }*

private void Awake () {
// you can automatically set it up if there is nothing assigned from Editor with this condition
if (tradeEndPoints.Count == 0) {
Transform[] childTransforms = GetComponentsInChildren();
if (childTransforms != null) { tradeEndPoints.AddRange(childTransforms); }
}
}

}

// it would be better to call this class TradeShipSpawner - because that’s what it does
public class TradingAndTradeShips : MonoBehaviour {

// alternative approach is to set up this list with values in an instance of the script in the scene
// [SerializeField] private List tradeEndPoints = new List();

// assign this value in the Editor to an instance of this script
[SerializeField] private TradeEndPoints tradeEndPoints = null;

[SerializeField] private NeutralAIMovement tradeShipPrefab = null;
[SerializeField] private float waitToSpawn;
[SerializeField] private List factionRelationship = new List(); // remember to set up the faction relationships; I suspect that you will need a separate class for this in the future

// public int factionNumber; // I removed factionNumber variable, because you don’t use it
private Coroutine spawnTradeShipsCoroutine;

private void Start () {
// instead of a bool flag you can use the actual Coroutine object returned from StartCoroutine() and call StopCoroutine() on it when you want to stop it
spawnTradeShipsCoroutine = StartCoroutine(SpawnTradeShips());
}

private IEnumerator SpawnTradeShips () {
while (true) {
for (int i = 0; i < factionRelationship.Count; ++i) {
if (factionRelationShip > 50) {
Transform tradeEndPoint = tradeEndPoints.GetTradeEndPoint(i);
if (tradeEndPoint != null) { // make sure the trade end point exists
// you can instantiate using a component on a prefab and you automatically get a reference to the component! Very useful, and spares you a GetComponent() call
NeutralAIMovement tradeShip = Instantiate(tradeShipPrefab); // don’t need to specify position and rotation if you want to use the values from the prefab
tradeShip.SetTradeEndPoint(tradeEndPoint);
}
}
}
// I think you wanted to check all relationships and then wait, not wait between each check :wink:
yield return new WaitForSeconds(waitToSpawn);
}
}

}

public class NeutralAIMovement : MonoBehaviour {
[SerializeField] private float speed = 0;
// with the help of storing this variable, you don’t need the index nor the list anymore
private Transform tradeEndPoint;
public void SetTradeEndPoint (Transform value) { tradeEndPoint = value; }

private void Update () {
if (tradeEndPoint != null) {
// slightly more refined debug printout
Debug.Log(“NeutralAIMovement "” + name + "" target position: " + tradeEndPoint.position);
transform.position = Vector2.MoveTowards(transform.position, tradeEndPoint.position, speed * Time.deltaTime);
}
}

}