You can use a generated MDriven model from a Unity 3D script to load model objects and create Unity GameObjects from them; this guide is for developers building the documented Mono/Unity 3.5 proof of concept.
Scope and compatibility
This integration was demonstrated with Unity's Mono runtime and a class library targeting Unity Full v3.5 base class libraries. The example uses the EcoCore NuGet package and an XML persistence file.
The instructions below document that integration approach. Before starting a new Unity project, confirm that your Unity version, target framework, MDriven assemblies, and package versions are compatible. The original setup used Visual Studio 2015 Tools for Unity to obtain the Unity-specific framework profile.
What you will build
You will create a class library that contains:
- Generated code for an MDriven model and an EcoSpace.
- A Unity
MonoBehaviourscript. - An XML-backed persistence mapper that reads game data from a local file.
When Unity starts the scene, the script loads all Player objects from the model, creates one prefab for each player, positions the prefab, and shows the player's score in a TextMesh.
For example, if the XML file contains three Player objects, the scene creates three car prefabs and writes each player's Score on its text mesh.
Prerequisites
- A Unity project with a scene in which you can add a GameObject.
- Visual Studio and the Unity-specific target framework profile used by this integration.
- An MDriven model containing the classes you want to use. The example uses a
Playerclass with aScoreattribute. - A prefab stored in Unity's
Resourcesfolder. The example calls itMyCarPrefaband gives it a childTextMesh. - A writable location for the XML persistence file, such as
C:\temp\Gamedata10.xml.
MDriven generates strongly typed C# classes from your model. For the broader framework programming model, see Documentation:MDriven Framework.
Create the model class library
- In Visual Studio, create a class library.
- Set its target framework to Unity Full v3.5 base class libraries, as used by the documented Unity/Mono setup.
- Install the MDriven core assembly package in the Package Manager Console:
Install-Package EcoCore
- Verify that the MDriven assemblies are added to the project references.
Add an EcoSpace and model
The project needs an EcoSpace—the generated runtime context for the model—and the model that supplies its generated classes.
You can add these by temporarily adding a project that already contains an EcoSpace and model, then moving the required model and generated items into the Unity class-library project. Remove temporary project items that are not needed afterward.
If you use an existing model, link to both the model file and its package folder rather than creating a duplicate model. The original example refers to the package folder as EcoProject1.
Delete the default Class1 file created with a new class library if it conflicts with a model class named Class1.
- Make a small model change, such as adding
Player.Score. - Generate the model code.
- Build the project and resolve the remaining assembly-reference errors before moving on.
Configure local XML persistence
The original generated setup used PersistenceMapperSharer. That mapper is intended for server-side scenarios where multiple clients share a persistence mapper. For this local Unity sample, replace it with PersistenceMapperXml so the game reads and writes an XML file.
In the EcoSpace initialization code, create the XML mapper, set its file name, and assign it to PersistenceMapper:
Eco.Persistence.PersistenceMapperXml xmlpm = new Eco.Persistence.PersistenceMapperXml();
xmlpm.FileName = @"c:\temp\Gamedata10.xml";
this.PersistenceMapper = xmlpm;
Do not keep the PersistenceMapperSharer field and initialization for this local-file scenario. For example, remove code equivalent to:
private Eco.Persistence.PersistenceMapperSharer persistenceMapperSharer1;
this.persistenceMapperSharer1 = new Eco.Persistence.PersistenceMapperSharer();
this.persistenceMapperSharer1.MapperProviderTypeName =
"EcoProject1.EcoSpaceAndModel1.EcoProject1PMP";
this.PersistenceMapper = this.persistenceMapperSharer1;
The file path is part of the sample configuration. Ensure that the directory exists and that the process running Unity can write to it.
Reference UnityEngine and create the script
Your class-library project must reference UnityEngine.dll. In the documented Windows Unity installation, it was located under Unity's editor installation in the Windows standalone support managed assemblies.
- Add a reference to
UnityEngine.dllfrom your Unity installation. - Set the reference's Copy Local property to False. Unity supplies its own copy of this assembly; copying another copy into the project can cause conflicts.
- Add a class that derives from
MonoBehaviour.
using UnityEngine;
namespace ClassLibrary1
{
public class MyScriptThatUseMDriven : MonoBehaviour
{
void Start()
{
Debug.Log("Start!!! works?");
}
void Update()
{
Debug.Log("works?");
}
}
}
Unity finds a MonoBehaviour attached to a scene object and calls its lifecycle methods. Use Start for initial model loading. Do not leave a logging Update method in production code: Unity calls it repeatedly while the game runs.
Deploy the assembly to the Unity project
Unity must receive your built class library and its dependencies.
- In the Unity project, create a folder under
Assets, for exampleAssets\MyVSAssemblies. - In the Visual Studio class library, add a post-build event that copies the build output to that folder.
- Build the class library.
- Return to Unity and wait for it to compile the copied assemblies.
The documented post-build event was:
xcopy "$(TargetDir)*.*" "C:\temp\TheMDrivenTestProject1000\Assets\MyVSAssemblies" /Y
Replace the destination with the Assets\MyVSAssemblies directory in your own Unity project. The copy includes dependencies from the build output, but UnityEngine.dll must not be copied because its reference has Copy Local set to False.
If Unity reports a missing assembly in its Console, add the missing reference to the Visual Studio project and set its Copy Local behavior as required by that assembly. The original example required a reference to WindowsBase.
Prepare the Unity scene and prefab
- Open the Unity project and scene.
- Add an empty GameObject. It acts as the scene object that owns the MDriven script.
- In the Project window, locate the compiled script in
MyVSAssemblies. - Drag the script onto the empty GameObject.
- Press Play and check the Unity Console for the
Debug.Logoutput.
Next, create the prefab that represents each model object:
- Create a prefab and name it
MyCarPrefab. - Add a
TextMeshto the prefab or one of its children. - Place the prefab in a
Resourcesfolder so thatResources.Load("MyCarPrefab")can find it.
The prefab can be a cylinder, car, or another visual object. The important requirement for the sample is that GetComponentInChildren<TextMesh>() finds a text mesh.
Load model objects and instantiate prefabs
In Start, create and activate the generated EcoSpace. Query the Player extent, instantiate one prefab for each player, move each instance so objects do not occupy the same position, and set the text mesh to the player's score.
void Start()
{
Debug.Log("Start!!! works?");
_es = new EcoProject1EcoSpace();
_es.Active = true;
var players = _es.Extents.AllInstances<Player>();
int c = 0;
foreach (var x in players)
{
c++;
GameObject go = (GameObject)Instantiate(Resources.Load("MyCarPrefab"));
var p = go.transform.position;
p.Set(p.x + (c * 2.5f), p.y + (c * 2), p.z);
go.transform.position = p;
go.GetComponentInChildren<TextMesh>().text = x.Score.ToString();
}
}
Replace EcoProject1EcoSpace, Player, and Score with the generated EcoSpace, class, and attribute names from your model.
This is a one-way visualization example: model data is read when Start runs and used to create Unity objects. The same approach can be extended to send user changes back to the model, but that behavior is not part of this sample.
Create sample data
The XML file will not display anything until it contains Player objects.
- Start the MDriven debugger for the model.
- Create a few
Playerobjects and assign a value to eachScore. - Open the DirtyObjects tab.
- Select the changed objects and press Update selected to persist them to the XML file configured in the EcoSpace.
- Run the Unity scene again.
For example, create players with scores 10, 20, and 30. The scene should create three instances of MyCarPrefab, with those values shown in their text meshes.
Troubleshooting
| Symptom | Check |
|---|---|
| Unity does not show the script as a component | Build the Visual Studio project, confirm that the output was copied beneath Unity's Assets folder, and allow Unity to compile it. Confirm that the class derives from MonoBehaviour.
|
| Unity reports assembly errors | Check the Unity Console for the missing assembly. Add that reference to the class library. Do not copy UnityEngine.dll; set its Copy Local property to False.
|
| No prefabs appear when Play starts | Confirm that the XML file contains persisted Player objects, that the EcoSpace is active, and that the generated type names in the script match the model.
|
| A prefab is created but has no score text | Confirm that MyCarPrefab contains a TextMesh in itself or a child, and that the script can find it through GetComponentInChildren<TextMesh>().
|
| Objects appear on top of each other or inside terrain | Review the position calculation. The example offsets each object by its loop counter; adjust the coordinates for the terrain and prefab used in your scene. |
For a visual walk-through of this proof of concept, watch Unity + MDriven.
