- Home /
Creating script fields via code
I am trying to build, what I call an identifier script. This script, when placed on an object, will have fields that the user can use to define the objects properties. For example, if the object is an animal or a plant. What I want to do, is be able to change what the user can pick based on their earlier answers. For example, if the user defines the object as a bird a new field will appear asking how fast the bird can fly. Does anyone have any ideas on how to do this?
This could veer way off on some deep/machine learning tangent. It will get very, very complicated (from an implementation perspective) if you don't want to just do giant if-else trees. If you limit your scope to a known set of objects (flora, fauna, inanimate object, etc) it's somewhat easier to implement, but you'd still be stuck with massive if-else ladders and working from a fixed set of properties for each type. If you go the machine learning route, that would take a massive amount of training data to get right. The how is spread on numerous research papers on deep and machine learning.
There is no way to easily make variables available to the user if they selecte certain criteria?
It depends if you've created the vars ahead of time or you're trying to create them at runtime. I didn't quite get that from your question.
Answer by JVene · Aug 01, 2018 at 10:39 PM
Fortunately you haven't asked about the UI design for such an exchange, because that has myriad possible solutions. You could present one question which leads to a dialog, which itself leads to other dialogs, each one selected based on the answers from the previous. It could be implemented as a tabbed dialog, where the appropriate questions are presented on each tab. It has been done using a tree control, where expanding appropriate entries in the tree expose a set of options as entries in the expanded tree node.
In all of these there are some vaguely common design elements for the code. The details vary according to the UI approach, but you are basically going to create a representative dialog for each permutation of options which ultimately land on a specific set of prerequisite answers to key questions. Your question almost outlines how that is presented - you first ask for plant or animal, presenting the plant dialog when the user selects that, or the animal dialog (or an exit if they back out).
After that, you're talking about how to represent these different choices. What you want to avoid is the notion that there would be, say, 20 options that result from this interview with the user, where the owning object (some GameObject the script is attached to) has 20 member variables, 19 of which would be null and the one the user selected is the only one with an attached object.
What you want, instead, is to create a hierarchy of classes based on the notion of a generic game element. The base class of this design has no idea what it is (it could be a plant or an animal, any one of 10 plants or 25 animals).
All service required of that game element is operated from this base class using abstract functions, making the base an abstract class. The specific selections about the plant the user chooses, or the animal, is stored in the derived class, and the unique behaviors required of that game element is controlled by the derived class. Look into the use and design of abstract classes in C# if you're unsure.
It can be tough to get started in this direction, so here's the major single hint that gets over the initial block new authors have with abstract classes: you're probably forwarding the Update call from your script to the game element (an abstract Update function of your own implementation).
In a naive design, you'd probably flood the MonoBehaviour (your script) with all the variables for plants and animals, and all permutations of them, with some bools or a number indicating what the selection the user made. This means you end up with massive if/elseif/else tests to mutate behavior of the script to suit the various behavioural situations, which all get squeezed into a massively overcomplicated Update or FixedUpdate function of the script.
Since Unity's primary "hook" into your script is Update or FixedUpdate (along with Start, Awake, etc.), your primary hook for these game elements I propose is the Update or FixedUpdate call. That is to say, when you create an abstract base class for the game element that could be plants or animals, the base is most likely going to forward the Update call. Routed from an abstract function, this "automatically" chooses code appropriate for the user's selection (based on what derived class is instantiated), so there are no massive if/elseif/elseif tables in Update required. You probably want to forward a reference to "this" of the script's MonoBehaviour derivative so the game element can do all that would be done inside Update of the script.
Further, you may benefit from studying the factory pattern as a means of creating the derived objects as that is typical in this design motif.
Just so I understand, you are saying that I should have a individual script for each plant or animal. Each script would inherit from a parent script which would inherit from an overall base script. Am I understanding that correctly? As a side note what do you mean by "forward a reference to "this" " and "Unity's primary "hook""?
The word script is unfortunate. It isn't a program$$anonymous$$g concept. A script is just a text file. The central program$$anonymous$$g concept you're actually describing is the class, otherwise known as an object (not a GameObject) when instantiated.
I make a point of this because Unity students tend to think scripts and objects, or classes, are the same thing. They aren't. $$anonymous$$ore importantly, Unity students tend to think classes are all handed to them by Unity, and therefore derived from $$anonymous$$onoBehaviour. Classes can be stand alone, derived from nothing, or derived from a base of their own creation, entirely unassociated with Unity (as a C# program$$anonymous$$g concept), yet consumed and used in Unity classes.
To your specific question, substituting the word class for script, the answer is a qualified "sort of". That is, there would be an abstract base representing the element of the game you're ultimately identifying as a plant or animal. However, the design of the plant class is up to you. You could have a generic plant class which is sufficient for all plants, typified by some artwork which itself just a selection. That could imply one class for all plants, but then you may have reason to differentiate, say, trees from weeds, which could, then, imply two classes.
To be clear, however, the plant calls (if one suffices for your purposes) is a derivative of the game element base, so when I say one plant class (or two, one for trees and another for weeds), I'm counting the derived classes, and assume it is understood the is one common base class from which it (or they) derive.
Likewise, your design shows how many element classes there must be. You may have no reason to be more descriptive or specific than to have one animal class which suffices for all animals, but your design may indicate there are two or three types of animals, say reptiles, birds and mammals. The number of classes depends on how your use of this design implements the variations.
During your work you may start with one animal class, then after fleshing out your application realize "your doing it again" - "It" being that thing that happens when you're writing massive "if/elseif/elseif/" tables, or repeating the same code in different places. This is a clear signal that an object is hinting to you that it should exist, but you've not written it yet.
That is the real driving issue here. Where you implement varied behaviour from a common theme, you're likely designing a hierarchy of classes derived from a base class that is likely abstract. Whenever you're repeating code all over the place, this likely hints the job should be handled by a class more automatically (and therefore more reliably). Whenever you're making lots of "if/elseif/elseif" logic, you're "mutating" behavior based on tests, which is why abstract classes exist - if your design merely started using them.
So to recap, the whole point of using a main class and lower classes is to reduce the amount of repeating code?
Your answer
Follow this Question
Related Questions
Distribute terrain in zones 3 Answers
Best way to defining scripts within a list inside the editor? 1 Answer
Multiple Cars not working 1 Answer
Exposed Areas 1 Answer
Sceneview Lags when using Arrays 0 Answers