MVC in Unity with Scriptable Objects Part 3
Tags: gamedev, beginners, unity3d, mvc
Published: 2019-10-24 15:32:54

Here is the last part of the MVC project.

I've tried to make a schema to illustrate the workflow of MVC in unity. 

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/2oojzjohhflaktomqvdt.png)

In a unity app, MonoBehaviour objects live in a scene, so you could see what objects in the hierarchy. But these objects can't communicate with each other directly. MVC pattern in unity is a useful solution to that problem.

Let's try to write it simply:

User input --> Controller -----createView(ModelData)-----> View -----display(ModelData)

First, we wait for input from the user like a button click. Next, the Controller provides the view(as prefab in project) and what model needed to pass to be able to display in this view. Then, Controller instantiates the View and creates it in the scene with the data provided from the Controller. Now, View is ready and holds references for UI objects, passes data to those references to be displayed.

Let's make it in unity from where we left.

I'll work on the view first. I'll create a panel that contains uGUI objects.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/aac657lr281x3ik6mkfq.png)

We have a panel and an Image for item icon, three text objects for name, type and attack power, respectively. To hold a reference for these objects, create a class in the project, `InfoView`, add to InfoView object in the scene. 


![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/bmrg2scoqifbnhyjyoqr.png)

```c#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class InfoView : MonoBehaviour
{
    public Image icon;
    public Text nameText;
    public Text typeText;
    public Text attackText;
}

```

Next, let's add an init method to pass info to those references.

```c#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class InfoView : MonoBehaviour
{
    public Image icon;
    public Text nameText;
    public Text typeText;
    public Text attackText;

    public void Init(ItemData data)
    {
        icon.sprite = data.icon;
        nameText.text = data.name;
        attackText.text = "Attack Power: " + data.attack;
        
        switch (data.type)
        {
            case ItemType.Axe: typeText.text    = "Type: Axe"; break;
            case ItemType.Dagger: typeText.text = "Type: Dagger"; break;
            case ItemType.Hammer: typeText.text = "Type: Hammer"; break;
            case ItemType.Potion: typeText.text = "Type: Potion"; break;
        }
    }
}
```

Then, assign UI objects in the editor.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/2b05a0v4zwkjfg74f0a5.png)

It's ready to make a prefab for this view. I'll make a folder as `Resources`. This is a special folder that unity has an access API to this specific folder. Place this prefab in Resources.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/melc65oc5o3t41b9ayk8.png)

I've organized my project folders a bit. Now all prefabs in my `Resources` folder and I can access via API.

Since I will `Instantiate` view prefabs, delete InfoView from scene.--

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/fqifb8fponnwimgzi3ws.png)

Time to open Controller.

I'll make a public `Transform` to point who is going to be the parent of this view, and a private variable to store a reference to `ViewInfo` at start.

```c#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ItemViewController : MonoBehaviour
{
    public Inventory inventoryHolder;
    public Transform inventoryViewParent;
    public Transform infoViewParent;

    private GameObject infoViewPrefab;
    private GameObject itemViewPrefab;

    private void Start() 
    {
        itemViewPrefab = (GameObject)Resources.Load("Item");
        infoViewPrefab = (GameObject)Resources.Load("InfoView");
    }
}
```

Create a method to instantiate view into the scene.

```c#
private void CreateInfoView(ItemData data)
{
var infoGO = GameObject.Instantiate(infoViewPrefab, infoViewParent);
infoGO.GetComponent<InfoView>().Init(data);
}
```

I'll give this method to `ItemView` in `InitItem` , you guessed right thanks to `Action<>` in c#. Let's modify a bit `ItemView` to achieve that.

```c#
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class ItemView : MonoBehaviour
{
    public Button button;
    public Image itemIcon;

    private ItemData itemData;

    public void InitItem(ItemData item, Action<ItemData> callback)
    {
        this.itemData = item;
        itemIcon.sprite = itemData.icon;

        button.onClick.AddListener(() => callback(itemData) );
    }
}
```

So here, I've added a parameter more to pass a method.

Now I can wire up in the controller.

```c#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ItemViewController : MonoBehaviour
{
    public Inventory inventoryHolder;
    public Transform inventoryViewParent;
    public Transform infoViewParent;

    private GameObject infoViewPrefab;
    private GameObject itemViewPrefab;

    private void Start() 
    {
        itemViewPrefab = (GameObject)Resources.Load("Item");
        infoViewPrefab = (GameObject)Resources.Load("InfoView");

        foreach (var item in inventoryHolder.inventory)
        {
            var itemGO = GameObject.Instantiate(itemViewPrefab, inventoryViewParent);
            itemGO.GetComponent<ItemView>().InitItem(item, CreateInfoView);
        }
    }

    private void CreateInfoView(ItemData data)
    {
        var infoGO = GameObject.Instantiate(infoViewPrefab, infoViewParent);
        infoGO.GetComponent<InfoView>().Init(data);
    }
}
```

At `Start`, I populate inventory with items, and when you click items, `CreateInfoView` fires up. But before testing it out, I saw a problem here. Controller doesn't know if there is an `InfoView` created before we click. Let's check before `Instatiate`.

```c#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ItemViewController : MonoBehaviour
{
    public Inventory inventoryHolder;
    public Transform inventoryViewParent;
    public Transform infoViewParent;

    private GameObject infoViewPrefab;
    private GameObject itemViewPrefab;

    private GameObject infoView;

    private void Start() 
    {
        itemViewPrefab = (GameObject)Resources.Load("Item");
        infoViewPrefab = (GameObject)Resources.Load("InfoView");

        foreach (var item in inventoryHolder.inventory)
        {
            var itemGO = GameObject.Instantiate(itemViewPrefab, inventoryViewParent);
            itemGO.GetComponent<ItemView>().InitItem(item, CreateInfoView);
        }
    }

    private void CreateInfoView(ItemData data)
    {
        if (infoView != null)
        {
            Destroy(infoView);
        }

        infoView = GameObject.Instantiate(infoViewPrefab, infoViewParent);
        infoView.GetComponent<InfoView>().Init(data);
    }
}
```

Here, I've made a variable `infoView`, and when I try to make a new `InfoView` in the scene, first, I check if there is any.

Now time to give it a go.

Hit to play.

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/tuv8zo677vslveph8pyk.gif)

It seems we made it!

Project on [github](https://github.com/cemuka/intro-to-so).

This was a gentle intro to MVC in unity with Scriptable Objects. But I believe it could be implemented like this way to any project. Especially, when receiving REST calls in unity, this pattern could be a life-saving pattern to keep your code organized and scaleable. In unity, it could be a challenge to maintain your objects and communicating them via code. Some may argue with the best solution could be Singletons. They're right, this is not the only way, but a good one.

I think it could be possible to live without design patterns as well, but I'm sure that would be no different from medieval :) 

Anyway, since this series completed, I suggest you check my other series using MVC and Scriptable Objects as well: [Making a REST service using Node and Express to use with Unity](https://dev.to/cemuka/making-a-rest-service-using-node-and-express-to-use-with-unity-part-1-321n).

Happy coding unity ninjas!