I am currently working on a foxes & rabbits simulation, and I am completely stuck on "breeding".
The way I have built the simulation, three scripts are used; “TheGame”, “FoxScript” and “RabbitScript. Since the foxes and rabbits are essentially the same, we can reduce these three to two scripts; “RabbitScript” and “TheGame”. The RabbitScript is attached to the respective prefab; the “rabbitPrefab”, whereas TheGame is attached to an empty GameObject.
TheGame instantiates a number of RabbitPrefabs, which then move, age and breed. Since the build is supposed to collect and present data at a later stage, the rabbits are included in a list as well as being counted. This list is found in the main script, and when the rabbits breed, the offspring needs to be included in this list as well as adding to the counter.
I have tried instantiating a primitive with this method, and it works.
The Breed function in the script attached to the rabbits:
void Breed(){
float p = Random.Range (0.0f, 1.0f);
if (p < probability2breed) {
position = gameObject.transform.position;
TheGame.BreedRabbit(position);
}
}
And the BreedRabbit method in TheGame script:
public static void BreedRabbit(Vector3 position) {
GameObject rabbit = Instantiate(RabbitPrefab) as GameObject;
rabbit.transform.position = new Vector3(position);
Rigidbody gameObjectsRigidBody = rabbit.AddComponent<Rigidbody>();
rabbit.GetComponent<Rigidbody>().useGravity = false;
rabbit.name = "Rabbit#:" + rabbitCount;
rabbit.tag = "rabbittag";
rabbits.Add(rabbit);
rabbitCount++;
}
NOTES: (I figure a lot of this code seems pointless, so to answer any questions about that beforehand: I use collider to handle interactions between the agents involved, and to my understanding this calls for a rigidbody. With rigidbody they started falling, even without mass, so I had to turn of gravity. The tags are to my understanding needed for collision handlig as well.I could probably skip the count and just count the list, but this shouldn't matter now)
It keeps asking for an object reference , and I just can't figure out how this can be solved?
THe error message: "an object reference is required for the nonstatic field method or property"
I'd assume the object reference error occurs on this line?:
GameObject rabbit = Instantiate(RabbitPrefab) as GameObject;
If this is the case, it may be because the prefab hasn't been set, i.e, the script doesn't know what RabbitPrefab is.
You could set a variable in the script, and then drag your prefab onto the corresponding slot into the inspector:
public GameObject theRabbitPrefab;
GameObject rabbit = Instantiate(theRabbitPrefab) as GameObject;
If this is not the case, can you edit your question to where you are getting the error? Surely the error states which line of code the error is being generated from? :)
Edit: From Diego, if this is the case, you can add the rigidbody and configure it in your prefab, and you won't need to do it in the code for every new rabbit!
Related
BreakableObject script is a foreign script that came attached to describe how barrels exploded. When those barrels explode, I want a new object to pop up in their place. So I've added the following to the top of the code:
public class BreakableObject:MonoBehaviour{
public GameObject gamePiece2;
One of the methods in this class, which houses the overall process, is coded as follows. Unimportant lines have been dashed out.
public void triggerBreak() {
//if(transform.parent.CompareTag("Winner"))
//{
//Destroy(transform.FindChild("object").gameObject);
//Destroy(transform.GetComponent<Collider>());
//Destroy(transform.GetComponent<Rigidbody>());
//StartCoroutine(breakObject());
//foreach (Transform child in transform.parent)
//{
// GameObject.Destroy(child.gameObject);
//}
//animalSpawn = Random.Range(0, 4);
Instantiate(gamePiece2, transform.position, Quaternion.identity);
}
}
Lastly, I have verified (with 'Find References in Scene') that this script is only applied to one empty Game Object titled 'Animal Array' and that I have assigned a reference object in the inspector, as seen the attached picture.
Nonetheless, I still get an 'UnassignedReferenceException' saying that gamePiece2 of BreakableObject has not been assigned. Any thoughts?
#UnholySheep: My main script is called game manager. This is a side script defining when a barrel will explode. My goal is to have it instantiate an object where the barrel was right when it explodes. It seems easiest to do that in the barrel script.
This image is where I thought I assigned it
I have a gameObject as a sprite in my 2D game, and then in a different script I have an array of 2d textures, in a sprite array. I simple want to change the sprite's sprite property but get the error 'object reference not set to an instance of a object'.
Here is the line throwing the error, which is in one script.:
this.gameObject.GetComponent<SpriteRenderer> ().sprite = GameObject.Find ("UIM").GetComponent<Manager> ().spriteImages [1];
While the array, is in a different script, attached to the object 'UIM' in a different scene to the one I am trying to access it from (not sure if this causes the problem), is defined with:
public Sprite[] spriteImages = new Sprite[5];
Why am I getting this error? I have filled the array with the textures so cannot see the problem.
You are trying to access a script & variable from another scene. In unity whenever you load a new scene your old scene values will be destroyed and that will lead to 'object reference not set to an instance of a object' error. You can bring the tell the unity not to destroy the object which you will need in future scenes by calling DontDestroyOnLoad. This will allow the gameobject to persist across the scene.
One more thing you have to keep in mind is that if you are returning to the old scene where you marked the Object UIManager as dontdestroyonload then make sure the next instances are deleted and managed from the scene which is reloaded else whenever you keep on reloading the old scene with UImanager it will keep on piling up the instances of it across the scenes. The example in the unity with dontdestroyonload should be more than enough to solve your problems. Here is a snippet shown in Unity API which you can refer:
void Awake()
{
GameObject[] objs = GameObject.FindGameObjectsWithTag("music");
if (objs.Length > 1)
{
Destroy(this.gameObject);
}
DontDestroyOnLoad(this.gameObject);
}
You can try:
public GameObject[] objs =
SceneManager.GetSceneByName(sceneToLoad).GetRootGameObjects();
foreach(GameObject go in objs)
{
if(go.name == "UIM")
{
this.gameObject.GetComponent<SpriteRenderer> ().sprite =
go.GetComponent<Manager> ().spriteImages [1];
break;
}
}
I am trying to develop a small 2D Unity platformer to learn to work with Unity's interface. I have been having an issue trying to make a gameobject track clones of an enemy and follow it. The function is to make it so when you hover on the enemy clone, it shows the enemy's health. But when I hover on the enemy, it tracks the position of the original enemy, not the clone. Both gameobjects have the same name. What I want is the GameObject HoverDataDisplay (as shown in the screenshot) to track its sibling, Enemy.
The current code that I have for the tracking script is as shown:
private GameObject Enemy;
void Start() {
Enemy = GameObject.Find ("Enemy");
}
void Update(){
transform.position = new Vector3 (Enemy.transform.position.x - 0.57f, Enemy.transform.position.y + 1.5f, Enemy.transform.position.z);
}
But the GameObject (HoverDataDisplay) Only follows the original enemy.
Thanks for your help!
In Unity, you can use the forward slash "/" to find a Child of an Object. Since the name of the parents are different, you can easily find them like this:
GameObject.Find("EnemyObject/Enemy");
And the second HoverDataDisplay:
GameObject.Find("EnemyObject(Clone)/Enemy");
It's not really a good idea to let your GameObject use the default "Clone" name. You should rename it after instantiating it so that it will be easy to find. Only do this if you need to find the Object after instantiating it.
This script is attached to the HoverDataDisplay GameObject
You can actually get it's parent Object which is either EnemyObject or EnemyObject(Clone) with transform.parent then use the FindChild to find the enemy Object.
//First, Find the Parent Object which is either EnemyObject or EnemyObject(Clone)
Transform parent = transform.parent;
//Now, Find it's Enemy Object
GameObject enemy = parent.FindChild("Enemy").gameObject;
I recommend you use this method instead of the first one I mentioned. The first one is mentioned so that you will know it can be done.
EDIT:
Transform.FindChild is now deprecated. You can use Transform.Find to do that same exact thing.
You can get a reference to the parent then search through the parents children
// get a reference to the rb of the parent
parentRigidbody = gameObject.GetComponentInParent<Rigidbody>();
// a reference to the camera in a sibling object
playerCam = rigRigidbody.gameObject.GetComponentInChildren<Camera>();
I'm trying to have my game spawn enemies when ever the player reaches a way point.
Right now, I have this functionality working. When my player gets to the first way, the enemies spawn. He only moves on once he has killed all of the enemies on the screen are dead. However, when he gets to the second way point, no enemies spawn.
Right now, in my collision class I call the following line of code:
Destroy(gameObject)
Whilst this work for the first way point, the second one wont spawn anything as the game object my collision class has been attached to has been destroyed. However, all of my enemies are prefabs and I thought the destroy function would only destroy that instance of the prefab. No matter when you called the instantiate method, it would only destroy that instance.
I'm spawning my enemies with the following method:
public GameObject SpawnEnemies()
{
Vector3 _position = new Vector3(transform.position.x, transform.position.y, transform.position.z);
// instantiate particel system
Instantiate(_particle, _position, Quaternion.identity);
_clone = (GameObject)Instantiate(_enemy, _position, transform.rotation);
_ai = _clone.GetComponent<HV_BaseAI>();
_ai._waypoints = _wayPoints;
return _clone;
}
Then I'm finding out how many of the enemies are still alive with the following code in my collision method:
GameObject g, f; // enemies I want to spawn
g = GameObject.FindGameObjectWithTag("SectionController");
f = GameObject.FindGameObjectWithTag("SectionController");
HV_SectionController tempSectionControllerGroundEnemies, tempSectionControllerFlyingEnemies;
tempSectionControllerGroundEnemies = g.GetComponent<HV_SectionController>();
tempSectionControllerFlyingEnemies = f.GetComponent<HV_SectionController>();
tempSectionControllerGroundEnemies._numberOfGroundEnemies.Remove(gameObject); // remove enemies from list
tempSectionControllerFlyingEnemies._numberOfFlyingEnemies.Remove(gameObject);
//Destroy(gameObject);
_numberOfGroundEnemies = tempSectionControllerGroundEnemies._numberOfGroundEnemies.Count;
_numberOfFlyingEnemies = tempSectionControllerFlyingEnemies._numberOfFlyingEnemies.Count;
Then when I want to move on I do the following check:
if (_groundEnemiesRemaining == 0)
{
MoveToNextSection();
_sectionStartTime = Time.time;
}
i know the above line is checking only one type of enemy at the moment, but its the ground enemies I'm having issues with at the moment.
Does anyone know how I can delete the enemy prefab I'm spawning from my first section, once they've been hit, then have it respawn at the next section without the error:
The object of type 'GameObject' has been destroyed but you are still
trying to access it.
My guess would be that the gameobjects are being "destroyed" by two different collision events. First one destroys it, second throws the error.
What I've done in similar situations is put the Destroy code within the object being destroyed. Then from within your collision class, use gameObject.SendMessage(string) to send a message to the actual object, which destroys it.
Without seeing further code I can't speculate as to the origin of the error, but the above is my best guess. SendMessage can also take a DontRequireReceiver parameter, so it won't pop an error if two collision events try to send it a message.
Instead of destroying them u can just disable them using gameObject.SetActive() !
GameObject enemy = Instantiate(spawnObject,spawnPosition,spawnObject.transform.rotation) as GameObject;
enemy.transform.parent = transform;
The above code generates the expected result when I test my game in game mode, however I'm gettting this error message:
"Setting the parent of a transform which resides in a prefab is disabled to prevent data corruption."
Yes, the spawnObject variable contains a prefab, however creating a new GameObject should have fixed the problem, I assume?
Check if your "transform" variable is actually from a gameobject and not from a prefab.
var transform = somePrefab.transform;
enemy.transform.parent = transform; // this won't work
var transform = someOtherGameObject.transform;
enemy.transform.parent = transform; // this will
Maybe you could give some more information about where that transform variable of yours comes from.
I've been seeing this issue as well - an instantiated GameObject (not the prefab) giving this error message. My GameObject (A) had been parented into the middle of another instantiated GameObject (B) of a different type. I wanted to reparent A into another part of B - which would fail with the given error. My only solution has been to first reparent A to null, then reparent into B again.