0
\$\begingroup\$

I am aiming to create a Unity project with a code structure similar to ECS. I want the code to be consistent, easy to integrate extend and expand if multiple developers will work with it.

By that I mean I want to centralize as much as I can the source of bugs and errors.

For example, if there is a problem with the mouse dragging one object, the source of the bug should be the dragging system class and not a class attached to that object.

So, basically, I want to write common logic once, and centralize as much as possible the source of error.

Before showing a sample of the code, I want to say I come from a professional software development background, so I think there is importance in following guidelines and design patterns to avoid troubles that come with developing large systems instead of dealing with them.

For now a simple drag "system" is implemented. There are 3 classes:

  • InputManager.cs
  • DragManager.cs
  • Properties.cs

InputManager.cs detect a drag on an object and raises a Drag event public static event Action<Transform, Vector3> MouseDragEvent, that event is consumed by the DragManager.cs class which takes some properties (isDraggable, dragSpeed) from the Properties.cs class and moves the Transform given as parameter by dragSpeed.

Question: Is this design bad or good? It may be overkill but that seems to satisfy the first paragraph.

Code:

InputsManager.cs

public class InputsManager : MonoBehaviour {

    public static event Action<Transform, Vector3> MouseDragEvent;
    public static event Action<Transform, Vector3> ObjectClickedEvent;

    Ray ray;
    RaycastHit rayHit;

    DragManager _dragManager;
    Transform draggedObject = null;

    ClickManager _clickManager;
    Transform clickedObject;
    
    // Mouse Buttons States
    bool lastMouseButtonDownState = false;


    // Use this for initialization
    void Start () {
        _dragManager = GetComponent<DragManager>();
    }
    
    // Update is called once per frame
    void Update () {

        if (!lastMouseButtonDownState)
        {
            draggedObject = null;
        }
        if(draggedObject == null)
        {
            ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out rayHit))
            {
                GameObject hitObject = rayHit.collider.gameObject;
                if (hitObject != null)
                {
                    Properties hitObjectProperties = hitObject.GetComponent<Properties>();
                    if (hitObjectProperties != null)
                    {
                        if (lastMouseButtonDownState)
                        {
                            draggedObject = hitObject.transform;
                        }
                        else
                        {

                        }
                    }
                }
            }
        }

        if(lastMouseButtonDownState && draggedObject)
        {
            MouseDragEvent(draggedObject.transform,
                                Vector3.Scale(Camera.main.ScreenToWorldPoint(Input.mousePosition), new Vector3(1, 1, 0)));
        }

        lastMouseButtonDownState = Input.GetMouseButton(0);
    }
}

DragManager.cs

public class DragManager : MonoBehaviour {

    Properties properties;

    void Start () {
        properties = GetComponent<Properties>();

        InputsManager.MouseDragEvent += Drag;
    }

    public void Drag (Transform target, Vector3 newPosition) {
        Debug.Log(target);
        target.position = newPosition;
    }
}

Properties.cs

public class Properties: MonoBehaviour {
    public bool IsDraggable;
    public float DragSpeed;
}
\$\endgroup\$
5
  • \$\begingroup\$ Currently this architecture doesn't actually do anything. I think you will see if this architecture works for you or not when you actually start to implement gameplay. Depending on your game mechanics you might end up with a DragManager which does either nothing or far too much. The one thing that really seems "bad" to me at first glance is a class that is simply named "Properties". I hope you don't intend to cram every single property an entity in your game can have all into a single class. Perhaps that MonoBehaviour should rather be called "DragProperties"? \$\endgroup\$
    – Philipp
    Jan 11 at 8:59
  • \$\begingroup\$ Right the properties should be split into multiple classes. It's true it will depend on the game, and the current game will possibly be a mobile game that involves clicking and dragging objects. With that in mind I aimed at interactive games mostly. I am aiming at writing the code using "composition" pattern if the word is correct. So at a later stage if no dragging will happen in another game, i could simply remove some code instead of reusing old functions and old code to copy it into a new gameobject script. Does this sound worse than just going the normal "gameobject script" way ? \$\endgroup\$
    – user159431
    Jan 14 at 17:23
  • \$\begingroup\$ This sounds a bit as if you are trying to develop an "universal architecture" which you are then planning to apply to every game you will develop in the future. This might be a rather futile endeavor, because different games tend to have very different requirements. It's usually better to plan the architecture for each project from scratch while keeping the specific requirements of that project in mind. \$\endgroup\$
    – Philipp
    Jan 14 at 18:50
  • \$\begingroup\$ Regarding "aiming for a composition pattern": This is usually a good approach in Unity. The Unity game engine is built around the composition principle. But again, no solution fits every game. \$\endgroup\$
    – Philipp
    Jan 14 at 18:51
  • \$\begingroup\$ @Philipp Thank you. And is there any code repo of a game that is considered industry standard ? No matter the language. It would be helpful to see what and how it's being done in the industry \$\endgroup\$
    – user159431
    Jan 14 at 20:23

You must log in to answer this question.

Browse other questions tagged .