I'm trying to make a list where I can add objects in my scene, later on I'm going to loop through them to determine the closest object to my character and make the character perform certain actions. As soon as I created a list, it won't allow me to add any object to my list or reference it and I don't understand why that's happening. Here's a video to further clarify my issue
List Not working for me
my code for further inquiries
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RobberMechanic : MonoBehaviour
{
public List<GameObject> testing = new List<GameObject>();
// void Start()
// {
// }
// // Update is called once per frame
// void Update()
// {
// }
}
Note: wanted to clarify that my unity version was on 2020.3.1f and now I've tried upgrading to 2020.3.10f and this issue occurs in both versions
what you are trying to do is not possible as you are dragging a gameobject inside your list from the hierarchy onto a prefab in the assets folder. Dragging and dropping works on gameObjects that are already inside the a scene/hierarchy.
To achieve your goal you must either:
Add your Terrorist prefab in the scene. Drag your Sphinx object inside it. The Terrorist prefab will then have the appropriate reference of the gameObject and can be used properly.
Turn your Terrorist object into a scriptable gameObject you can then add all sorts of different properties and will be easier to manage. There are tons of videos and documentation on it as well.
You're trying to add a GameObject from your scene to a list in a Prefab which is not possible, you'll have to drop your prefab into the scene before adding game objects to it or make a Prefab of the object you're trying to add to the list.
Related
I am new to C# and I am working on an AR project where I am showing directions to a section of books in a library. I have a basic scene set up where the user clicks on a button and something happens. I am using the Mixed Reality Tool Kit's directional indicator. I created 4 game objects that represent different subjects and are placed at different points in space in the scene. I have a directional indicator for each of those game objects and those directional indicators are prefabs. They are an arrow that points to that game object, so what I am trying to do is have them turned off and when the user clicks the button, it turns them on.
Prefabs are just files that contain GameObject, they aren't directly connected to the scene. If you want to create new GameObject from Prefab in runtime you can Instantiate it, and then keep reference to this new GameObject.
You also can check similar question, maybe it will help.
Code example
class SomeClass: MonoBehaviour
{
private GameObject newGameObject;
...
public void InstantiatePrefab(GameObject prefab)
{
newGameObject = Instantiate(prefab, ...);
}
public void SetGameObjectState(bool state)
{
newGameObject.SetActive(state);
}
}
I'm currently making a game in Unity and I ran into a problem. Essentially what I'm currently trying to do is load a huge list of objects that I require for future scenes in my Recource folder and load them before any scene including the startup scene has been loaded so that I can essentially randomly choose to load scenes instead of being dependent on the first scene in order to load gameobjects that I will need in later scenes. I found a method online that was supposed to be able to do this. I created a gameobject called main put it into my resources folder and attached the Script bellow to it. Then I attached all the gameobjects that I would need to load before any of my scenes to this gameobject ("Main"):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Main : MonoBehaviour
{
//[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
void Start()
{
GameObject main = Instantiate(Resources.Load("Main")) as GameObject;
var mainObj = Instantiate(main);
mainObj.SetActive(false);
GameObject.DontDestroyOnLoad(main);
MySceneManager.LoadScene(1, this);
}
}
When I then run my game for somereason I get a NullReferenceexception stating: (The Object you want to instantiate is null). Does anyone know how I can solve this problem or even if their is an easier solution to the problem I'm trying to solve?
Thanks in advance
You can create an empty "loading scene". The scene will be purely to instantiate the objects you need and will terminate after it is done. Like a main menue in games.
You can put the scripts in the scene select scene.
So i have this code to enter a new scene:
using System.Collections;
using UnityEngine;
// add this line to use the SceneManagment library
using UnityEngine.SceneManagement;
public class LoadScenes : MonoBehaviour {
[SerializeField] private string loadLevel;
void onTriggerEnter(Collider other) {
if (other.CompareTag ("Player")) {
SceneManager.LoadScene (loadLevel);
}
}
}
I then add this script to the cube and select it a trigger. I then type in the scene that I want it to send me too, but when i walk into it nothing happens at all. I have tried different variations but it just doesnt seem to work.
My character that I am using is a unity asset called man in suit but I have selected its tag as "Player". Any suggestions would be great!
The Handler for your trigger won't be invoked
As Sunimal allready noted you need to fix the typo.
void OnTriggerEnter(Collider other) {
if (other.CompareTag ("Player")) {
SceneManager.LoadScene (loadLevel);
}
}
Ensure your Scene is included and checked in the Build Settings
As you can see in the Screenshot below i have added a SampleScene to my build settings. There are 2 ways of adding scenes into the build
By clicking "Add Open Scenes" you can add the scene which is
currently open to that list.
Drag & Drop the scene from your ProjectView into the List
Ensure your SceneName is set correctly
Your loadLevel field would in my case need to have the value "Scenes/SampleScene".
[SerializeField] private string loadLevel;
The player needs a collider
As you use the OnTriggerEnter method, your Player object needs to have some sort of Collider attached to it. This can be a BoxCollider, SphereCollider or some other Collider. Note that the "Is Trigger" checkbox needs to be checked. Else it won't act as trigger.
Edit: Thanks Eddge for correcting me. See this answer for a deeper explanation about Triggers.
Programatically ensure you have a BoxCollider component beside your LoadScenes component
You can add the RequireComponent Attribute at your class. It basically ensures you have the given type added as a component. This will also automatically add a box collider to an object, when you add this script.
[RequireComponent(typeof(BoxCollider))]
public class LoadScenes : MonoBehaviour {
/// your other code is here
}
Thanks to Sunimal for this hint!
What if that did not solve the problem?
If all this does not help, please provide an screenshot of the inspector of your Playerobject. That way we can see what components are attached to that object and how they are "configured"
SceneManagement
To use the SceneManager to load a scene you must ensure that your scene is in the build settings, per Tobias's answer.
Triggers
In all software development case does matter and it is incredibly important. OnTriggerEnter is not the same as onTriggerEnter, also note OnTriggerEnter(Collider col) is not the same as OnTriggerEnter(Collision col)
In order to use any of the trigger methods there are 3 things that are a must:
Both Objects have to have colliders.
One of the colliders have to be marked as a trigger.
One of the objects have to have a rigidbody.
The trigger event is sent to the object with the rigidbody and whatever object is the trigger, in the circumstance that both objects are triggers both will receive it.
Here's the code I'm having problems with:
public class PlaneBehaviour : MonoBehaviour {
public GameObject ClickSymbol;
public void Update() {
if (Input.GetMouseButtonDown(0)) {
Instantiate(ClickSymbol, Input.mousePosition, Quaternion.identity);
}
}
}
When user clicks the left mouse button, then multiple ClickSymbol's will be instantiated. How to prevent that behavior (create the object only once) ?
As for the PlaneBehaviour script, it's attached to multiple (not
intersecting, not overlapping) objects on a plane
That's what I thought you are doing and wanted to verify this before adding an answer. Joe's answer should work but this is a bad design.
You get the multiple Objects instead of one because the script is attached to multiple Objects.
The proper solution here is to have one script that reads from the Input then call a function or trigger an event in another script if required. Create a new script called InputReader or with similar name then move your if (Input.GetMouseButtonDown(0))... Make that that this new script is only attached to one GameObject. Just attach it to an empty GameObject. That's it.
It will prevent problems such as executing code twice when there is an input event.
Now, let;s say that you want to notify another script attached to another GameObject when key is pressed, you can find that GameObject, get that script that is attached to it then call its function.
GameObject obj = GameObject.Find("YourOtherObjectName");
Script script = obj.GetComponent<Script >();
script.notifyKeyPress();
I attached it to multiple game objects to be able to detect which game
object was clicked
That's not how to detect which GameObject is clicked. Since this is a plane, I assume it is a 3D Object with a 3D collider. See 6.For 3D Object (Mesh Renderer/any 3D Collider) from my other post on how to do this.
I have a script called DialogueController, which is attached to a canvas. I would like to instantiate that canvas from the DialogueController script. Whenever I attempt to do this, all of the public objects that were assigned to the canvas through the Unity editor are set to null (including the canvas itself, which is what I am trying to instantiate).
Is there a simple way to do this? I have an alternative solution, but being able to do this would keep my code slightly more compartmentalized.
You could initialize these variables from the script itself, using the resources folders (and the Resources.Load() method). Something like that:
//The canvas is at the path "Assets/Resources/canvas".
function Start () {
your_canvas = Instantiate(Resources.Load("canvas"));
}
From the comments, it seems like you need an initial "seed" instance of that Canvas which contains your script to instantiate more copies if you need. Part 2 is most common for your needs
The easiest way is to have one instance of said canvas already in the scene. You could have the drawable/visible canvas part "disabled" by unticking the little checkbox in the inspector, and then have it enable itself in a function of a script on the GameObject...
void Start ()
{
thisCanvas = GetComponent<Canvas>();
thisCanvas.enabled = true;
}
of course, another way would just be to instantiate one copy from another script which you already have in the scene - classic case:
Create a BLANK GameObject in your scene (CTRL+Shift+N), [F2] rename it "GameManager" (SOME unity functions still bug out when there are spaces in GameObject names BTW) and then attach a new script called GameManager.
This script is basically just here to make sure the right scenes load, and instantiate certain prefabs, make network connections, set player variables that you haven't done from the editor etc etc
so:
using UnityEngine;
using System.Collections;
public class GameManager : MonoBehaviour
{
public GameObject myObject;
void Start ()
{
Instantiate(myObject, transform.position, transform.rotation);
}
}
now drag+drop your "prefab" which you want to instantiate into the slot on your "GameManager" in the inspector.
Note that it doesn't have to be when the game starts, another example is the GameManager script having a function listening for whenever a login is needed, and at that time - it instantiates your login dialog.