how to access multiple instantiated object in unity? - unity3d

when I'm instantiate some object and I create a reference for I destroy which destroy the only first object in instantiating, my goal is to declare how to create multiple references of instantiated object?, I'm trying this
instiatedobject = GameObject.Instantiate(realobject, realobject.position, real.rotation);

You could use any generic collection type like List, Queue etc. For example
private List<GameObject> runtimeCreatedObjects;
private void Awake() {
runtimeCreatedObjects = new List<GameObject>();
}
public void CreateObject() {
GameObject instiatedobject = GameObject.Instantiate(realobject, realobject.position, real.rotation);
runtimeCreatedObjects.Add(instiatedobject);
}
Here every time we instantiate new object we add it to our list and use them elsewhere as per our requirement.

Related

Why using getComponent to call objects in Unity?

I am new in unity, I'm just wondering why we call the player object like this :
private void OnTriggerEnter(Collider other)
{
// if the player hit the enemy then destroy the ememy
if (other.tag == "PLAYER" ) {
// like this
other.transform.GetComponent<Player>().damage();
}
while we can make the damege method static and call it like this :
private void OnTriggerEnter(Collider other)
{
// if the player hit the enemy then destroy the ememy
if (other.tag == "PLAYER" ) {
//other.transform.GetComponent<Player>().damage();
Player.damage();
}
why we call the object like this what the point
other.transform.GetComponent<Player>().damage();
does it effect performance ? or is it just another available way to call objects
I will try to explain this the best I can. This explanation isn't perfect, but I worded it so it makes the most sense.
A class is a file that contains code. There are two "types" of classes, static and non-static. Static classes can be accessed anywhere, but there is only ever 1 copy. For example, use UnityEngine.Mathf. That is a static class, so you can just do Mathf.(whatever).
The non-static class can have multiple copies. Non-static classes can have static methods and fields, which can be accessed like you would a static class. For most basic applications, these classes just use normal methods. These methods are instance-dependent.
For example, take a non-static Player class.
public class Player : MonoBehaviour {
//This is accessed using Player.instance
public static Player instance;
//This function only runs on the script you place on a GameObject
public void Start(){
//Sets the static instance to this instance
instance = this;
}
}
You can then access the active player instance with any other script (as long as the instance variable was set before)
public Player GetPlayer() {
//As you can see, you don't need a reference to a Player; you can just use the static instance.
Player instance = Player.instance;
return instance;
}
In conclusion, using Player.Whatever references the static version. Using playerInstance.Whatever references a runtime instance. If you will only have one runtime instance of a class, you can use the example above to allow other classes to access the instance.

How to reference a gameObject inside a prefab? Using GameObject.Find does not work

I am trying to use GameObject.Find within a prefab to reference an object that exists in the scene. The name of the object is exactly the same as the actual object.
LoseLives loseLives;
GameObject loseLivesing;
private void Awake()
{
loseLivesing = GameObject.Find("MasterManager");
}
private void Start()
{
loseLives = loseLivesing.GetComponent<LoseLives>();
target = Waypoints.waypoints[0];
}
loseLives.LoseLife();
Null Reference
I get a null reference when "loseLives.LoseLife();" runs.
Any help with solving the no reference problem would be greatly appreciated!
If you think there is a better way to create the connection between a script on a prefab and a script on a in-scene gameObject could you please explain it or point me to a tutorial, because in all my research I did not have any luck.
Thank you!
It seems like your LoseLives is a singular, constant object.
First Method
Simply making use of the inspector by exposing the fields.
public class YourScript : MonoBehaviour {
[SerializeField]
private LoseLives loseLives;
// ..
private void Start() {
loseLives.LoseLife();
}
// ..
}
It comes with the problem of needing to constantly drag your constant object into the inspector whenever you need it.
For a Prefab, it works if the target object is part of the Prefab, or the Prefab is generated in the same scene as the targeted object.
Second Method
Using singletons.
LoseLives.cs
public class LoseLives : MonoBehaviour {
public static LoseLives Instance {
get => Instance;
}
private static LoseLives instance;
private void Start() {
instance = this;
}
public void LoseLife() {
// ...
}
}
YourScript.cs
public class YourScript : MonoBehaviour {
// ..
private void Start() {
LoseLives.Instance.LoseLife();
}
// ..
}
This works if you have a global, singular instance of LoseLives object.
Even though it might not be the best approach, I found a workaround for my issue.
I am using a static variable that resides in the other script (CurrencyManager), calling it from the LoseLives script.
Instead of:
loseLives.LoseLife();
I do:
CurrencyManager.playerHealth -= 1;
Where CurrencyMananger is the other script and playerHealth is a static variable that is in the CurrencyManager script. This works because a static variable does not require the objects to be referenced in the inspector.
From now on, when I have a problem where I want to reference a gameObject within a script that is on a prefab, I will consider using static variables in my solution.

Unity How to get transform from Hashset<EnemyScript>

I have created a Hashset to which I add my enemies to. In the Enemy script in the OnEnable and Disable I add and remove from the Hashset. The Hashset is a public static so I can access the count of it by just Debug.Log(Enemy.enemyTargets.Count); to see the number increase and decrease.
How do I access the transform of the Hashset, I know hashset have no specific order and that is fine but I just want the transform of whichever object inside the Hashset.
Inside Enemy.cs script
public class Enemy: MonoBehaviour {
public static readonly HashSet<Enemy> enemyTargets = new HashSet<Enemy>();
private Transform _transform;
public new Transform transform => _transform = _transform ? _transform : base.transform;
private void OnEnable()
{
enemyTargets .Add(this);
}
private void OnDisable()
{
enemyTargets .Remove(this);
}
}
A HashSet has no transform but rather each Enemy has its own .transform reference.
Don't override that property but rather simply use
foreach(var enemy in Enemy.enemyTargets)
{
var transform = enemy.transform;
// use each transform
}
You can also simplify it with Linq
foreach(var transform in Enemy.enemyTargets.Select(enemy => enemy.transform)
{
// use transform
}
Or you could add a property for it like
public static Transform[] enemyTargetTransforms => enemyTargets.Select(enemy => enemy.transform).ToArray();

Global Scriptable Object

Suppose I have this ScriptableObject to represent a list of cards:
using UnityEngine;
using System.Collections;
[CreateAssetMenu(fileName = "CardList", menuName = "Inventory/List", order = 1)]
public class CardList : ScriptableObject {
public string[] cardName;
public Sprite[] cardSprite;
}
Then I create the ScriptableObject and fill it with all my cards information.
Is there a way to modify this code so that any script have access to it statically? For example, is it possible to give CardList a singleton behaviour?
I don't want to create another class, it would be easy to create a ScriptableObjectManager that could reference CardList. I'd rather call something like CardList.instance.cardName[i] directly.
Definitely, you can create it as singleton so for this.
Suppose that we have Unity Project that has file hierarchy like
UnityProject
- Assets (directory)
Scripts
SampleScriptableObject.cs
- Resources (directory)
SampleScriptableObject.asset
- Project
- ..etc
in "SampleScriptableObject" class will be like
public class SampleScriptableObject<T> : ScriptableObject where T : ScriptableObject
{
private static T _instance;
public T GetInstance()
{
if (_instance == null)
{
_instance = Resources.Load(typeof(T).Name) as T;
}
return _instance;
}
}
you can use scriptable object as singleton as you want.

CS0120 occurs (functions) Unity

public int[,] position = new int[8, 8];
Figure pawn1 = new Figure();
void Start()
{
pawn1.Create("pawn", 1, new Vector2Int(1, 2));
}
void Update()
{
}
[System.Serializable]
public class Figure
{
public int id;
public void Create(string nameEntered, int IdEntered, Vector2Int positionEntered)
{
position[positionEntered.x, positionEntered.y] = IdEntered;
//CS0120 occurs here
}
}
Getting this error and dont know how to fix it
Is there anyone who´s able to help?
Any kinda help is appreciated
CS0120 means
An object reference is required for the nonstatic field, method, or property 'member'
The reference to
public int[,] position = new int[8, 8];
is non-static or instanced since it doesn't use the keyword static. That means the only way to access it is over the reference of the instance of the outer class.
The solution depends on what you want to do with it:
If you want it non-static so that it is not "shared" between all instances of the outer class a solution could be to pass on your outer classe's instance reference like
private void Start()
{
pawn1.Create("pawn", 1, new Vector2Int(1, 2), this);
}
And in Figure expect according value (replace <OuterType> by the outer classes actual name)
[System.Serializable]
public class Figure
{
public int id;
public void Create(string nameEntered, int IdEntered, Vector2Int positionEntered, <OuterType> reference)
{
reference.position[positionEntered.x, positionEntered.y] = IdEntered;
}
}
Otherwise you can make it static so it is "shared" between all instances of the outer class:
public static int[,] position;
Hint1
If that is all your Create method is supposed to do why not setting the value in the outer class itself?
private void Start()
{
position[1,2] = 1;
// Rather pass on the value in this direction if Figure needs it
pawn1 = new Figure("pawn", position[1,2], /*...*/);
}
Than there is no need to pass position etc on to the Figure instance and than get the value written back (unless there is happening more you didn't show).
Hint2
Instead of create a new Figure in
Figure pawn1 = new Figure();
and than later use its method Create to setup a value you should probably rather use the constructor e.g.:
[System.Serializable]
public class Figure
{
public int id;
public Figure(string nameEntered, int IdEntered, Vector2Int positionEntered, <OuterType> reference)
{
reference.position[positionEntered.x, positionEntered.y] = IdEntered;
}
}
and use it like e.g.
Figure pawn1;
private void Start()
{
pawn1 = new Figure("pawn", 1, new Vector2Int(1, 2), this);
}
Hint3
The usage of Start and Update let's conclude that you are very probably using a MonoBehaviour.
To avoid confusion with the transform.position I'ld recommend to name your field maybe better Positions.
Hint4
So far you are not using any of the Vector2Int's functionality but use it only to get the two int values.
In case you are not doing anything else with positionEntered it would be less overhead to instead of passing on a new Vector2Int only to get two int values simply pass on the int values themselves
pawn1.Create("pawn", 1, 1, 2, this);
and
public void Create(string nameEntered, int IdEntered, int x, int y, <OuterType> reference)
{
reference.position[x, y] = IdEntered;
}
Hint5
In general if you are using MonoBehaviour components but you are not using one of Start or Update etc remove them entirely from your class because Unity calls them as soon as they exist which causes unnecesary overhead.