In my Unity 4.3 all work well, but after Upgrade to 5 I have a problem with GetComponent. To test a new deprecable GetComponent I have use the official tutorial
using UnityEngine;
using System.Collections;
public class test : MonoBehaviour {
public GameObject otherGameObject;
private AnotherScript anotherScript;
void Awake ()
{
anotherScript = GetComponent<AnotherScript>();
}
void Update ()
{
Debug.Log("The player's score is " + anotherScript.playerScore);
}
}
And the second script
using UnityEngine;
using System.Collections;
public class AnotherScript : MonoBehaviour {
public int playerScore = 9001;
}
This is only for test,
i've used the same example of the unity tutorial
https://unity3d.com/learn/tutorials/modules/beginner/scripting/getcomponent
After that I've associated the two object in the editor But the run report is:
NullReferenceException: Object reference not set to an instance of an object
test.Update () (at Assets/test.cs:22)
in unity 4.3 work well.
You should try getting the reference in the Start method. Make sure that both test and AnotherScript scripts are attached to the-same GameObject in the Editor, then the code below should work.
using UnityEngine;
using System.Collections;
public class test: MonoBehaviour
{
public int playerScore;
void Start()
{
anotherScript = gameObject.GetComponent<AnotherScript>();
}
void Update ()
{
Debug.Log("The player's score is " + anotherScript.playerScore);
}
}
If both Scripts are not attached to the-same GameObject then use:
anotherScript = GameObject.Find("Name of GameObject AnotherScript is Attched To").GetComponent<AnotherScript>();
You need to use FindObjectOfType<AnotherScript>() if the scripts are not attached to the same GameObject.
I believe this should be so:
public GameObject otherGameObject;
private AnotherScript anotherScript;
void Awake ()
{
anotherScript = otherGameObject.GetComponent<AnotherScript>();
}
void Update ()
{
Debug.Log("The player's score is " + anotherScript.playerScore);
}
}
And you should attach otherGameObject in the editor.
Are you sure that AnotherScript is also attached to the same Gameobject you test-script is attached to?
The GetComponent Method only looks for Components attached to GameObjects.
The easy way would for sure be to make anotherScript member public (so it´s exposed in the inspector) and drag´n´drop your script in there to get the reference.
Related
I am currently working on making a class accessible from other scripts. Below is what I have coded.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody2D))]
[RequireComponent(typeof(BoxCollider2D))]
// Start is called before the first frame update
public class _move
{
private float _sizex;
private float _sizey;
public _move(float sizx, float sizy....etc)
{
_sizex = sizx;
_sizey = sizy;
}
public void regularmove(float sizex, float sizey...etc)
{
GameObject _player;
_player = GameObject.GetComponent<GameObject>();
BoxCollider2D bc2d;
bc2d = _player.GetComponent <BoxCollider2D>();
bc2d.offset = new Vector2(locationx + 1, locationy);
}
}
however, when I try to compile it, it gives me an error.
cannot access non-static method"GetComponent"
on this line of code
_player = GameObject.GetComponent<GameObject>();
I do not know why this is happening because I have not declared the class as static, and do not really know the properties of GetComponent that well. Can someone tell me what is happening and how I can solve this?
Also, when I change
GameObject _player;
to
public GameObject player;
the scripts below suddenly cease to work, giving me errors like
cannot resolve symbol _player
what exactly is happening here?
Thanks in advance!
Whatever script creating the instance of the _move class (This is bad naming btw, it should be Move) should also pass its gameObject to the constructor.
// attributes here are not valid if your class is not a MonoBehaviour
public class Move
{
GameObject m_object;
public Move(GameObject obj, ...)
{
m_object = obj;
}
}
if your class is meant to be a MonoBehaviour component, then it has a GameObject member already and you can use the attributes:
[RequireComponent(typeof(BoxCollider2D),typeof(Rigidbody2D))]
// Start is called before the first frame update
public class Move : MonoBehaviour
{
void Start()
{
Debug.Log(gameObject.name);
}
}
I'm working on a 2D Pixel Platformer RPG, I need to develop a save and load mechanism in it. There are several scenes in the game (and will have many more), the question is, how do I save the scene number the player is currently in, so that when he quits and reloads the game, he's in the same scene. How can I implement it in C# Unity. (please be clear as I'm somewhat a beginner).
Ok, so there are a few things you need to do in order to achive this:
First, in the first scene in your build - create an Empty GameObject, name it "SceneManager".
Then, create a new tag "SceneManager" and add it to the "SceneManager" GameObject
Finally, add the "SceneManager" script to the "SceneManager" GameObject:
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
public class SceneManager : MonoBehaviour
{
void Awake()
{
DontDestroyOnLoad(gameObject);
}
public void SaveScene()
{
int activeScene = SceneManager.GetActiveScene().buildIndex;
PlayerPrefs.SetInt("ActiveScene", activeScene);
}
public void LoadScene()
{
int activeScene = PlayerPrefs.GetInt("ActiveScene");
SceneManager.LoadScene(activeScene);
}
}
Then, you can load/save scenes by using this script:
using UnityEngine;
public class UsageScript: MonoBehaviour {
private SceneManager SceneManager;
void Awake ()
{
sceneManager = GameObject.FindGameObjectWithTag("SceneManager").GetComponent<SceneManager>();
}
void UsageManager()
{
sceneManager.SaveScene();
sceneManager.LoadScene();
}
}
I'm using a namespace to instantiate a prefab in my game however unity thinks that the prefab is not a GameObject and returns the NullReferenceException error
I've linked the Prefab, properly in the GameObject that holds the script. This is the code that I currently have in Visual Studio but I also tried various forms of the code, they are what follows the first lines of code
public GameObject Prefab;
public void OnAppear(){
GameObject spawn = Instantiate(Prefab, Spawnpoint.position, Spawnpoint.rotation);
spawn.transform.parent = Spawnpoint.transform;}
V1
var spawn = Instantiate(Prefab, Spawnpoint.position, Spawnpoint.rotation);
V2
var spawn = Instantiate(Prefab, Spawnpoint.position, Spawnpoint.rotation) as GameObject;
Entire script:
namespace AugReal
{
public class StartAll : MonoBehaviour
{
public Transform Spawnpoint;
public GameObject Prefab;
public void OnAppear()
{
GameObject spawn = Instantiate(Prefab, Spawnpoint.position, Spawnpoint.rotation);
spawn.transform.parent = Spawnpoint.transform;
}
public void OnDisappear()
{
Debug.Log("You lose");
}
}
}
Inspector:
Try the following code instead:
You do not need to create a public reference to the transform that this script is attached to. Since the script is a monobehaviour, you can directly access this via this.transform
Rather than setting the parent explicitly after instantiating, consider usign the Instantiate method with the parent override.
(I have also change the casing on your property "Prefab". It doesn't affect the code, but standard is to keep property names camelCase to distinguish them from the PascalCased class types.)
namespace AugReal
{
public class StartAll : MonoBehaviour
{
public GameObject prefab;
public void OnAppear()
{
GameObject spawn = Instantiate(prefab, this.transform);
}
public void OnDisappear()
{
Debug.Log("You lose");
}
}
}
I don't know how to fix it. It's a 2D game. When you collide with the box, it should load/teleport you to the next scene, but it doesn't.
I tried everything on the internet and it didn't work.
using UnityEngine;
using UnityEngine.SceneManagement;
public class VictoryZone : MonoBehaviour
{
public void LoadNextLevel()
{
void OnTriggerEnter2D(Collider2D collider)
{
SceneManager.LoadScene(1);
}
}
}
I expect it to teleport me to my next level.
It looks like you nested the OnTriggerEnter2D() function inside of LoadNextLevel()? That's what the Local Function warning is referring to.
Those should be two separate functions, not one within the other. OnTriggerEnter2D() is a function of MonoBehavior; the MonoBehavior (VictoryZone) is what gets notified of the collision.
using UnityEngine.SceneManagement;
public class VictoryZone : MonoBehaviour {
public void LoadNextLevel() {
SceneManager.LoadScene(1);
}
void OnTriggerEnter2D(Collider2D collider) {
LoadNextLevel();
}
}
Note: you might also need to check the GameObject associated with collider to make sure that it's a player, and not an enemy or something (if, hypothetically, you had enemies or projectiles or other objects with colliders moving into the victory zone).
So I have an enemy spawner with a method to instantiate prefabs working just fine. Simplified:
public class EnemySpawner : MonoBehaviour {
public GameObject EnemyPrefab;
public void setEnemies()
{
Instantiate (EnemyPrefab, enemyPos, rotation);
}
void Start()
{
setEnemies();
}
}
This works fine. But it doesnt work when I call it from a different script:
public class Player : MonoBehaviour {
public EnemySpawner enemyspawner;
void Update(){
if (Input.GetMouseButtonDown (0))
{
enemyspawner= new EnemySpawner();
enemyspawner.setEnemies();
}
}
I keep getting this error:
ArgumentException: The prefab you want to instantiate is null.
What am I doing wrong?
Edit:
So I figured that I could not create a Monobeaviour by using the New keyword .I changed it to:
enemyspawner = gameObject.AddComponent<EnemySpawner> ();
enemyspawner.setEnemies();
But that still wont work.
I just read your comment about changing:
new to enemyspawner = gameObject.AddComponent<EnemySpawner>();
However, you did not properly solve the problem, you only made a workaround that won't work because your prefab, public GameObject EnemyPrefab;, won't be set.
With your new code gameObject.AddComponent<EnemySpawner>(); You are attaching a script to the Player GameObject, this will bring you problems in the future.
My Suggestion
Create an Empty GameObject and attach EnemySpawner to it and name it EnemySpawnerObj.
Then to call the function setEnemies() from another class you do this:
EnemySpawner spwner = GameObject.Find("EnemySpawnerObject").GetComponent<EnemySpawner>();
spwner.setEnemies();
So what you are doing is looking through your scene for the GameObject named EnemySpawnerObject then you get the component named EnemySpawner and then you can call that class instance.