Search Unity

Tool selection mechanism

Discussion in 'Scripting' started by Vesuvius, May 22, 2015.

  1. Vesuvius

    Vesuvius

    Joined:
    May 22, 2015
    Posts:
    2
    Hey,
    I've recently discovered Unity and have started learning how to use it (I have previous C# experience). I have done one of the basic tutorials and have also read through the manual, though I did skip some of the parts concerning graphics and modeling, as I prefer my project to have basic working features before making it look nice.

    What I'm currently trying to make is a tool selection system for a sandbox game. I'm thinking of a sandbox game where the player can select a tool from a panel in the GUI, and then use the selected tool to modify the scene (change terrain, place objects, etc.).

    I'd appreciate some insights about what's wrong with the following design I wanted to use:
    My GameController script would contain logic for choosing the current tool:
    Code (CSharp):
    1. /// <summary>
    2. /// An object responsible for managing gameplay
    3. /// </summary>
    4. public class GameController : MonoBehaviour
    5. {
    6.     /// <summary>
    7.     /// The tool currently in use by the player
    8.     /// </summary>
    9.     private ITool _currentTool;
    10.  
    11.     // Event handling for clicking on a button in the
    12.     // GUI goes here and changes _currentTool
    13. }
    My tools would be MonoBehaviors implementing the following interface:
    Code (CSharp):
    1.     /// <summary>
    2.     /// An interface which is the base for any tool in the game,
    3.     /// i.e. something the user can use to modify the scene (build,
    4.     /// edit terrain, place stuff, etc.)
    5.     /// </summary>
    6.     interface ITool
    7.     {
    8.         string Name { get; }
    9.  
    10.         /// <summary>
    11.         /// Builds whatever the tool is supposed to build,
    12.         /// e.g. constructs a wall, places a chair, etc.
    13.         /// </summary>
    14.         void Build();
    15.     }
    I thought that being MonoBehaviors, my tools could interact with the user (e.g. execute when the mouse is pressed, find where the mouse is placed, etc.).

    Now the problem I have encountered was that I couldn't find a way to set _currentTool in my game controller. I couldn't create a new instance of my tools (You are trying to create a MonoBehaviour using the 'new' keyword. This is not allowed. MonoBehaviours can only be added using AddComponent(). Alternatively, your script can inherit from ScriptableObject or no base class at all).
    I tried to use AddComponent, but since GameController.cs is a MonoBehavior itself, it doesn't have AddComponent; I couldn't use ScriptableObject for my tools, because then I wouldn't have all the events a MonoBehavior can handle (e.g. OnMouseDown). Since those are the only two suggestions in the exception, I'm kind of out of ideas on how to implement this.

    As I said, I'd appreciate any help or insights about this design for such sandbox games.
    Thanks in advance!
     
    Last edited: May 22, 2015
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,697
    The .AddComponent<>() method operates on a GameObject and accepts a MonoBehavior type, which it then attaches to said GameObject, and "plumbs in" all the necessary goodness to make it operate.

    So if you have an GameController script object called foo, and you want to add another script to it, you would use:

    Code (csharp):
    1. foo.gameObject.AddComponent<OtherScript>();
    Conversely, the Unity3D way is to create a prefab that has all the necessary things on it you can possibly use, and then have a master script that turns all of them off (using foo.enabled = false;) except the one that you want.

    That way you are not adding/removing scripts at runtime, which of course is fine, but it does lose the entire state of that local script object when it is removed/readded.

    Just a few thoughts to try.
     
  3. Vesuvius

    Vesuvius

    Joined:
    May 22, 2015
    Posts:
    2
    Thanks a lot for your tips.
    On the specific scenario that I presented, where the tools are stateless and could actually be static, and there is no situation where two tools will be used at the same time, is there any benefit in using a prefab?
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,697
    Honestly that's kind of a philosophical statement, really only answered by your own work situation and preferences. If you have a team, the prefab can encapsulate a certain useful set of shared functions, as well as represent a fine-grained unit of "work delivered" that can be very helpful. Other people prefer to hand-code everything themselves and essentially put the objects together at runtime, usually with some sort of factory pattern.

    I can only summarize by saying "Try it a little bit each way, get a feel for what you're dealing with."