Good afternoon guys, such a question, I'm doing an array with brute force. I can't understand why assigning a value from the last element of the FrezeTree array to the BufferObject works in the Start() method, but this does not happen in Update. So. At the start of the scene, there is a search for all objects with the Tree tag (This is a temporary and debag solution):
FrezeTree = GameObject.FindGameObjectsWithTag("Tree");
Then, this list is passed to the array:
public GameObject[] FrezeTree;
Next, I'm trying to pass one element from the array to another object (This happens in the Start() method):
foreach (GameObject gm in FrezeTree)
{
BufferObject = gm;
}
But it turns out that only the last element is transmitted (Because of My own crookedness, since I don't know how to fix it yet). Why do I need a Buffer Object? From it I get the X position of the object, which I use for other purposes. The idea is to transfer one element from the array to the object, and when the object ceases to exist (Gets the null status), it goes to the element above / below (No matter in what order). Yes, I know that in what I have given above and I do not feel that I am trying to make a transition or skip an element from the array. I found various solutions on the great Internet, but the result was always the same, gets the last element and does not choose another one. That's why I turned here.
CodePudding user response:
As I understand you want to
- set one closest target object
- wait until it is destroyed
- go to the next closest target object
You could do this by simply checking whether the BufferObject is already set and still alive like e.g.
using System.Linq;
...
public GameObject BufferObject;
private void Update ()
{
// This means BufferObject is either not assigned yet or was destroyed
if(!BufferObject)
{
BufferObject = FindClosestTarget();
}
}
private GameObject FindClosestTarget ()
{
// Get all currently existing trees
// since this happens only once in a while it should be okey to repeat this call
return GameObject.FindGameObjectsWithTag("Tree")
// order them by distance
.OrderBy(gm => (transform.position - gm.transform.position).sqrMagnitude)
// get the first one or null if there was none
.FirstOrDefault();
}
This way it would also take trees that are spawned later into account.
If you rather want to cache this array only once you can still do this like
private GameObject [] trees;
public GameObject BufferObject;
private void Start ()
{
trees = GameObject.FindGameObjectsWithTag("Tree");
}
private void Update ()
{
// This means BufferObject is either not assigned yet or was destroyed
if(!BufferObject)
{
BufferObject = FindClosestTarget();
}
}
private GameObject FindClosestTarget ()
{
// First filter out any null or destroyed objects
return trees.Where(t => t)
// Then order the rest by distance
.OrderBy(gm => (transform.position - gm.transform.position).sqrMagnitude)
// Then pick the first one or null if there isn't any
.FirstOrDefault();
}
See
CodePudding user response:
In general, I figured out how to implement everything myself. So, the code:
public GameObject[] FrezeTree; //Array of all objects in the scene
private void Start()
{
FrezeTree = GameObject.FindGameObjectsWithTag("Tree"); //Finding all objects with a tag (I do not recommend using tags due to the lack of code navigation)
}
private GameObject FindClosestTarget()
{
return False True.Where(t => t).FirstOrDefault(); //Assigning and sorting an array with objects from the scene, thanks @derHugo
}
void Update()
{
BufferObject = FindClosestTarget(); //will be Assigned the next element of the array, in case the current will become "null"
if (BufferObject == null)
{
Debug.Log("debug for (BufferObject == null)"); //arbitrary code in the case that any object on the stage left.
}
}
P.S. This code is perfect for creating a simple AI for NPCs in your game. It's not perfect, but at least something is better than nothing :) Thanks @derHugo
