Hello,
I’m an intermediate level programmer coming from VB, and I’m getting up to speed on C# to start rebuilding a game I was working on in VB for Unity 5.
My question is what the best way is to essentially assign object data to game objects. For example, if I want to show a star map, in VB I would create a StellarObject class, and derive a Star clas from that, with important information (name, star class, color, etc) and for display purposes create a worldPosition to use for a UI class.
With Unity, it seems to require shoehorn object data into components, and while I have managed to get a working prototype by creating Star prefabs and attaching a StarData script to it with the name, class, size, etc info, this feels very clunky to me by having to use GetComponent to access the data members. I want to be able to use the prefab as the object so that the UI will be easier, but I’m just struggling with having to use MonoDevelop classes and not being able to simply ‘new’ a Star object when I need it. Thoughts? Thanks!
Steve
Instantiate is basically “new” for Unity GameObjects. If you have a reference to the Star prefab (or even to an existing star in your scene), you can write a function that will Instantiate a new copy of it and then do whatever you want to it.
Instead of a constructor, you can write a static method that Instantiates, initializes, and returns a Star, and then you can use that method pretty much exactly like you’re used to using “new”.
You will want to read about the Component Pattern and Composition over Inheritance discussion.
Unity maps game algorithms into behaviors to be plugged at game objects. This entity/behavior decoupling can result in better, more reusable code if done properly.
Anyway nothing holds you from creating pure (non monobehaviour classes) and call then from a behavior. This is done sometimes (but not always) using Singletons.
1 Like
Not sure i understand there seems to be more question than one intermixed. You can either use:
gameobject go = Instantiate(StarPrefab) as gameobject;
stardata myStar = go.getcomponent<stardata>();
//then handle myStar as if it was a normal object instantiated from any old class accessing mydata.stellartype or mydata.gosupernova() as you please
Or you can write your own classes that do not derive from monobehavior and manipulate those in your datamodel/simulaton as you please. Only instantiate prefabs for the things you need to show. Those prefabs would access your datamodel/simulation through a reference to the data-class. (see model-view-control pattern for instance)
These are all handy responses, thank you! Brominion, I am basically writing a turn-based 4X where the GameObjects will act as objects to click on, but there will be a lot of ‘pure’ classes. The player will not manipulate the actual GameObjects beyond clicking on them - I am more looking for the best way to tie in the object data (name, star class, color, etc) with the object prefab representing it in the game. There will be some object scripting (rotating stars and such) but I am comfortable with that interaction. It’s just tying the Star data to the Star prefab, so that when the player selects that specific prefab, it will access that Star’s data.
I think the model-view-control is what I’m trying to replicate, and in theory using Unity’s GameObjects should be easier (I can just program an event when a player clicks a star to do something instead of programming a UI class from scratch) but the game is VERY data-driven so it was one of my concerns with using the engine in the first place.
Steve
A corollary question: if I want to write a pure Star class, how can I attach it to a prefab? I struggled with this, hence my original question. I didn’t seem to be able to reference the class members without attaching it as a Conponent, which I couldn’t do without making the Star data script a MonoBehavior.
Steve
I would have imagined the point of a “pure” class would be so that you didn’t have to attach it to a prefab. If you’re attaching it to a prefab, what is the downside of making it a MonoBehavior?
If you need it to sometimes be attached to a GameObject and sometimes not, you could create a MonoBehavior wrapper whose sole purpose is to have a public field of your pure class (and initialize that field in its Awake() method).