[C#] Problem with not equal to the right variables in for loop

Hi, so i have a little problem, with not equal to the right variable properties.

This is the MobAI script

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(NavMeshAgent))]
public class MobAI : MonoBehaviour {
	
	MobCreator mc;
	public float health = 57f;
	public float minDamage = 5f;
	public float maxDamage = 10f;
	public float scale = 1f;
	public float attackSpeed = 1500f;
	public string runAnim;
	public string walkAnim;
	public string idleAnim;
	public bool attackable;

	float distance;
	int i = 0;
	NavMeshAgent nma;

	void Awake()
	{
		mc = GameObject.Find("_CREATORSCRIPTS").GetComponent<MobCreator>();
		nma = GetComponent<NavMeshAgent>();
	}

	void Start()
	{

	}

	// Update is called once per frame
	void Update () {
		distance = Vector3.Distance(GameObject.FindWithTag("Player").transform.position, transform.position);
		if(distance <= 15  distance > 2f)
		{
			nma.SetDestination(GameObject.FindWithTag("Player").transform.position);
		}

		for(int i = 0; i < mc.mobCreator.Count; i++)
		{
			Debug.Log("For start");
			health = mc.mobCreator[i].health;
			minDamage = mc.mobCreator[i].minDamage;
			maxDamage = mc.mobCreator[i].maxDamage;
			scale = mc.mobCreator[i].scale;
			nma.speed = mc.mobCreator[i].runSpeed;
			attackSpeed = mc.mobCreator[i].attackSpeed;
			runAnim = mc.mobCreator[i].runAnim;
			walkAnim = mc.mobCreator[i].walkAnim;
			idleAnim = mc.mobCreator[i].idleAnim;
			attackable = mc.mobCreator[i].attackable;
			Debug.Log("For end");
		}
	}
}

Then the mobcreator script(A script for easy making new mobs):

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

public class MobCreator : MonoBehaviour {

	[System.Serializable]
	public class Mob
	{
		public enum MobType
		{
			Normal,
			Elite,
			Boss
		}
		public enum MobTypeState
		{
			Hostile,
			Aggressive,
			Friendly
		}
		public enum MobDamageType
		{
			Physical,
			Ranged,
			PhysicalAndRanged,
			Fire,
			Arcane,
			Earth,
			Frost
		}

		public string name = "Unnamed";
		public float health = 57f;
		public float minDamage = 5f;
		public float maxDamage = 10f;
		public float scale = 1f;
		public float runSpeed = 4f;
		public float attackSpeed = 1500f;
		public GameObject mob;
		public string runAnim;
		public string walkAnim;
		public string idleAnim;
		public MobType mobType;
		public MobTypeState mobTypeState;
		public MobDamageType mobDamageType;
		public bool attackable;
	}

	public List<Mob> mobCreator = new List<Mob>();

	// Use this for initialization
	void Start () {
		GameObject mobTest = (GameObject)Instantiate(mobCreator[0].mob, GameObject.Find("MobSpawn").transform.position, Quaternion.identity);
	}
	
	// Update is called once per frame
	void Update () {
	
	}
}

Example to what i want:

I have 3 mobs in the mobcreator list, Thug, thief and rat
so i instantiate Thug, and the instantiated thug should have the variable properties from the thug in the list, but instead it does so the thug variable properties is equals to the last in the list which is the rat, so the thug has the rat properties which i don’t want, what i want is the thug has the thug properties and thief has the thief properties and rat has the rat properties, because it doesn’t really make sense if i have a thug with rat properties or a thief with rat properties :stuck_out_tongue:

So i appreciate any help i can get, and i appreciate tips on how i could make things better.

Also a screenshot below shows the list i have of the mobs

as far as i understand the code, you constantly re-set the values in the for loop, and if i get that right, you set it to the values of mobCreator[0] up to mobCreator[2] each frame, it ends on mobCreator[2] and renders that.

Yeah, but i’m not sure how i would do it so it does not do that

Something to try:

Make Mob a stand alone class.

Add this to it’s method list:

		public string ToString(){
			string s = "";
			s+="MobHealth: " + health.ToString() + "\n";
			s+="MobMinDamage: " + minDamage.ToString() + "\n";
			s+="MobMaxDamage: " + maxDamage.ToString() + "\n";
			s+="MobRunSpeed: " + runSpeed.ToString() + "\n";
			s+="MobAttackSpeed: " + attackSpeed.ToString() + "\n";
			s+="MobAttackable: " + attackable.ToString() + "\n";
			
			return s;
		}

