Using a selfmade C# class in a Unity 3D script

This example was part of a project where I wanted to move an object in Unity 3D triggered by events from a C# class in a DLL created with Visual Studio Express 2010. I am using C# edited with MonoDevelop for Unity 3.5.

There were my steps:

  • Create a DLL with Visual Studio
  • Implement a simple C# class without any events
  • Import the DLL in Unity 3D
  • Use the simple C# class from a Unity script
  • test the C# with the debugger in Unity

Step 1: Create a DLL with Visual Studio

  • Create a new project
  • Choose a C# project: class library
  • Name the new project: MyDllForUnity
  • Rename your class to MyClassForUnity (you can also rename the .cs file)
  • I’ve read that Unity 3D doesn’t support namespaces in user code yet. So I removed the namespace that Visual Studio automatically has added. Remove the namespace line and the opening and closing bracket from the C# file.
  • To allow Unity 3D to ‘talk’ to our class we have to make it of a base type that Unity can understand. This base class is called MonoBehaviour.
  • This base class is stored in a DLL from Unity that is called UnityEngine.dll. First we have to add a reference to this dll in our Visual Studio project.
  • Choose add reference and browse to your unity program files. Select the UnityEngine.dll from the folder

    \Program Files\Unity\Editor\Data\Managed\

  • The base class MonoBehaviour from this dll is defined in a namespace class UnityEngine. Make this namespace known to our code by adding a using statement.

    using UnityEngine;

  • Now we can derive our class from the base class MonoBehaviour.

    public class MyClassForUnity : MonoBehaviour
    {
    }

  • Important: Unity 3.5 doesn’t seem to support DLL made for the .NET framework 4. By default visual studio created the project for .Net framework 4. We have to change our project to be made for a lower version framework. I’ve used 3.5 in this example. If you forget this, you will get the following error message while running your script in Unity:

    Internal compiler error. See the console log for more information. output was:
    Unhandled Exception: System.TypeLoadException: Could not load type 'System.Runtime.Versioning.TargetFrameworkAttribute' from assembly 'MyDllForUnity'.

  • In visual studio. Select the properties of your project. In the Application tab, change Target Framework to: .Net Framework 3.5.
  • Save you project to any location. In the next step we’re going to going our DLL to a unity project. I’ve used D:\Documents\Visual Studio 2010\Projects\MyDllForUnity.

Step 2: Implement a simple C# class without any events

  • First we add a simple implementation to this class. A function to retrieve a string with version information. Our C# class should now look something like this:

    using System;
    using UnityEngine;

    public class MyClassForUnity : MonoBehaviour
    {
    public string GetVersion()
    {
    return "MyClassForUnity version 0.1";
    }
    }

  • Build the DLL (in release).

Step 3: Import the DLL in Unity 3D

  • I assume you already have a Unity 3D.
  • Unity expect external dll’s to be placed in a folder plugins inside the assets folder. It is doesn’t exist yet, create in. It will be something like this now:

    \Documents\New Unity Project\Assets\Plugins

  • Import our DLL as an asset from the Unity menu Import new Asset…. Select the dll from it’s visual studio location. That could be called something like this:

    \Documents\Visual Studio 2010\Projects\MyDllForUnity\MyDllForUnity\bin\Release\

  • Verify that the import was succesfull. In the Projects tab of Unity. Expande ‘Plugins’. You should see our dll MyDllForUnity. When you expand the dll, you should see our class MyClassForUnity.

Step 4: Test the simple C# class from a Unity script

  • Open (Edit) a script where we want to use our dll.
  • Unity has already added our dll to it’s references. You can examine this by looking at the references of the Assembly-C Sharp of the solution of your project (in MonoDevelop)
  • There is no need to add a usingstatement here, because our class is not in a namespace.
  • Add a member variable myClassObject for our class in the class of the scripts. The Unity script is called MyUnityScript in this example.

    public class MyUnityScript : MonoBehaviour
    {
    private MyClassForUnity myClassObject;
    }

  • In the Start function of the unity scripts, create an instance of our class. And call the simple fuction.

  • void Start()
    {
    // create an instance of our class
    myClassObject = new MyClassForUnity();

    // retrieve the version string from our object
    string txt = myClassObject.GetVersion();
    }

  • Build the script. We should not get any error message.

