Assign script instead of GameObject in editor? - c#

I'm connecting my GameObjects by assigning them in the editor.
All I need is the script assigned to a GameObject but I always have to do this:
public class GameBoard : MonoBehaviour {
//assigned the gameobject containing the ScoreScript in the editor
public GameObject totalScore;
private ScoreScript totalScoreScript;
void Start() {
totalScoreScript = this.GetComponent<ScoreScript>();
}
}
Is there a better way to achieve this result?

Just use ScoreScript as the public variable. To assign it drag the game object with the script attached as normal via the editor. This also works for builtin components like Transform.
public class GameBoard : MonoBehaviour {
public ScoreScript totalScoreScript;
}

Related

How to call a script component from a GameObject that is child to another GameObject, but from other GameObject?

In my unity project, I have a GameObject called "Spawn_manager", that has another Child GameObject called "Enemy_Container". The script of Spawn_Manager makes "Enemy" prefabs instantiate inside the "Enemy_Container". I am trying to acess the "Enemy" script(also named Enemy) from another script.
Anyone knows how I can get it?
I tried writing this:
private Enemy _enemy;
private void Start()
{
_enemy = GameObject.Find("Enemy").GetComponent<Enemy>();
}
But obviously it is not working, but I can't get it to work. Basically, I wanna the script, and the path would be Spawn_Manager>Enemy_Container>Enemy.
If you want to make the Enemy easily accessible you can add all spawned Enemy to static list. Like this:
public class Enemy : MonoBehaviour
{
public static List<Enemy> AllEnemy { get; private set; } = new List<Enemy>();
private void Awake()
{
AllEnemy.Add(this);
}
private void OnDestroy()
{
AllEnemy.Remove(this);
}
}
Using Find is demanding and not a reliable operation. If you will have any other GameObjects with name Enemy it will found them instead of desired one.
in this case i think that problem is that after instantiation prefab new GameObject have name in format $"{prefab.name}(Clone)".

How do I reference a variable from another class in the same script?

I am trying to make a wave spawn system in a serialized list in the inspector, but I can't figure out how to make it work. I can't seem to reference variables in other classes within the same script, and I need that data to make it work.
Right now it looks something like this, with classes nested within each other:
`
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class WaveSystemScript : MonoBehaviour
{
[SerializeField] public WaveBubbleScriptableObject waveBubbleSO; //This contains the list of valid bubbles, but I can't reference it from the other classes.
[SerializeField] public List<GameObject> validBubbles = new List<GameObject>(); //So does this
[SerializeField] List<Waves> waveList = new List<Waves>();
}
[System.Serializable]
class Bubble
{
[SerializeField] GameObject bubbleSelection; //select the bubble to spawn repeatedly
[SerializeField] float spawnInterval;
}
[System.Serializable]
class Waves
{
[SerializeField] List<Bubble> waveBubbles = new List<Bubble>(); //each wave may have multiple bubbles, with different variable each
float waveLength;
}
`
The main issue is setting the bubbleSelection gameobject in the bubble class. Anything in the monobehaviour class can't be referenced in the other classes for a reason I'm not aware of. I tried lists, arrays and scriptableobjects but couldn't figure out how. I could reference the prefab directly using an empty GameObject variable, but I would like it to work such that all the valid spawnable objects are already present in an array/list or dropdown for easy selection.
Well, both fields within Bubbles as well as within Wave have the default member accessibility private and therefore are not visible for any other type.
(See access modifiers)
You either simply want to make those public (in which case the [SerializeField] becomes redundant as it is only needed to serialize fields that are not public)
// [System.Serializable] <- this is also redundant as MonoBehaviour or anything
// derived from UnityEngine.Object already is serialized anyway
public class WaveSystemScript : MonoBehaviour
{
public WaveBubbleScriptableObject waveBubbleSO;
public List<GameObject> validBubbles = new List<GameObject>();
public List<Waves> waveList = new List<Waves>();
}
[System.Serializable]
class Bubble
{
public GameObject bubbleSelection;
public float spawnInterval;
}
[System.Serializable]
class Waves
{
public List<Bubble> waveBubbles = new List<Bubble>();
public float waveLength;
}
or for encapsulation, depending on your use case, you can keep them as private so they are only editable via the Inspector but via code only provide them as public readonly properties like e.g.
[System.Serializable]
public class Waves
{
[SerializeField] private List<Bubble> _waveBubbles = new List<Bubble>();
[SerilaizeField] private float _waveLength;
public IReadOnlyList<Bubble> waveBubbles => _waveBubbles;
public float waveLength => _waveLength;
}

unity wont let me attatch object to variable

Unity wont let me drag and drop a game object into the variable
heres my script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Assertions;
public class GameManager : Singleton<GameManager>
{
[SerializeField] private Player currentPlayer;
public Player CurrentPlayer
{
get { return currentPlayer; }
}
private void Awake()
{
Assert.IsNotNull(currentPlayer);
}
}
Your public class GameManager : Singleton<GameManager> should be a monobehaviour.
Monobehaviours are the type to inherit from when you to add functionality to a gameObject. You cannot drag whatever to a script that just hold a [SerializeField].
You need to have a Monobehaviour inherited class as a component of a gameobject (meaning that it should be attached to it). There is where you can drag the componenets into the public or the private [SerializeField] fields shown in the editor when you select the correspoding gameobject.
Your script must inherit from Monobehavior for you to be able to do that. And since Singleton is a generic type, that wont work.

Instantiating a Prefab returns the NullReferenceException error

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");
}
}
}

Instantiating prefabs from another script (The prefab you want to instantiate is null)

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.

Categories

Resources