UnassignedReferenceException but it seems clearly assigned? - c#

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

Related

Unity Referencing an Instantiated (cloned) object on a Button via Script

My Problem:
I cant get it to work, that every Building has its own SpawnPoint.
I'm working on an RTS like build mechanism. I have set it up that after pressing a key I can place buildings in the scene. The buildings get instantiated from a prefab and after they get instantiated they get a script called "BuildingScript" attached to them. Now i want to implement, so that i get a individual spawn point for every building (for now just next to it). I got a UI set up with a button, which by pressing spawns a unit at the building.
I had the "BuildingScript" attached to the prefab, but when i set the spawn point for one Building, it set it for every Building in the Scene. So a Unit was Spawned always at the same Buidling.
I want to set it up, that every Building has its own spawn point. Thats why I want to give every Building the script "BuildingScript" when Instatiated, because I hope, that this way every script gets handled individually. Is that right? Or will it still set the same point for every building, because the script is still the same?
Also I wanna reference the current placed building to the button, so when its clicked, it will run only the code of the last placed building (for now). I think I cant do this by using "On Click()" Of the Button, because my clone isnt Instatiated yet, so I have to reference the clone to the button somehow via Script, so the button works with the clone.So my problem is, that I need to set a reference from my cloned Building to the Button, after I placed the clone.
I googled a lot on how to do this, but didnt found any answers to my problem besides this https://forum.unity.com/threads/controlling-instantiated-game-objects-from-ui-buttons.332005/.
But I cant get it to work and I think it will not work because my clone is an Object and not a GameObject, so I could never set reference to it to call the funktion SpawnUnit(), because GetComponent only works for a GameObject.
Now I'm really at a point where I just don't know how Unity handles these kind of things.
BuildingScript on the Instantiated Building
public class BuildingScript : MonoBehaviour
{
public bool SavePos = false;
public Vector3 SpawnPoint;
public Vector3 BuildingPos;
public GameObject Unit;
void Start()
{
FindObjectOfType<SpawnButtonReference>().GiveReference(this);
}
public void SpawnUnit()
{
//I did this because if a building gets instatiated i wanted it to save its
Position to Spawn Units from it (doesnt really work though).
"MousePos" ist the last Position of the Mouse in the PlacementScript, before klicking to place the building.
if (SavePos == false)
{
BuildingPos = GameObject.FindObjectOfType<GroundPlacementController>().GetComponent<GroundPlacementController>().MousePos;
Debug.Log(BuildingPos);
SavePos = true;
}
float PosX = BuildingPos.x + 2;
float PosZ = BuildingPos.z + 2;
SpawnPoint = new Vector3(PosX, 0, PosZ);
Debug.Log("Spawn" + SpawnPoint);
Instantiate(Unit, SpawnPoint, Quaternion.identity);
}
}
Script on the Button
public class SpawnButtonReference : MonoBehaviour
{
public GameObject objectReference = null;
internal void GiveReference(BuildingScript Object)
{
objectReference = Object;
}
void OnButtonPress()
{
if (objectReference != null)
{
objectReference.GetComponent<BuildingScript>().SpawnUnit();
}
}
}
So I solved it myself with a little workaround. Instead of trying to reference the clone, I wrote a script on the Spawn Button which searches all Objects with the "BildingScript" then if they are Selected (which can only be one Building) it spawns a Unit at its Spawn point.
The Building itself saves his spawn point when being placed (so when Input.GetMouseButtonUp(0))
works very well for me :)

In Unity, how can I duplicate a GameObject by value so that I can modify it BEFORE instantiating it?

