Video Tutorials
Interface
Essentials
Advanced
How To
UnigineEditor
Interface Overview
Assets Workflow
Settings and Preferences
Working With Projects
Adjusting Node Parameters
Setting Up Materials
Setting Up Properties
Lighting
Landscape Tool
Sandworm
Using Editor Tools for Specific Tasks
Extending Editor Functionality
Built-in Node Types
Nodes
Objects
Effects
Decals
Light Sources
Geodetics
World Objects
Sound Objects
Pathfinding Objects
Players
Programming
Fundamentals
Setting Up Development Environment
Usage Examples
UnigineScript
C++
C#
UUSL (Unified UNIGINE Shader Language)
File Formats
Rebuilding the Engine Tools
GUI
Double Precision Coordinates
API
Containers
Common Functionality
Controls-Related Classes
Engine-Related Classes
Filesystem Functionality
GUI-Related Classes
Math Functionality
Node-Related Classes
Objects-Related Classes
Networking Functionality
Pathfinding-Related Classes
Physics-Related Classes
Plugins-Related Classes
IG Plugin
CIGIConnector Plugin
Rendering-Related Classes
Content Creation
Content Optimization
Materials
Art Samples
Tutorials

Migrating from .NET Framework to .NET 5

This section provides information on how to migrate your projects from .NET Framework to .NET 5.

Switching to .NET 5 is caused by its ability to meet the cross-platform needs and create high-performance and scalable systems.

Notice
For those who use Visual Studio, note that .NET 5 runs with Visual Studio 2019. With earlier IDE versions, migration is impossible.

Migration Guide#

The project file (.csproj) can be divided into 5 parts:

  1. General properties for any configuration (release/debug, float/double)
  2. Configuration-related properties
  3. Links to libraries, including the UNIGINE ones
  4. List of the project .cs files
  5. PostBuildEvent, which copied the compiled file to the bin folder and transformed into the file of the project_name_x64[d].exe type

In .NET 5, parts 2, 3, and 5 become united, and PostBuildEvent now runs the utility that generates the component properties.

Therefore, manual migration of the project file contains the following steps:

  1. Moving the .csproj file to the project root folder.
  2. Migrating common properties.
  3. Migrating configuration-related properties.
  4. Configuring links to libraries.
  5. Adding PostBuildEvent for the automatic property file generation for all components.

1. Moving .csproj File to Project Root Folder#

.NET 5 / .NET Core implies that the project file is located in the root folder. That simplifies the work with the project in such environments as Visual Studio Code.

Therefore, you also need to change paths to folders and files: ..\bin should be changed to bin, AppSystemLogic.cs to source\AppSystemLogic.cs, etc.

2. Migrating Common Properties#

Compared to .NET Framework, .NET 5 project files became much simpler, and some elements are singled out to individual files (such as the project run settings, for example).

  • Remove all arguments of the <Project> tag.

    Previously:

    Source code (XML)
    <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

    Now:

    Source code (XML)
    <Project>
  • Change WinExe to Exe to allow cross-platform running:

    Source code (XML)
    <OutputType>Exe</OutputType>
  • Delete the <TargetFrameworkVersion> and/or <TargetFrameworkProfile> tags, if any, and write the following instead:

    Source code (XML)
    <TargetFramework>net5.0</TargetFramework>
  • The tags <ProjectGuid> and <AppDesignerFolder> can be deleted.
  • Delete these lines:

    Source code (XML)
    <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
    <Platform Condition="'$(Platform)' == ''">x64</Platform>

    And use the following (if you have a float-based project, delete Debug-Double;Release-Double):

    Source code (XML)
    <Configurations>Debug;Release;Debug-Double;Release-Double</Configurations>
    <Platforms>x64</Platforms>
    <PlatformTarget>x64</PlatformTarget>
  • Add the following element to disable the automatic search of .cs files in the project. All necessary files are added by the Editor automatically or manually via the IDE. Disabling the automatic search significantly speeds up the build process:

    Source code (XML)
    <EnableDefaultItems>false</EnableDefaultItems>>

    This will make the process of building the application significantly faster compared to the automatic search of all .cs files in your project.

  • Migrate <Import>. Previously there was only one import element in the project file:

    Source code (XML)
    <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

    Now there are two elements of this type. One of them is added at the very top of the project file, and the other — at the very bottom:

    Source code (XML)
    <Import Sdk="Microsoft.NET.Sdk" Project="Sdk.props"/>
    
    
    <Import Sdk="Microsoft.NET.Sdk" Project="Sdk.targets"/>

