UnityLink:
The Wolfram Language & 
The Unity Game Engine

Charles Pooh, Alec Shedelbower
Wolfram Research

Join the Conversation #WolframTechConf

Overview of the Talk

1. Wolfram Technologies & Unity

2. UnityLink Overview

3. Made with UnityLink

Wolfram Technologies & Unity

Over more than a quarter of a century, Wolfram has progressively built an unprecedented technology stack that has led to many transformative developments and that promises ever more in the years to come.

Unity Game Engine & Wolfram

Unity is a cross-platform game engine developed by Unity Technologies, which is primarily used to develop video games and simulations for computers, consoles and mobile devices.

UnityLink Overview

Unity Core Concepts

Unity Core Concepts

• The scene contains game objects.
• Each game object has one or more components attached to it.
• Some components reference assets such as audio clips and meshes.

Unity Editor

UnityLink: Get Started

Load the UnityLink package.

Needs["UnityLink`"]

Open the Unity project selection window.

UnityOpen[]

Find all of the game objects in the current scene.

FindUnityGameObject[All]

UnityLink: Principles & Concepts

Objects & Components:

Create

Create a new UnityObject and return a reference.

Create and save a scene.

CreateUnityScene["MySceneName"]

Create a game object from some geometry.

CreateUnityGameObject["Spikey",PolyhedronData["RhombicHexecontahedron"]]

Create a new game object with a light component.

CreateUnityLight["This Little Light of Mine"]

Create a UnityMesh.

unityMesh=CreateUnityMesh["Dodecahedron",PolyhedronData["Dodecahedron"]]

Save the UnityMesh to the Assets folder.

CreateUnityAsset[File["Assets/Dodecahedron.asset"],unityMesh]

Find

Get a reference to an existing Unity Object

Find the current scene.

FindUnityScene[]

Find a game object by name.

FindUnityGameObject["Directional Light"]

Find the components on a game object.

UnityGameObjectComponents["Directional Light"]

Find all the assets in the Assets folder.

FindUnityAsset[All]

Delete

Delete a UnityObject from a reference.

Delete a game object.

DeleteUnityGameObject["Spikey"]

Delete a component.

DeleteUnityLight["Directional Light"]

Delete an asset.

DeleteUnityAsset[File["Assets/Dodecahedron.asset"]]

Delete the current scene.

DeleteUnityScene[FindUnityScene[]]

UnityLink: Country Selector

Button[,NotebookOpen[FileNameJoin[{NotebookDirectory[],"WTC Demos","Assets","Notebooks","UnityLink_WTC_Examples.nb"}]],Appearance->"Frameless"]

Country Selector: Workflow

Country Selector: Calling WL From Unity

Country Selector: Find Country Entity

latitude=40;
longitude=-75;
geoPos=GeoPosition[{latitude,longitude}]

GeoGraphics[{Red,PointSize[0.03],Point[geoPos]},GeoRange->"World"]

country=First[GeoNearest[Entity["Country"],geoPos]]

Country Selector: Create Country Mesh

country=(Entity["United States", Entity["Country","UnitedStates"], "Entity[\"Country\", \"UnitedStates\"]", "country"]);

polygons=CountryData[country,{"SchematicPolygon","Equirectangular"}];
Graphics[{FaceForm[Red],EdgeForm[GrayLevel[0.2]],polygons}]

regions=Table[DiscretizeRegion[Polygon[points],MaxCellMeasure->Infinity],{points,polygons[[1]]}];
regions[[{1,2}]]

LatLonToCartesian[{lon_,lat_},R_:1.01]:=R*{Cos[lat*Degree]*Cos[lon*Degree],Cos[lat*Degree]*Sin[lon*Degree],Sin[lat*Degree]}