I'm trying to make a city builder, and I'm writing the part of the game that creates a transparent render of the building you're going to place before you actually place it. What I'd like to do is simply make a copy of the GameObject in code, modify the materials' transparency, remove some components, and then instantiate it.
There's a problem: pretty much everything in Unity is pass by reference. Is there a way to do what I want to do or is there no such way?
If you want to create a scene by combining several GameObjects instantiated on runtime, you can create a script called generateEnviroment.cs (just an example name), then you should pass one or several GameObjects as attributes to that script from the inspector.
Next step is to instantiate the correct gameObject and then modify its properties as you please (position, size, material...). Each instance will be independet, with its own attributes that you can modify as you want,and other instances of the same GameObject will not be altered.
public GameObject customGameObject1;
public GameObject customGameObject2;
void Start()
{
generateEnviroment()
}
void generateEnviroment()
{
//In case you want to add other type of GameObject, like a car or sth you have created:
GameObject myInstantiatedGameObject = GameObject.Instantiate (customGameObject1);
//You change its position
myInstantiatedGameObject.transform.position = new Vector3(0, 0.5F, 0);
// Widen the object by 0.1
myInstantiatedGameObject.transform.localScale += new Vector3(0.1F, 0, 0);
//Change material properties, assuming it has a material component
Renderer rend = myInstantiatedGameObject.GetComponent<Renderer>();
rend.material.shader = Shader.Find("Specular");
rend.material.SetColor("_SpecColor", Color.red);
...
}
You can even add to the GameObject a script component, and you will also be able to access and modify each attribute (variable) in that script independently for each instance of the GameObject (As long as you don't declare that attribute as static)
You dont have to create a copy of your gameobject. Just instantiate it and change values to it's temporary placement state. Like setting material properties, disabling child objects, etc. when the building is finally placed just reset the changes.
As everyone here already said, creating a copy of prefab or scene object is possible with GameObject.Instantiate. You cannot delay instanitiation of object (placing it on scene), but you can delay its startup calls (e.g. Start and Awake). You simply must copy an object that is not active, modify whatever you want and then activate it manually. Is that what you are looking for?
static GameObject InstanitateDelay(GameObject source)
{
bool isActive = source.activeSelf;
source.SetActive(false); // disable it temporarly
var go = Instantiate(source); // create inactive copy
source.SetActive(isActive); // return to previous state
return go; // remeber to activate manually via go.SetActive(true)
}
Instantiating is the way u duplicate an object in Unity.
If instantiating is to slow for you, just instantiate every object you need, when the scene loads and disable/enable them when you need them.
That way you can change Property before enabling and/or moving it to its final position.
The following call should make it transparent.
instantiatedObject.GetComponent<MeshRenderer>().material.color = new Color(0.0f, 0.0f, 0.0f, 0.0f);
Have look at the following 3 links:
https://docs.unity3d.com/Manual/InstantiatingPrefabs.html
https://unity3d.com/de/learn/tutorials/topics/scripting/instantiate
https://docs.unity3d.com/ScriptReference/Color.html

Unity3D C# - Text UI

I have the following piece of code. I referenced the text component in the editor to no_lives. The gamemanager (singleton) is being instantiated a scene before. The debug.log() shows 5 in the console. But when I try to set the text I get that the reference is not set to an instance of the object. Why is that?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class level1_script : MonoBehaviour {
public Text no_lives;
// Use this for initialization
void Start () {
no_lives = GetComponent<Text>();
}
// Update is called once per frame
void Update () {
int lives_n = gamemanager.lives_f ();
Debug.Log (lives_n);
no_lives.text = lives_n + " x";
}
}
Are you certain that Start() was called before Update and that the GetComponent is actually setting a value to no_lives?
If not then code defensively. Also lives_n needs to be converted to a string lives_n.ToString() + " x" or use a format.
void Update () {
int lives_n = gamemanager.lives_f ();
Debug.Log (lives_n);
if(no_lives != null) {
no_lives.text = string.Format("{0} x", lives_n);
}
}
EDIT:
But when I try to set the text I get that the reference is not set to
an instance of the object.
That's because when you do GetComponent<Text>‌​(), it will look for the instance of Text component on the-same GameObject your level1_script script is attached to.
You have two choices:
1.Attach Text component that GameObject your level1_script script is atached to then your current code should work.
2.If you already have the Text component attached to another GameObject, let's say an Object called "MyText", use GameObject.Find to find "MyText" then perform GetComponent on it to get the Text component.
no_lives = GameObject.Find("MyText").GetComponent<Text>‌​()
Edit:
Well, both Text and script are attached to the same object
prntscr.com/f7p7vx
It's likely attached to multiple GameObject and the other GameObject does not have the Text script attached to it.
Select the level1_script script, go to Assets --> Find References in Scene then remove the duplicated script from other objects.
As the script logs '5' in the debug log, it seems to me that the variable lives_n is used correctly.
My guess is that the component "no_lives" isn't filled (that's what is often causing the "reference is not set to an instance of the object" error)
I suggest that you try to add the script to the UI Text object in your scene, this way the script finds the "Text" component on that object.
It's important to know the differences between objects and components, because they're both essential parts of unity. Objects are "things" in your scene, like cubes, cameras and stuff like that. Components on the other hand are part of object and define the properties of that object. For example: a camera object has a camera component to make it a camera and to make it actually viewable by the user.
The GetComponent<>() method searches for a (in your case) Text component on the object the script is attached to.
Hope this helps!
(oh and don't forget to remove the script from the other object you've placed it on, in case this works. Otherwise you'll still get errors)

"Object reference" needed in script

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!

Unity 2D c# scripting, Spawnobject at mouseposition when down

I'm fairly new to C#(basically first time using, having to script for this project), I'm trying to teleport (from off screen to on) an object in my game(i'm using a cube for a simple object, in which I will use inkscape to create a 'better' object in its place when it works)will add cube2 later, just focusing on getting this working.
The aim is to teleport an object to where to my 'Bumber' prefab (the floor), based upon the player clicking a position on the 'Bumber' and spawn where the mouse position was on that 'Bumber' and if not on the 'Bumber' don't spawn at all(haven't go to bumber check yet), which will trigger an event, causing the player to lose.
When I was playing the game before, when I clicked, the cube would only despawn and then throw an error at me and not spawn in at the cursors position
I have my 'cube' prefab (dragged from hierarchy into Resources folder, which has the spawn script component). When I go back into unity, I get the error:
(32, 37) the name 'cube' doesn't exist in current context
(32,25) The best overloaded method match for `UnityEngine.Object.Instantiate(UnityEngine.Object, UnityEngine.Vector3, UnityEngine.Quaternion)' has some invalid arguments
(32, 25) Argument #1' cannot convertobject' expression to type `UnityEngine.Object'
I've tried for hours to fix this script, looking at unity database and to no avail.
using UnityEngine;
using System.Collections;
public class Spawn : MonoBehaviour {
public int trapCount;
void Start ()
{
trapCount = 0;
GameObject cube =(GameObject)Instantiate((GameObject)Resources.Load("cube"));
}
void Update ()
{
if (Input.GetMouseButtonDown (0))
{
Spawner ();
trapCount++;
}
}
void Spawner()
{
Vector3 mousePosition = Input.mousePosition;
transform.position = Camera.main.ScreenToWorldPoint(Input.mousePosition);
if(trapCount == 0)
{
Instantiate(cube, transform.position, Quaternion.identity); //getting error here, I don't care about rotation value, don't want to rotate at all, but doesn't like it, if it doesn't have anything there.
}
else if (trapCount >= 1)
{
Debug.Log("Trap limit reached!");
}
}
}
C# please, also, if you could, explain what you're doing, thank you kindly!
Always (well, almost always) believe what the error messages tell you.
(32, 37) the name 'cube' doesn't exist in current context
You get this for the line
Instantiate(cube, transform.position, Quaternion.identity);
At that point there is no cube anywhere within the scope of the method. You have your
GameObject cube =(GameObject)Instantiate((GameObject)Resources.Load("cube"));
in your Start() method, but it only exist within that method. It's not a member of the class for example. Making it a member would solve that problem.
And that is more than likely also the cause of the subsequent errors. If it doesn't know what a cube is, it has no idea what to do with it as an argument of Instantiate().
If you're entirely new to C# the biggest favour you could do yourself is to pick up a good book. Unity will allow you to get pretty far by hacking away at it, but there will be a point where there's simply no substitute for learning the language. It will help you tremendously.
Good luck.

Categories