So I have a foreach loop going on where my gameobjects within a list do something according to when they’re in a specific list, this all works fine. However there’s a problem where I want the gameobjects to do something once they’ve been removed from the list and I have no idea what the best approach would be, does anyone have any ideas how to go about this?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.AI;
public class DragTotemScript : MonoBehaviour
{
public float dragSpeed = 0.001f;
Vector3 lastMousePosition;
public Transform minYEmpty;
public Transform maxYEmpty;
public float totalDistance;
public float currentDistance;
public float totemDragAmount = 0;
public float currentPercent;
public Text totemPolePercentageText;
public float currentWorshippers;
public float worshippersSelectedFloat;
public List<GameObject> selectedWorshippers;
public void DragTotem()
{
Vector3 delta = Input.mousePosition - lastMousePosition;
Vector3 position = transform.localPosition;
position.y += delta.y * dragSpeed;
position.y = Mathf.Clamp(position.y, minYEmpty.transform.localPosition.y, maxYEmpty.transform.localPosition.y);
transform.localPosition = position;
lastMousePosition = Input.mousePosition;
totemDragAmount = transform.localPosition.y;
totalDistance = Vector3.Distance(minYEmpty.transform.position, maxYEmpty.transform.position);
currentDistance = Vector3.Distance(transform.position, minYEmpty.transform.position);
currentPercent = currentDistance / totalDistance * 100;
GetVillagersList getVillagersList = GetComponentInParent<GetVillagersList>();
currentWorshippers = currentPercent / 100 * getVillagersList.playerWorshippers.Count;
worshippersSelectedFloat = currentWorshippers;
int worshippersSelectedInt = (int)worshippersSelectedFloat;
totemPolePercentageText.text = currentPercent.ToString("n0") + "%";
selectedWorshippers = getVillagersList.playerWorshippers.GetRange(0, worshippersSelectedInt);
// Relevant foreach loop
foreach (GameObject selectedWorshipperObject in selectedWorshippers)
{
VillagerScript villagerScript = selectedWorshipperObject.GetComponent<VillagerScript>();
villagerScript.isVillagerGoingToWorshipSite = true;
// Boolean check to see if the villager is in the list? Then do something on the VillagerScript when it's not?
}
}
}
You should be able to see what happens here, I drag a gameobject up and down and it gets me an appropriate percentage of a list of gameobjects, in this case villagers, then they go and worship. As ever while I’m writing this post I just thought of a boolean check I could do now to see whether the these villagers are in the list so I may do that but let me know if I’m doing this wrong.
Oh wait, no nevermind I still need to have a check on whether the villager has been removed from the list and I don’t know how to do that.
Use the List<>.Contains method to see if it’s in the list?
…
If you need an event based thing where you get signaled when removed. You may want to create your own list that raises events when the list changes. System.ComponentModel.BindingList<> already does this, but that class might be a bit overkill.
[edit]
I see you write this comment in your code:
Thing is that comment is inside a for loop of the list. Clearly the villager is in the list, you’re looping the list right now.
What are you attempting to accomplish right now? Not in a “I want to see if a GO is in a List” but WHY you want to see if a GO is in a list.
So what happens is when I drag the totem up and down it gets a percentage of villagers in the list and then adds that percentage to the list, the list then cycles through and sends the villagers to the worship site. What I need now is make it so that when the villagers are removed from this list they then go back to what they were doing before.
I should have deleted the comment as I was sort of thinking about it while I was typing, a second list makes sense but I have no idea how I would implement that in the way I’m thinking of. Would list contains maybe work from the gameobject itself? Then that would probably be the best option for sending the villager on it’s way to go and do something else if it’s not worshipping.
There’s no code that removes anything from the list.
Do you mean you want to know if you call ‘GetRange’ again, if it’s not in that NEW list relative to the previous list that last time GetRange was called (the last time DragTotem was called). If that’s what you mean, hold onto the old list, get the new, and then compare the 2.
var oldlist = selectedWorshippers;
selectedWorshippers = getVillagersList.playerWorshippers.GetRange(0, worshippersSelectedInt);
foreach(var w in selectedWorshippers) oldlist.Remove(w);
//now oldlist only contains worshippers NOT in selectedWorshippers
Note this code assumes selectedWorshippers is never null. You will likely need to add that null safety check.
I think I get your explanation, I think I’m getting it and I’ll experiment with the implementation, I didn’t know I could use lists this way which is why I was struggling but this makes a lot more sense now. I’ll post the results of my implementation up because it should all work now with this method.
But yeah, you’re copying over the list to another list just before the current list changes aren’t you? That’s what I’ve been missing, I just need to do a foreach loop on the oldList and have all my villagers in that list reset and go back to what they’re doing now.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.AI;
public class DragTotemScript : MonoBehaviour
{
public float dragSpeed = 0.001f;
Vector3 lastMousePosition;
public Transform minYEmpty;
public Transform maxYEmpty;
public float totalDistance;
public float currentDistance;
public float totemDragAmount = 0;
public float currentPercent;
public Text totemPolePercentageText;
public float currentWorshippers;
public float worshippersSelectedFloat;
public List<GameObject> selectedWorshippers;
public void DragTotem()
{
Vector3 delta = Input.mousePosition - lastMousePosition;
Vector3 position = transform.localPosition;
position.y += delta.y * dragSpeed;
position.y = Mathf.Clamp(position.y, minYEmpty.transform.localPosition.y, maxYEmpty.transform.localPosition.y);
transform.localPosition = position;
lastMousePosition = Input.mousePosition;
totemDragAmount = transform.localPosition.y;
totalDistance = Vector3.Distance(minYEmpty.transform.position, maxYEmpty.transform.position);
currentDistance = Vector3.Distance(transform.position, minYEmpty.transform.position);
currentPercent = currentDistance / totalDistance * 100;
GetVillagersList getVillagersList = GetComponentInParent<GetVillagersList>();
currentWorshippers = currentPercent / 100 * getVillagersList.playerWorshippers.Count;
worshippersSelectedFloat = currentWorshippers;
int worshippersSelectedInt = (int)worshippersSelectedFloat;
totemPolePercentageText.text = currentPercent.ToString("n0") + "%";
var oldList = selectedWorshippers;
selectedWorshippers = getVillagersList.playerWorshippers.GetRange(0, worshippersSelectedInt);
foreach (GameObject w in selectedWorshippers) oldList.Remove(w);
foreach (GameObject w in oldList)
{
VillagerScript villagerScript = w.GetComponent<VillagerScript>();
villagerScript.isVillagerGoingToWorshipSite = false;
villagerScript.isVillagerWorshipping = false;
villagerScript.VillagerWander();
}
foreach (GameObject selectedWorshipperObject in selectedWorshippers)
{
VillagerScript villagerScript = selectedWorshipperObject.GetComponent<VillagerScript>();
villagerScript.isVillagerGoingToWorshipSite = true;
}
}
}
Nailed it! Thank you for the help! It’s working perfectly now, I need to do some tweaking in other behaviours but this is working very accurately, I love how my percentage maths is all blending in with it nicely too. Now when I set the totem to 50% it only sends 1 villager to the worship site out of 2 exactly like you’d expect.