Step 5: Test the C# with the debugger in Unity

  • Put a break point (F9) on the line where we assign our string txt to the string we reveived from the GetVersion function.
  • Attach the debugger to the Unity editor from the MonoDevelop menu: Run -> Attach to process. Then select the Unity Editor.
  • Start the game that included the script by pressing Play in Unity 3D.
  • Switch back to the MonoDevelop editor and notice the yellow arrow on the line where you set the breakpoint. This means that the execution of the script by Unity 3D has arrived on the line with our breakpoint. Perform a single step (F10) to execute the function call to our object.
  • Examine the member variable txt. The contents should be our version string “MyClassForUnity version 0.1”.
  • We have succesfully called a function on a selfmade C# class, and retrieved information from it in our Unity 3D script!

Notes:
When copying a new version of your dll from visual studio folder to unity. Close the MonoDevelop editor.


Adding an XML element without namespace (xmlns) attribute

Issue:
When adding creating an element in an XmlDocment an unwanted namespace attribute may appears in your xml file.
You have to be carefull to add the new element in the correct namespace.
That does not always have to be the NamespaceURI of the document, but must be the NamespaceURI of the parent node.

Example:
This is an example of a SandCastle project file.
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
...
</Project>

I want to add a element called ItemGroup with a certain attribute inside.
My first try was to write this code:

XmlNode project = xmlDoc.GetElementsByTagName("Project")[0];
XmlNode newItemGroup = project.AppendChild(xmlDoc.CreateElement("ItemGroup", null));
newItemGroup.InnerXml = "<Folder Include="MyFolder"/>";

But this resulted in an undesired xml.file that could not be handled by the parser (in this case MsBuild or Sandcastle Help File Builder)

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<ItemGroup xmlns="">
<Folder Include="MyFolder" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" />
</ItemGroup>
</Project>

Note: The xmlns text that was added. This caused the issue.

Solution:

The solution is to create the new element in the same namespace as it’s parent node.
In other words, the element must be created with the namespace of the node.

This is the working code that uses the NamespaceURI property of the project node.:

XmlNode project = xmlDoc.GetElementsByTagName("Project")[0];
XmlNode newItemGroup = project.AppendChild(xmlDoc.CreateElement("ItemGroup", project.NamespaceURI));
newItemGroup.InnerXml = "";

This will results in this Xml file:

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<ItemGroup>
<Folder Include="MyFolder" />
</ItemGroup>
</Project>


Eclipse: The project cannot be built until the build path errors are resolved.

A strange problem occurs in Eclipse when I tried the ‘Hello World’ example from LibGDX.

After importing the project to their instruction, one problem remained in Eclipse:

The project cannot be built until the build path errors are resolved.

I have installed Eclipse with the Android ADT plugin.
The solution, or workaround, for this problem can be found here:

http://www.scottdstrader.com/blog/ether_archives/000921.html

The resolution was to force a resave of the selected projects (and their .classpath files):

  • Open the project properties
  • Select Java Build Path > Libraries
  • Add a new, arbitrary library (to be deleted later) > OK
  • Wait for the workspace to refresh (or force a refresh of the project)
  • The error(s) will go away
  • Remove the dummy library

The only other references I could find were to make minor alterations of contents of the .classpath file.


Network transfer of SQL database

With the tool ‘Import and Export data’  you can copy the contents of a SQL database to another PC in a user friendly way. Here are some tips to make sure your security settings are correct, and the database is the same on the destination system.

Installed on PC:

  • SQL Server 2008 Express R2

Network settings

  • Enable TCP/IP as protocol for both SQL servers: open the SQL server configuration manager, select SQL server network configuration: protocols for SQLExpress. And enable the setting ‘TCP/IP”.

Security

  • Enable remote access (on desitionation SQL server)

Database contents

The wizard for the import and export tool works pretty straighforward (if security settings are ok). However, there are some important transfer settings. You can find them under the button “Edit mapping”’.

  • Enable ‘enable identity insert’. If you do not check this option, the identity (autoincrement functionality for values) is lost, and e.g. your INSERT sql commando’s do not work anymore, because your identity column is not allowed to be NULL. When you expected the column to be autoincremental, this propably did not give a value for that in your INSERT statement.

Security enhancements in CRT string functions

How to replace non-secure string functions with their secure ( +  _s) counterparts?

Sscanf_s