Change the MobAI Update for part to something like this:

		for(Mob mob in mc.MobCreator){
			Debug.Log("For start");
			
			health = mob.health;
			minDamage = mob.minDamage;
			maxDamage = mob.maxDamage;
			scale = mob.scale;
			nma.speed = mob.runSpeed;
			attackSpeed = mob.attackSpeed;
			runAnim = mob.runAnim;
			walkAnim = mob.walkAnim;
			idleAnim = mob.idleAnim;
			attackable = mob.attackable;
			
			Debug.Log(mob.ToString());
			Debug.Log("For end");
		}

Hi, i did something a little bit easier

for(int i = 0; i < mc.mobCreator.Count; i++)
{
    Debug.Log("For start");
    if(this.gameObject.name == mc.mobCreator[i].name)
    {
        health = mc.mobCreator[i].health;
        minDamage = mc.mobCreator[i].minDamage;
        maxDamage = mc.mobCreator[i].maxDamage;
        scale = mc.mobCreator[i].scale;
        nma.speed = mc.mobCreator[i].runSpeed;
        attackSpeed = mc.mobCreator[i].attackSpeed;
        runAnim = mc.mobCreator[i].runAnim;
        walkAnim = mc.mobCreator[i].walkAnim;
        idleAnim = mc.mobCreator[i].idleAnim;
        attackable = mc.mobCreator[i].attackable;
        break;
    }
    Debug.Log("For end");
}

Just adding a if statement and a break, now it does what i want.
Thanks anyway :slight_smile:

@jolo309

for(int i = 0; i < mc.mobCreator.Count; i++)
{
    Debug.Log("For start");

    if(this.gameObject.name == mc.mobCreator[i].name)
    {
        health = mc.mobCreator[i].health;
        minDamage = mc.mobCreator[i].minDamage;
        maxDamage = mc.mobCreator[i].maxDamage;
        scale = mc.mobCreator[i].scale;
        nma.speed = mc.mobCreator[i].runSpeed;
        attackSpeed = mc.mobCreator[i].attackSpeed;
        runAnim = mc.mobCreator[i].runAnim;
        walkAnim = mc.mobCreator[i].walkAnim;
        idleAnim = mc.mobCreator[i].idleAnim;
        attackable = mc.mobCreator[i].attackable;
        break;
    }

    Debug.Log("For end");

}

You can also do

debug.log("for start")
for(...)
{
    if(!this.gameObject.name.equals(mc.mobCreator[i].name)) {continue;}
    health = ... (your block of assignments)...
}
debug.log("for end")

This will reduce nesting and accomplish the same end.

That being said, you might look into LINQ select queries to find your information, as it will save you a lot of loop control for this type of item.
(LINQ overview: Introduction to LINQ | Microsoft Learn)
(LINQ samples: http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b)

@bigmisterb

Please never use string concatenation like this:

public string ToString(){

            string s = "";
            s+="MobHealth: " + health.ToString() + "\n";
            s+="MobMinDamage: " + minDamage.ToString() + "\n";
            s+="MobMaxDamage: " + maxDamage.ToString() + "\n";
            s+="MobRunSpeed: " + runSpeed.ToString() + "\n";
            s+="MobAttackSpeed: " + attackSpeed.ToString() + "\n";
            s+="MobAttackable: " + attackable.ToString() + "\n";

            return s;

        }

Performance is horrid, especially in an update loop. If you actually need string data, do something like

var data = new StringBuilder();
data.Append("MobHealth ");
data.AppendLine(health.ToString());
(... the rest of your items following the same pattern)

Strings are immutable, so you’re creating multiple objects when you say stringvalue += “Some data” + some_other_data + “newline”

Also of note, when you do use a stringbuilder, don’t do concatination within the stringbuilder either, for the same reason as above.

(WRONG)
data.AppendLine(“Some String” + Envronment.Newline +“Some Other String”);

(Correct)
data.AppendLine(“Some String”);
data.AppendLine("Some Other String);

Thanks it works fine and does the exact same :slight_smile:
I’m going to look into LINQ too, thank you very much