How to instantiate a prefab associated with a class? - c#

Every time i needed a prefab i would just instantiate it from my prefabs folder and yada yada everything is working perfectly.
But now im trying something different.
I have a class Player() wich has lets say a prop called public int MoveSpeed{get;set;}.
Ok now i want to instantiate a prefab "myPlayer" associated with my Player class. So i could do things like myplayer.Movespeed = x;
How do i use the instantiate(in this scenario)?
How do i use the constructor Player myPlayer = new Player(moveSpeed = x);
I have been searching about this in a lot of places, bue the answers were foggy to me, can anyone help me?
EDIT: I think what im trying to do has no logic. Unity works witha a Component-Model Paradigm, and im trying to go againt that it seems.
The reason why i am asking this is because this time i want to have a solide, smart and flexible code, not a spagheti code mess.

You could instantiate an empty GameObject and build on it, prefabs are just shortcuts so you don't have to write tons of line of code to build up the components on gameobject, here is example:
GameObject someGO = new GameObject();
Player refToClass = someGO.AddComponent<Player>();
refToClass.Movespeed = x;

Related

I find a way to use less "GameObject.find" but I´ve never see somebody do it like that, am I wrong?

I needed to find a better way to find my Game Objects without using GameObject.Find because I have this line more than 30 time is one script, so I created this line on my script:
public List<GameObject> gameObjectList = new List<GameObject>();
Then, I go in the inspector and add manually the gameobjects in the list.
and everything works fine.
But I see nobody talking about that way on internet, so is there something wrong with that way?
Assigning Object references using the Inspector is a great practice! It can make your components more flexible, because you can rewire the same code to work with different Objects.
Note that you can also expose private fields using the SerializeField attribute. Making fields private when you can is good practice, because limiting access to them can help reduce bugs.
Another things to note is that you can also edit Component type fields using the Inspector, so you don't need to do any GetComponent calls in your code. You rarely need to work with GameObjects directly; basically only when you want to destroy a GameObject or modify it's active state.
[SerializeField]
private Button[] buttons = new Button[0];

How can I grab a reference of a game-object in a scene from a prefab

currently I am working on a Equipment system that will Instantiate Game objects into the scene from a list, prior to this I was not using a Instantiation system with just keeping the Game Objects Active in the scene at all time.
Now with Instantiating the Game Object(Prefab) I am running into the error of Loosing the References when I instantiate them, I have looked at various other articles before such as this Discussion here:
However I am looking at alternative ways other than using Tags as this system may use a large amount of tags decreasing game performance overtime, would anyone know different methods as to saving references from a scene into a prefab?
So as this is a new system I am really just looking for suggestions on how to save references of scene game-objects into a prefab, as my old system was just holding the game objects active in the scene and not actually instantiating them, once again I would love to hear different types of methods, something more than just using Tags.
The References im trying to save are three Transform Elements from a script attached to my Prefab they are the following
public Transform camPos;
public Transform aimLocation;
public Transform crosshairLocation;
Currently I am just dragging and dropping the gameobjects from the scene into the public fields in the script
Since this will be a major system I would like to not want to use tags for this system. But it is definitely a Valid option I am just looking for other methods for saving references of scene game-objects into a prefab When Instantiating the prefab into the scene,
Thank you for taking the time to read and any suggestions would be greatly Appreciated!
Any Questions Just Ask!
You can not save scene references in prefabs, for obvious reasons (what happens if you instantiate that prefab into another scene?). Your prefab needs to discover the objects it needs after it's instantiated. I'm not a huge fan of the tag system in Unity (or any other system that uses strings as identifiers, too much room for error). I'd recommend you take any of these three approaches:
Make the transforms you need (cam pos, aim location, etc.) singletons if there's ever only going to be one of each. You'd make a script class specifically for each one, make that class a singleton, and put it on the game objects. Then, after your prefab is instantiated, you can do something like this: camPos = CamPos.Instance.transform; You can read up on the singleton pattern here.
If there's going to be more than one of each, group all related objects into a single hierarchy (that is, make them all the child of a single game object). For example, if there are going to be many characters and each is going to have a separate aim location, you can make aim location a child of the character game object. Then, in your prefab (take care to make the prefab a child of the same root game object as well), you can do something along these lines: camPos = transform.root.GetComponentInChildren<CamPos>().transform; Better yet, you can have a component that has references to all such objects, and attach one to the root game object. Then, you can do: camPos = transform.root.GetComponent<ReferenceRepository>().CamPos;
Initialize the prefabs when they're instantiated. For example, say you have a player class that instantiates a weapon and already has a reference to the camPos. You can do it like this: var weapon = Instantiate<Weapon>(myWeaponPrefab); weapon.CamPos = camPos; Note however that when you assign public fields this way, they will only be accessible once Start is called. In other words, they won't be available in Awake.
That said, I don't think making stuff like aim location and crosshair location separate objects is a very good idea anyway. You should have a player/human/pawn class, and that class can provide this information to other objects that need it.

Unity Array and Instatiation

Im new in unity and I have a problem regarding arrays.
I want to be able to set the Elements of the arrays via script.
Here straight is a "public gridElementScript[] straight;"
If I'm understanding correctly, you're asking how to access Straight from another instance. If so, you need to cast your instantiated prefab to a GameObject and call GetComponent<MyComponent>() on it. Something like I've written below should work for you.
GameObject object = (GameObject)Object.Instantiate(myPrefab)
GridElementScript script = object.GetComponent<GridElementScript>();
script.Straight[0] = neighbor

Unity 5 C# - How to Change Scenes and Import all Resources from Last Scene