Read formatted data from a string. Parse part of strings and store results into variables. Consider a string like this:

char* source = "William                182";

We want to parse the name and the number into two variables, i.e. the destination of the sscanf function.

char scanned_name[200];
int scanned_value = 0;

Earlier we could do it like this:

sscanf( source, "%s %d", scanned_name, &scanned_value);

With help of the secure function we have to do it like this:

sscanf_s( source, "%s %d", scanned_name, sizeof(scanned_name), &scanned_value);

We give the length of the destination buffer as an additional argument sizeof(scanned_name) to the function. This additional argument is placed immediately after the destination buffer and before any other argument that is going to be scanned. The known size prevents the function to have a buffer overflow and prevents exploitation of your a system running the software.

Getenv_s

This is an example from MFC (CString) and wchar’s:

CString sVideoMemory = _tgetenv_s(_T("ORSVideoMemory"));

Into

wchar_t ptr[80];
size_t len;
_tgetenv_s(&len, ptr, 80, _T("ORSVideoMemory"));
CString sVideoMemory(ptr);

Strcpy_s

Todo


Test and debug C++ code with NUnit

If you like NUnit, you can also use it to test your C++ sofwtare. You can create managed C++ unit tests that call native C++ software. Instead of Nunit you can also use the test framework of Visual Studio 2008.

Installed on PC

– Visual Studio 2008 Professional
– NUnit 2.5.7

Let’s assume you have written a C++ class library that you want to test. We call this software the SUT (software or system under test).

Create a unit test project

  1. Open the solution of the SUT
  2. Add a new project: E.g. “UnitTests”
  3. Choose type: Visual C++, CLR and ‘CLR Empty project’
  4. I made a managed C++ class library for this.
  5. Add reference to unit. Right click on ‘UnitTests’ projects and select references. Add a new reference to the Nunit dll. This can be something like: c:\Program Files\NUnit 2.5.7\bin\net-2.0\framework\nunit.framework.dll
  6. Create a new class in the project. This class will be the managed wrapper for test functions that call your native code.
    public ref class UnitTestForSUT
    {
    ...
    }
  7. Import the NUnit namespace into the code of the test project:
    using namespace NUnit::Framework;
  8. Include your C++ class
    // Softwareunder test
    #pragma unmanaged
    #include ".Sut.h"
    #pragma managed
  9. Create a function that will contain the test code.  Add the [TestMethod] attribute. Nunit will use this attribute to find the functions to execute.
    [Test]
    void UnitTest1()
    {
    }
  10. Implement a test with help of the Assert::… statement[Test]

    void UnitTest1()
    {
    SUT test = new SUT();
     

    test.SetInput(4);
    test.IncrementInput(); // some processing, e.g. to increment to input value
    int output = test.GetOutput( );

    Assert::AreEqual(5, output, “Incorrect output value.”);

    delete test;
    }

Running the test

There are many ways. You can download a visual studio plugin, or start Nunit from Windows’ start menu and select the DLL of the SUT .

Debugging the test

I have configured the debug build to be tested with the console program of NUnit. To see the output of any printf() statements. And I use the GUI of NUnit in release build. I want NUnit to run when I start the test project from visual studio.

  1. In the test project settings. In the debugging tab set the following parameters:For Debug:Command: C:\Program Files\NUnit 2.5.7\bin\net-2.0\nunit.exe
    Command arguments: /nothread  $(OutDir)\$(ProjectName).dll 

    For Release:

    Command: C:\Program Files\NUnit 2.5.7\bin\net-2.0\nunit.exe
    Command Arguments: $(OutDir)\$(ProjectName).dll

    We pass the name of our TestProject to NUnit. Not the name of our SUT library. You will have to check that the working directory of your test project is the same as the output directory of the SUT.

  2. Important! Make sure you can access native code. Set ‘Debugger Type’ to Mixed. Otherwise you can nicely debug your test code, but cannot ‘step into’ the software under test.
  3. Put a break point in your test code or in the SUT, and start the test project.

An alternative way to debug is to start NUnit from the Windows’ start menu, and attach the visual studio debugger to this process.


Creating a DotNetNuke (DNN 6) module with an .ascx control

How to create a module for DotNetNuke 6, based on your own C# Web User Control (.ascx file)

Without the use of the visual studio templated of the DotNetNuke starterkit.

Continue reading