3. Migrating Configuration-Related Properties#

  • Previously, there was only <PropertyGroup> for each configuration. Now there is also <ItemGroup> to indicate which engine library is used for the specified configuration. (Platform) is not used in the Condition anymore.

    Previously:

    Source code (XML)
    <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

    Now:

    Source code (XML)
    <PropertyGroup Condition="'$(Configuration)'=='Debug'">
  • Remove <AssemblyName> from the common properties section and add to each configuration with its specific postfix: _x64, _x64d, _double_x64, _double_x64d. For example:
    Source code (XML)
    <AssemblyName>main_csharp_x64d</AssemblyName>
  • In <DebugType>, change the type from "pdbonly" and "full" to "portable", to allow the debug version run on Linux. It also makes sense to move it to the common properties section:
    Source code (XML)
    <DebugType>portable</DebugType>
  • Delete the <PlatformTarget> element from the configuration-related properties, because we have already used it in the common properties.
  • The <StartArguments> element is not used in .csproj files anymore. In the project root folder, create the folder named Properties, and create the file named launchSettings.json inside it. Use the commandLineArgs element to pass the command line arguments to the built application.

    The launchSettings.json file has the following arrangement:

    Source code (XML)
    {
      "profiles": {
        "Project": {
          "commandName": "Project",
          "commandLineArgs": "-data_path ./data -console_command "world_load \"csharp_app\"",
        }
      }
    }
    If you use Visual Studio Code as an IDE: in the project root folder, create the folder named .vscode, and create the file named launch.json inside it. In this case arguments are passed using the args key.

    The launch.json file has the following arrangement:

    Source code (XML)
    {
       "version": "0.2.0",
       "configurations": [
            {
                "name": "Run Debug",
                "type": "coreclr",
                "request": "launch",
                "preLaunchTask": "build debug",
                "program": "${workspaceFolder}/bin/main_csharp_x64d.dll",
                "args": [ "-data_path", "./data" ],
                "cwd": "${workspaceFolder}",
                "console": "internalConsole",
                "stopAtEntry": false,
            }
        ]
    }
  • Add <ItemGroup> immediately below each configuration. The arrangement is as follows:
    Source code (XML)
    <ItemGroup Condition="'$(Configuration)'=='Debug'">
        <Reference Include="UnigineSharp_x64d">
            <SpecificVersion>false</SpecificVersion>
            <HintPath>bin\UnigineSharp_x64d.dll</HintPath>
        </Reference>
    </ItemGroup>
    Use the corresponding postfix for each configuration.

4. Configuring Links to Libraries#

  • System libraries: in .NET 5, you don't need to use links to system libraries anymore, therefore <Reference Include="System"/> can be deleted.
  • UNIGINE libraries: we have already added them during the previous step, therefore, they can be deleted.
  • External libraries: if any external libraries have been added, keep them as is.

5. Adding PostBuildEvent#

  • Add the <SkipPostBuild> item with the false value. This is a part of optimization. The Editor and Build Tool will change this value to true, if you need to build the project, but there haven't been any changes in the source code components.
    Source code (XML)
    <SkipPostBuild>false</SkipPostBuild>
    Add <SkipPostBuild> in the Common properties as well.
  • Add the <DOTNET_HOST_PATH> item for the cross-platform purposes. In this case the project is always built using the dotnet tool on any platform.
    Source code (XML)
    <DOTNET_HOST_PATH Condition="'$(DOTNET_HOST_PATH)' == ''">dotnet</DOTNET_HOST_PATH>
    Add <DOTNET_HOST_PATH> in the Common properties as well.
  • In the bottom of the .csproj file, above the import of Sdk.targets, replace the old <PostBuildEvent> item to the <Target> item of the following arrangement:
    Source code (XML)
    <Target Name="PostBuild" AfterTargets="PostBuildEvent">
        <Exec Command=""$(DOTNET_HOST_PATH)" "$(OutputPath)cspropgen_double_x64d.dll" -p "$(OutputPath)$(AssemblyName).dll" -data_path ../data/" Condition="'$(Configuration)'=='Debug-Double' And $(SkipPostBuild)=='false'"/>
        <Exec Command=""$(DOTNET_HOST_PATH)" "$(OutputPath)cspropgen_double_x64.dll" -p "$(OutputPath)$(AssemblyName).dll" -data_path ../data/" Condition="'$(Configuration)'=='Release-Double' And $(SkipPostBuild)=='false'"/>
    </Target>
    If your project has a float precision, remove all _double and -Double postfixes. This target will run the tool that generates property files for all components used in the project.

Project File Example#

Here is an example of the .NET Framework project file and the same project file ported to .NET 5:

