I’m trying to write a script that grabs all the npc (tags: npcPrimary) gameObjects and then assigns then random roles.
To me it seems a good start would be to just get it working in the inspector where I pull all the objects by tag (works). And then create a list of NPC in the inspector with the various variables that I need to set.
Think Cluedo but in every game a different NPC is assigned the role of butler/spinster/murderer/holding a smoking gun.
What is see as far as the inspector looks good I just can’t for the life of me figure out how to assign gameObjects or any other variables in to the npcList.
Thanks!
What I’ve got so far, but this just errors:
"the name “npcGameObjectsPrefab’ does not exist in the current context”.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
public class npcConfigList : MonoBehaviour
{
[Header("Object Pulled with Tags")]
public List<GameObject> npcPrimary = new List<GameObject>(); //list of any objects - to be used below to grab all objects with a certain tag in the scene currently
public List<GameObject> npcPrimary2 = new List<GameObject>(); //list of any objects - to be used below to grab all objects with a certain tag in the project
[Header("Main Character Tracker")] //slot for the player
[Tooltip("No Use right now unless we're switching characters")]
public GameObject Player1;
//Create serialsed list for NPC
[System.Serializable]
public class npcList
{
[Header("Npc object")]
public List<GameObject> npcGameObjectsPrefab;
[Multiline]
public string Discription;
[Header("Npc Needs - Health(x), Hunger(y), Hibernate (z) ")]
public Vector3[] needs; //
public List<string> Proactive;
public List<string> Quests;
public List<string> Routine;
}
[Header("Npc Role Assignment")]
[Tooltip("Create NPC roles and Stats.")]
[SerializeField] //if you have a private variable you want visible in the spector you add serializeField
private npcList[] npcListArray;
// Start is called before the first frame update, but will be empty prior to game launch.
void Start()
{
}
void Reset() //placing code here updates inspector without launching game.
{
npcPrimary.AddRange(GameObject.FindGameObjectsWithTag("npcPrimary")); //all objects IN SCENE with tag
npcPrimary2.AddRange(Resources.FindObjectsOfTypeAll(typeof(GameObject)).Cast<GameObject>().Where(g => g.tag == "npcPrimary").ToList()); //ALL objects in scene AND project with tag - means duplicates for in scene items.
Player1 = GameObject.FindGameObjectWithTag("Player"); //sets player1 to the first object it finds with the tag "Player"
// Here is where I would like to assign each gameObject with the npcPrimary tag into the npclist class > npcGameObjectsPrefab
//Nothing I've tried has worked.
npcGameObjectsPrefab.AddRange(Resources.FindObjectsOfTypeAll(typeof(GameObject)).Cast<GameObject>().Where(g => g.tag == "npcPrimary").ToList());
}
// Update is called once per frame
void Update()
{
}
}
Hi ippdev, first thanks for taking the time to respond.
The thing is I’m a visual guy - in the game there will be more than a few npc’s. Each npc has at least 5 variables associated to them so we’re talking about a minimum of 20 variables if there are only 4 npcs. I’d like to be able to review in the inspector if the variables I’ve assigned each npc have worked correctly in a single place (vs going to each npc and checking).
I might be misunderstanding but I’m not sure having a long list of variables will give me the sort of easy to overview inspector that I was hoping for.
I’ve spent quite some time on google and forums - maybe I just don’t know the correct phrases to look for but it really does seem hard to find out how to assign something into a class.
Thanks.
That should work. Since you didn’t say what was actually wrong, I’ll give details: You should be seeing npcListArray in the Inspector. Pop it open (the triangle thingy) and give it a size. Popping open one of the items should show npcGameObjectsPrefab, discription, and so on. Popping open npcGameObjectPrefab should give for a size. Giving that a size one should make empty slots appear saying (gameObject) where you can just drag them in.
There may be some syntax issue or a glitch. You might try simplying it: commenting out the headers, making things public, until it works. Or you could make a test. This works for me:
[System.Serializable]
public class ZZZ {
public string w;
public List<GameObject> N;
}
public ZZZ[] ZZZZ;
I would make a component with each of the variables you want and drop that on the NPC’s. If you want to set a field or grab a value you query the component. Then your List is simply that and all the variables you get or set are available by getting the member of the List and accessing the public variables…
Hello Owen-Reynolds, I afraid you’ve missed the question. I’m aware of how to open and the pop up (triangle) (I hope what I write doesn’t come across as sarcastic - I really don’t mean to). Most of the code works fine. I’m trying to automatically populate the fields in the public class npcList using code (not manually drop them in), in this case taking the gameobjects with the “npcPrimary” tag and placing those into the public class npcList → public List npcGameObjectsPrefab;
The code works when finding gameObjects with the desired tag.
Placing gameObjects with the desired tag in the parent class (public List npcPrimary) also works without issue.
But getting any strings / variables / int / gameObjects into the child class (public class npcList) seems impossible.
If you aren’t doing it already, you need to initialize all of the lists and arrays within the npcList class. Example:
[System.Serializable]
public class npcList
{
[Header("Npc object")]
public List<GameObject> npcGameObjectsPrefab = new List<GameObject>();
[Multiline]
public string Discription;
[Header("Npc Needs - Health(x), Hunger(y), Hibernate (z) ")]
public Vector3[] needs; //
public List<string> Proactive = new List<string>();
public List<string> Quests = new List<string>();
public List<string> Routine = new List<string>();
}
You could also do this with a constructor method, or manually after creating a new instance if you want.
Edit: After more carefully reading your original post, the issue is that you aren’t referencing your npcList object when trying to assign the list of prefabs. Note that the code below assumes you made the initialization change from above. If you don’t, you will have to initialize those inner arrays too.
void Reset() //placing code here updates inspector without launching game.
{
npcPrimary.AddRange(GameObject.FindGameObjectsWithTag("npcPrimary"));
npcPrimary2.AddRange(Resources.FindObjectsOfTypeAll(typeof(GameObject)).Cast<GameObject>().Where(g => g.tag == "npcPrimary").ToList());
Player1 = GameObject.FindGameObjectWithTag("Player");
// npcListArray is never initialized in your code, so I'll do it here
npcListArray = new npcList[1]();
// npcListArray is empty, we need a new object to add to it.
npcListArray[0] = new npcList();
// Now we can populate the field of npcList. We created an instance above, so we can now refer to it.
npcListArray[0].npcGameObjectsPrefab.AddRange(Resources.FindObjectsOfTypeAll(typeof(GameObject)).Cast<GameObject>().Where(g => g.tag == "npcPrimary").ToList());
}
Thanks WallaceT_MFM, this almost works.
The line npcListArray = new npcList1;
Causes an error (CS0149:Method name expected.
I got around this by adding private const int COUNT = 1; //needed to force size
at the top of the parent class and then changing
[Header(“Npc Role Assignment”)]
[Tooltip(“Create NPC roles and Stats.”)]
[SerializeField] //if you have a private variable you want visible in the spector you add serializeField
private npcList[ ] npcListArray;
to
[Header(“Npc Role Assignment”)]
[Tooltip(“Create NPC roles and Stats.”)]
[SerializeField] //if you have a private variable you want visible in the spector you add serializeField
public npcList[ ] npcListArray = new npcList[COUNT]; //Force size 1
At this point, there are no errors BUT instead of adding just 1 npc object, you have added the whole list.
So I’ve changed
npcListArray[0].npcGameObjectsPrefab.AddRange(Resources.FindObjectsOfTypeAll(typeof(GameObject)).Cast().Where(g => g.tag == “npcPrimary”).ToList()); //Adds all the objects.
to
npcListArray[0].npcGameObjectsPrefab.Add(GameObject.FindGameObjectWithTag(“npcPrimary”)); //Adds a single the object.
Now there are no errors and I just need to figure out how to read / loop through my “npcPrimary” game objects and input 1 at a time.
At any rate, I feel a lot closer now - thanks.
And thanks to everyone else on this thread for taking the time to help me - it is VERY much appreciated!!
D’oh, I always forget the right array syntax, silly me.
You could do something like this to get them one at a time and the add to the npcListArray:
List<GameObject> prefabList = Resources.FindObjectsOfTypeAll(typeof(GameObject)).Cast<GameObject>().Where(g => g.tag == "npcPrimary").ToList();
npcListArray = new npcList[prefabList.Count];
for(int i = 0; i < prefabList.Count; i++)
{
npcList listI = new npcList();
listI.npcGameObjectsPrefab.Add(prefabList[i]);
// Maybe fill the other fields here
npcListArray[i] = listI;
}