iam quite new (first post… ) to Unity and programming and I hope you can help me with the following problem:
I want to find the GameObject with the greatest Y-Value and tag “Filling” and assign it to GameObject highestFilling.
This is what I got so far:
using UnityEngine;
using System.Collections;
using System.Linq;
public class FindHighestFilling : MonoBehaviour {
void Update ()
{
GameObject[] fillings = GameObject.FindGameObjectsWithTag ("Filling");
GameObject highestFilling;
fillings = fillings.OrderBy(filling => filling.transform.position.y).ToArray();
// Here is where I struggle...How can I assign highestFilling to the GameObject with the highest y?
}
}
You’ve already done the hardest part. After you sort the array, your highest object should be either the first or the last object in the array depending on how the sorting algorithm works (I’m assuming last).
If first:
highestFilling = fillings[0];
If last:
highestFilling = fillings[fillings.Length-1];
As an aside, if you’re doing other things with this sorted array then carry on, but “sorting an array” is a lot more CPU-time-consuming than “finding the largest value of an array” and this would be an opportunity for optimization. (For that matter, FindGameObjectsWithTag is not great for speed either.) This is a typical algorithm I use to find the highest/lowest value in an array:
GameObject[] fillings = //your array here
GameObject highestFilling = null;
float highestFillingPosition = -99999f; //start with a value that could never be higher than all your objects
for (int f=0;f<highestFilling.Length;f++) {
float thisY = fillings[f].transform.position.y; //cache this, because calculating it twice is also slower than need be
if (thisY > highestFillingPosition) {
highestFillingPosition = thisY;
highestFilling = fillings[f];
}
}
Sorry for my slow response - busy week
Thanks for your code! Problem solved
But I got another related question:
How do I change the color of the fillings object that is currently the highestFilling (and change it back, once it’s no the highest anymore)?
You can have a property on your FindHighestFilling script:
public class FindHighestFilling
{
public Color highlightedColor;
public Color defaultColor;
private GameObject m_highestObj = null;
public GameObject HighestObject
{
set
{
OnChangeHighestObject(m_highestObj, value);
m_highestObj = value;
}
get
{
return m_highestObj;
}
}
void OnChangeHighestObject(GameObject oldValue, GameObject newValue)
{
if (oldValue != null && oldValue != newValue)
{
ColorScript script = oldValue.GetComponent<ColorScript>();
if (script != null)
{
script.color = defaultColor;
}
}
if (newValue != null && newValue != oldValue)
{
ColorScript script = newValue.GetComponent<ColorScript>();
if (script != null)
{
script.color = hightlightedColor;
}
}
}
}
Once you set the new value, old value will have its color changed. Of course, I placed ColorScript as you didn’t mention how you change colors, via script or material so you have to manually fix that.
using UnityEngine;
using System.Collections;
using System.Linq;
public class FindHighestFilling : MonoBehaviour {
public Color highlightedColor;
public Color defaultColor;
private GameObject m_fillingObj;
public GameObject HighestFilling
{
set
{
OnChangeHighestObject(m_fillingObj, value);
m_fillingObj = value;
}
get
{
return m_fillingObj;
}
}
void Update ()
{
FindHighest ();
}
void FindHighest()
{
GameObject[] fillings = GameObject.FindGameObjectsWithTag ("Filling");//your array here
float highestFillingPosition = -99999f; //start with a value that could never be higher than all your objects
for (int f=0;f<fillings.Length;f++)
{
float thisY = fillings[f].transform.position.y; //cache this, because calculating it twice is also slower than need be
if (thisY > highestFillingPosition)
{
highestFillingPosition = thisY;
HighestFilling = fillings[f];
}
}
}
void OnChangeHighestObject(GameObject oldValue, GameObject newValue) // Do I have to ad
{
if (oldValue != null && oldValue != newValue)
{
HighestFilling.GetComponent<SpriteRenderer>().color = defaultColor; // is this correct to change the color via the SpriteRenderer?
}
if (newValue != null && newValue != oldValue)
{
HighestFilling.GetComponent<SpriteRenderer>().color = highlightedColor;
}
}
}
Compiling yields the following error message:
NullReferenceException: Object reference not set to an instance of an object
FindHighestFilling.OnChangeHighestObject (UnityEngine.GameObject oldValue, UnityEngine.GameObject newValue) (at Assets/Scripts/FindHighestFilling.cs:54)
FindHighestFilling.set_HighestFilling (UnityEngine.GameObject value) (at Assets/Scripts/FindHighestFilling.cs:15)
FindHighestFilling.FindHighest () (at Assets/Scripts/FindHighestFilling.cs:40)
FindHighestFilling.Update () (at Assets/Scripts/FindHighestFilling.cs:27)
void OnChangeHighestObject(GameObject oldValue, GameObject newValue) // Do I have to ad
{
if (oldValue != null && oldValue != newValue)
{
oldValue.GetComponent<SpriteRenderer>().color = defaultColor;
}
if (newValue != null && newValue != oldValue)
{
newValue.GetComponent<SpriteRenderer>().color = highlightedColor;
}
}
In your previous code you were calling the property, which returned null at that time obviously. Idea behind this function is to change first game objects color to default, and seconds color to highlighted. If you noticed in your previous code, you weren’t using your parameters at all!