Source code (XML)
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration>
    <Platform Condition="'$(Platform)' == ''">x64</Platform>
    <ProjectGuid>{2BFF5419-1600-4B67-D91D-4D9A45D3CDDD}</ProjectGuid>
    <OutputType>WinExe</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>UnigineApp</RootNamespace>
    <AssemblyName>csharp_app</AssemblyName>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <PlatformTarget>x64</PlatformTarget>
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>..\bin</OutputPath>
    <DefineConstants>TRACE;DEBUG;UNIGINE_DOUBLE;</DefineConstants>
    <WarningLevel>4</WarningLevel>
    <StartArguments>-data_path ../ -engine_config "../data/csharp_app/unigine.cfg" -console_command "world_load \"csharp_app\""</StartArguments>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <PlatformTarget>x64</PlatformTarget>
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>..\bin</OutputPath>
    <DefineConstants>TRACE;UNIGINE_DOUBLE;</DefineConstants>
    <WarningLevel>4</WarningLevel>
    <StartArguments>-data_path ../ -engine_config "../data/csharp_app/unigine.cfg" -console_command "world_load \"csharp_app\""</StartArguments>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System"/>
    <Reference Include="System.Core"/>
    <Reference Include="UnigineSharp">
      <SpecificVersion>false</SpecificVersion>
      <HintPath Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../bin/UnigineSharp_double_x64d.dll</HintPath>
      <HintPath Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../bin/UnigineSharp_double_x64.dll</HintPath>
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <Compile Include="AppEditorLogic.cs" />
    <Compile Include="AppSystemLogic.cs" />
    <Compile Include="AppWorldLogic.cs" />
    <Compile Include="main.cs" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <PropertyGroup>
    <PostBuildEvent>if $(ConfigurationName) == Debug (
copy "$(TargetPath)" "$(TargetDir)$(ProjectName)_$(PlatformName)d.exe"
) else (
copy "$(TargetPath)" "$(TargetDir)$(ProjectName)_$(PlatformName).exe"
)
    </PostBuildEvent>
  </PropertyGroup>
</Project>
Source code (XML)
<?xml version="1.0" encoding="utf-8"?>
<Project>
    <PropertyGroup>
        <BaseIntermediateOutputPath>junk\csharp_app\</BaseIntermediateOutputPath>
    </PropertyGroup>
    <Import Sdk="Microsoft.NET.Sdk" Project="Sdk.props"/>
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net5.0</TargetFramework>
        <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
        <GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
        <GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
        <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
        <GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute>
        <GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>
        <GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
        <RootNamespace>UnigineApp</RootNamespace>
        <StartupObject>UnigineApp.UnigineApp</StartupObject>
        <WarningLevel>4</WarningLevel>
        <IntermediateOutputPath>junk\csharp_app\$(Configuration)\</IntermediateOutputPath>
        <OutputPath>bin</OutputPath>
        <ApplicationIcon>source\common\Unigine.ico</ApplicationIcon>
        <EnableDefaultItems>false</EnableDefaultItems>
        <SkipPostBuild>false</SkipPostBuild>
        <Configurations>Debug;Release;Debug-Double;Release-Double</Configurations>
        <Platforms>x64</Platforms>
        <PlatformTarget>x64</PlatformTarget>
        <DebugType>portable</DebugType>
        <DOTNET_HOST_PATH Condition="'$(DOTNET_HOST_PATH)' == ''">dotnet</DOTNET_HOST_PATH>
    </PropertyGroup>
    <PropertyGroup Condition="'$(Configuration)'=='Debug'">
        <AssemblyName>csharp_app_x64d</AssemblyName>
        <DebugSymbols>true</DebugSymbols>
        <Optimize>false</Optimize>
        <DefineConstants>TRACE;DEBUG;</DefineConstants>
    </PropertyGroup>
    <ItemGroup Condition="'$(Configuration)'=='Debug'">
        <Reference Include="UnigineSharp_x64d">
            <SpecificVersion>false</SpecificVersion>
            <HintPath>bin\UnigineSharp_x64d.dll</HintPath>
        </Reference>
    </ItemGroup>
    <PropertyGroup Condition="'$(Configuration)'=='Release'">
        <AssemblyName>csharp_app_x64</AssemblyName>
        <Optimize>true</Optimize>
        <DefineConstants>TRACE;NDEBUG;</DefineConstants>
    </PropertyGroup>
    <ItemGroup Condition="'$(Configuration)'=='Release'">
        <Reference Include="UnigineSharp_x64">
            <SpecificVersion>false</SpecificVersion>
            <HintPath>bin\UnigineSharp_x64.dll</HintPath>
        </Reference>
    </ItemGroup>
    <ItemGroup/>
    <ItemGroup>
        <Compile Include="source/csharp/apps/main/**/*.cs"/>
    </ItemGroup>
    <Target Name="PostBuild" AfterTargets="PostBuildEvent">
        <Exec Command=""$(DOTNET_HOST_PATH)" "$(OutputPath)cspropgen_x64d.dll" -p "$(OutputPath)$(AssemblyName).dll" -data_path ../data/" Condition="'$(Configuration)'=='Debug' And $(SkipPostBuild)=='false'"/>
        <Exec Command=""$(DOTNET_HOST_PATH)" "$(OutputPath)cspropgen_x64.dll" -p "$(OutputPath)$(AssemblyName).dll" -data_path ../data/" Condition="'$(Configuration)'=='Release' And $(SkipPostBuild)=='false'"/>
    </Target>
    <Import Sdk="Microsoft.NET.Sdk" Project="Sdk.targets"/>
</Project>

See Also#

Last update: 2021-03-19