I'm not sure how to switch scenes and bring all of my resources with me. I do understand that upon load of new scene, the previous scene gets destroyed on load. I've explored some with DontDestroyOnLoad() but had no luck with what I'm trying to do.
I tried to make my player controller a prefab and simply put him into the next scene; however, I returned a heck of a lot of errors because of the many scripts I have. Mostly stuff like checkpoint, HP bars, and even the weapon.
What I need to know is how to import everything into the next scene. How do I do this without having to recode or even re-make all of the stuff that I need?
You're looking for LoadSceneMode.Additive. This is the second parameter of the LoadScene method and will load the new scene into the current one.
If you need to import every object from the previous scene, then what's the point in creating a new one?
What you could do is saving the objects positions into a file and then loading that file back on the next scene or try (again) with DontDestroyOnLoad();
I recommend to check the documentation of Unity about this function.
If you want an individual object not to be destroyed on the scene change then on the void Awake() function of Unity make a DontDestroyOnLoad(this.gameObject);
Could you provide more information? I ask because it seems from your description that
DontDestoryOnLoad
should accomplish what you want but you say it does not. As long as the object holding the components whose states you want to save is persisted into the next scene using that method, then all of those components' states should be persisted as well. Please elaborate and we can possibly provide a better answer. As for how to use it to save the state of every game object:
GameObject[] allObjects = UnityEngine.Object.FindObjectsOfType<GameObject>();
foreach(GameObject go in allObjects) {
if (go.activeInHierarchy) { /* and any other logic you want. Maybe like !isTerrain */
Object.DontDestroyOnLoad(go);
}
}
For the above code, I ripped it from https://answers.unity.com/questions/329395/how-to-get-all-gameobjects-in-scene.html

Coroutine wrong Behavior when scene is loaded

Ok so I have this coroutine :
IEnumerator ShowCharTraits()
{
while(!hasPlayerChosen)
{
yield return null;
traitPanel.SetActive(true);
}
hasPlayerChosen = false;
traitPanel.SetActive(false);
// Debug.Log("Got called! job done");
}
It's being called like this from the awake method in my GameManager:
players = GameObject.FindGameObjectsWithTag("Player");
foreach (GameObject g in players)
{
ui_Controller.StartShowCharTraits();
g.GetComponent<PlayerToken>().isTurn = false;
}
StartShowCharTraits() is a simple method that does this :
public void StartShowCharTraits()
{
StartCoroutine("ShowCharTraits");
}
Now, I have checked the tags, no null reference exception, actually no errors or warnings are being thrown. If i load the scene in the editor and then play it everything works fine. traitPanel.SetActive(true); get called and my panel shows up. However when I load my scene from another scene using SceneManager.LoadScene(1); the above mentioned line is never reached. Any ideas why this is happening ?
Say you want to have one central place that is "like a singleton" in a Unity project. Example,
SoundEffects
LapTimer
Scores
SocialMediaConnections
All you do is this.
make your script SoundEffects.cs
recall that every Unity project must have a "preload" scene. (it's impossible to not have one)
in the preload scene, have a empty game object called "holder". make sure it is marked "DontDestroyOnLoad"
attach SoundEffects.cs to that holder
you're done.
there's just nothing more to it.
you're finished.
it's "just that simple"
So, any particular script, which happens to be attached to any particular object, in any particular scene, may need to access "SoundEffects"...
To do so, simply do this in Awake:
SoundEffects soundEffects = Object.FindObjectOfType<SoundEffects>();
then just use soundEffects anywhere in that script, for example soundEffects.PlayBoom(13) etc etc.
So in Awake()
Laps laps = Object.FindObjectOfType<Laps>();
Social social = Object.FindObjectOfType<Social>();
AI ai = Object.FindObjectOfType<AI>();
or whatever.
Unity is simple. Incredibly simple. It's just that easy.
write your script, LapTimer.cs or whatever
put it on a holder object in your preload scene (where else could it be?)
there's no "3", that's all there is. It's just that ridiculously simple.
Note that...
In the early days of Unity, someone unfortunately mentioned "singletons" on a QA board somewhere. (You can't have "singletons" in an ECS system, it's meaningless.) At the time, this led to huge discussions about how you can make a "singleton-like thingy" in Unity, which is piling confusion on confusion. Unfortunately from that day to this, you get people learning Unity, who see "singleton" mentioned here and there on the net, and it leads to endless confusion.
Once again, note that the idea of "managers" is just impossibly simple in Unity - explained above. It's trivial. It just couldn't be easier.
Note, above I mention you might want syntactic candy to avoid the incredible chore of typing Laps laps = Object.FindObjectOfType<Laps>();
There are very unfortunately no macros in Unity/c# so you need another way.
All you do is use a "Grid" script http://answers.unity3d.com/answers/1124859/view.html which has been popular for years in Unity.
But honestly, it's so simple to use Scores scores = Object.FindObjectOfType<Scores>(); that I usually just do that nowadays.
Ok how do I explain this. I have a singleton that acts as a data holder. While developing the scene with the game manager I had attached the singleton to the gamemanger object that hold a bunch of scripts. Now when I made the main menu I ofc added my singleton to it so I can carry info to the game scene and because of this my whole game manger object was being deleted. This is the culprit from the DataHolder :
void Awake()
{
if (instance == null)
instance = this;
else if (instance != this)
Destroy(gameObject);//This right here.
DontDestroyOnLoad(gameObject);
}
So I changed that line to Destroy(gameObject.GetComponent(instance.GetType()));

Categories

Resources