cartesian=Table[MeshRegion[LatLonToCartesian[#]&/@MeshCoordinates[region],MeshCells[region,2]],{region,regions}];
cartesian[[{1,2}]]

combinedMesh=RegionUnion@@cartesian

CreateUnityGameObject[CountryData[country,"Name"],combinedMesh]

DeleteUnityGameObject[CountryData[country,"Name"]]

Country Selector: Set Country Information

country=(Entity["United States", Entity["Country","UnitedStates"], "Entity[\"Country\", \"UnitedStates\"]", "country"]);

property="FullName";
textObject=UnityGameObjectComponents[property,"Text"]

value=CountryData[country,property]

SetProperty[textObject,"Text"-> value]

textObject

Country Selector: Full Code

(* Functions called from Unity *)
SetRandomCountry[]:=SetCountry[RandomChoice[CountryData[All]]]
SetCountry[latitude_,longitude_]:=SetCountry[First[GeoNearest[Entity["Country"],GeoPosition[{latitude,longitude}]]]]

(* Main function *)
SetCountry[country_]:=
Block[{geoPos,script},
CreateCountryMesh[country];
SetCountryInfo[country];
script=UnityGameObjectComponents["Globe","WolframGlobeController"];
SetProperty[script,"Country"-> CountryData[country,"Name"]];
]

(* Create the mesh to highlight the country *)
CreateCountryMesh[country_]:=
Block[{polygons,cartesian,radius=1.01,regions,combined},
polygons=CountryData[country,{"SchematicPolygon","Equirectangular"}];
regions=Table[DiscretizeRegion[Polygon[points],MaxCellMeasure->Infinity],{points,polygons[[1]]}];
cartesian=Table[MeshRegion[LatLonToCartesian[#,radius]&/@MeshCoordinates[region],MeshCells[region,2]],{region,regions}];
(*combined=CombineRegions[cartesian];*)
combined=RegionUnion@@cartesian;
CreateUnityGameObject[CountryData[country,"Name"],combined,VertexNormals-> "Smoothe",VertexTextureCoordinates-> None];
]

(* Get and set the various information about the country *)
SetCountryInfo[country_]:=
Block[{properties,textObjects,values,p,mag,unit},
properties={"FullName","Population","GDP","CurrencyName","Languages"};
textObjects=Table[UnityGameObjectComponents[property,"Text"],{property,properties}];
values=Table[
p=CountryData[country,prop];
p=Which[StringQ[p],p,
QuantityQ[p],
mag=ToString[AccountingForm[QuantityMagnitude[p],DigitBlock->3]];
unit=ToString[QuantityForm[QuantityUnit[p],"LongForm"]];
mag<>" "<>unit,
True,LanguageData[First[p],"Name"]
]
,{prop,properties}];
Do[SetProperty[textObjects[[i]],"Text"-> values[[i]]],{i,Length[properties]}]
]

(* Convert from latitude and longitude to 3D cartesian space *)
LatLonToCartesian[{lon_,lat_},R_:1.0]:=R*{Cos[lat*Degree]*Cos[lon*Degree],Cos[lat*Degree]*Sin[lon*Degree],Sin[lat*Degree]}

Digit Classifier: Demo

Button[,NotebookOpen[FileNameJoin[{NotebookDirectory[],"WTC Demos","Assets","Notebooks","UnityLink_WTC_Examples.nb"}]],Appearance->"Frameless"]

Digit Classifier: Workflow

Digit Classifier: Calling WL From Unity

Digit Classifier: Get Image Data From Script

script=UnityGameObjectComponents["Drawing Canvas","WolframDigitDrawer"]

script["Properties"]

Short[script["Pixels"],2]

img=Image[script["Pixels"],ImageSize->Small]

ImageRotate[img]

Digit Classifier: Classify Image

img=;

path=FileNameJoin[{ParentDirectory[NotebookDirectory[]],"Resources","DigitNet.wlnet"}]

net=Import[path]

digit=net[img]

Digit Classifier: Set and Color Digit Text

digit=2

digitText=UnityGameObjectComponents["Digit","Text"]

SetProperty[digitText,"Text"-> ToString[digit]]
SetProperty[digitText,"Color"-> RandomColor[Hue[_]]]

digitText

Digit Classifier: All Code

$NetPath=FileNameJoin[{ParentDirectory[NotebookDirectory[]],"Resources","DigitNet.wlnet"}];
$DigitNet=Import[$NetPath];

ClassifyDigit[]:=
Block[{script,guess,image,digitText},
script=UnityGameObjectComponents["Drawing Canvas","WolframDigitDrawer"];
image=ImageRotate[Image[script["Pixels"]]];
guess=$DigitNet[image];
digitText=UnityGameObjectComponents["Digit","Text"];
SetProperty[digitText,"Text"-> ToString[guess]];
SetProperty[digitText,"Color"-> RandomColor[Hue[_]]];
]

Made With UnityLink: Wolfram Story

The Wolfram Story is a VR demo where players can explore the history and capabilities of the Wolfram Technology stack.

img={,,,,};ImageCollage[Thread[{9.4,1,1,1}->Take[ img,1;;4]],ImagePadding->5]

More About UnityLink

UnityLink: Hands-on
          Thursday 1:00-2:00PM
          Badger

Geometry VR Exhibit
          9:00-5:00PM
          Exhibit Floor