Coherent UI for Unity3D  2.5.3
A modern user interface library for games
 All Classes Namespaces Functions Variables Enumerations Enumerator Properties Events Pages
Samples
Note
Some samples show Desktop-specific features while others focus on Mobile targets

The samples provide a starting point for you. They are located in Assets/CoherentUI/Samples and the required scripts are already configured.

The samples are based on a simple scene we've set up for you. The scene consists of a light, a floor, a cube, and a FPS controller so you can move around. There are a few key points in the base sample you should be aware of.

  • The FPS controller's MouseLook script has been modified a bit - you can toggle if it's active using the Alt key. This was done for convenience so you can navigate over the page, projected on the cube easily, without looking around. The CharacterMotor script has also been modified for the same reason.
  • The cube's faces all have MeshCollider components. They are needed by Unity to produce texture coordinates in the raycast hit info. The texture coordinates, in turn, are needed to calculate the position of the hit point on the Coherent UI View.
  • The scenes that have interactive Coherent UI surfaces placed on objects use the Click-to-focus feature of the Coherent UI View. It allows the user to forward input to the view when she clicks on it and stop forwarding it when she clicks outside.
Note
In the case where the mesh collider does not coincide with the actual geometry of the object, the raycast and coordinate calculation must take place in the user code. In the samples we're only using simple geometry that is the same as the mesh collider so no further work is needed.

Hello, Coherent UI

Just hit play - and you'll see a rotating cube and a sign, saying "Hello, Coherent UI". The sample demonstrates the easiest possible setup for Coherent UI for Unity3D. The scene is made of a cube in front of the camera with a script that rotates it, and a Coherent UI component attached to the main camera. The component's URL is set to a local resource using our special coui:// protocol and the "Transparent" checkbox is ticked. You can preview the page displayed in your browser to see what you can expect.

Note
The coui protocol uses the folder selected by the Edit → Project Settings → Coherent UI → Select UI folder menu item as a root for a virtual file system.

You can also add a CoherentUIView component to a 3D object if you like. To do so, locate the CoherentUIView script under Standard Assets/Scripts/Coherent UI/CoherentUIView in the Project window and then add it to the object of your choice. In Unity3D 4.x you can do that from the inspector windows by clicking "Add component".

Here's a sample where a Coherent UI View component is added to a cube. Make sure you tick the "Click to focus" checkbox for the view to get input forwarding easily.

sample_hello.png
CoherentUIView on a texture

You can also try pages that show dialog boxes, such as

If you do not handle the Listener events for dialog boxes by yourself they will be handled automatically by Coherent UI.

sample_hello_prompt.png
CoherentUIView showing a prompt

Facebook integration

This sample uses a facebook application that shows some of your photos in a rotating circle. You'll see how to customize the View and ViewListener behaviour to suit your needs.

Note
If you're having trouble displaying the local resources, make sure you have selected the UIResources folder located in the root of the project using the Edit → Project Settings → Coherent UI → Select UI folder menu in the editor. This folder will be used for resources addressed with coui:// links.
sample_facebook.png
CoherentUIView Facebook integration sample

You will find a new script - FacebookSampleScript. We need to modify the default behaviour of UnityViewListener for this sample. The key points are:

  • In its Start method the FacebookSampleScript obtains the CoherentUIView component in the game object.
  • In the Start method the script also attaches to the CoherentUIView.OnViewCreated event to enable intercepting URL requests and to the UnityViewListener.URLRequest event to redirect the Facebook login URL to the local HTML page.

This is the easiest way to handle events provided by the UnityViewListener. Another option is to derive the UnityViewListener and CoherentUIView but that is unnecessary.

The FacebookSampleScript.OnURLRequestHandler checks if the requested URL is the one that was registered in the Facebook Application settings (this might be any made up URL). If that's the case, we redirect it to the local page that uses our Facebook application. You will find the page we're redirecting to in the sample project folder under FacebookSample/facebook.html.

Now that we've explained what the class does, the only thing left is to hit play. You can press Alt to stop moving/looking so you can browse in the Facebook application.

Menu And HUD

This sample shows a game menu and HUD built with Coherent UI.

Note
If you're having trouble displaying the local resources, make sure you have selected the UIResources folder located in the root of the project using the Edit → Project Settings → Coherent UI → Select UI folder menu in the editor. This folder will be used for resources addressed with coui:// links.

Double-click the Menu scene in the Project window (located in Scenes) to make it active, if it isn't already. In the Menu scene we have a MenuScript component attached to the camera. MenuScript does three things:

  • sends the mouse position to the view every Update()
  • registers the handlers for clicking on a menu button
  • loads the game when the "New Game" button is clicked
Note
You have to add the game scene to the build settings of your project so Unity3D can load it.

In the game, we have another component for controlling the view - HUD, this time implemented in UnityScript. Each frame the component updates the compass orientation, based on its transformation.

In addition to updating the compass, the HUD component takes care of disabling the CharacterMotor component when the focus is on a Click-to-focus view. The HUD script attaches to CoherentUISystem::OnViewFocused event and changes the canControl property of the selected CharacterMotor whenever a Click-to-focus view gains or loses focus. This allows typing in the focused view without moving the character. Here is the HUD component in code:

#pragma strict
#if UNITY_STANDALONE || UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_EDITOR
import Coherent.UI.Binding; // to use View.TriggerEvent with extra arguments
private var View : Coherent.UI.View;
private var CurrentDirection : float;
// CharacterMotor component to be disabled when a Click-To-Focus view has gained focus
public var characterMotor : CharacterMotor;
function Start () {
var viewComponent = GetComponent(typeof(CoherentUIView)) as CoherentUIView;
viewComponent.OnViewCreated += this.ViewCreated;
viewComponent.OnViewDestroyed += this.ViewDestroyed;
CurrentDirection = 0;
var uiSystem = Component.FindObjectOfType(typeof(CoherentUISystem)) as CoherentUISystem;
// get notified when a Click-to-focus view gains or loses focus
uiSystem.OnViewFocused += this.ViewFocused;
}
function ViewCreated(view : Coherent.UI.View) {
View = view;
var viewComponent = GetComponent(typeof(CoherentUIView)) as CoherentUIView;
Debug.LogWarning(String.Format("View {0} created", viewComponent.Page));
}
function ViewDestroyed() {
View = null;
}
function ViewFocused(focused : boolean) {
if (characterMotor) {
// enable or disable the character movements
characterMotor.canControl = !focused;
}
}
function Update () {
if (View != null)
{
var direction = this.transform.rotation.eulerAngles.y;
if (Mathf.Abs(direction - CurrentDirection) > 2)
{
View.TriggerEvent("SetAbsoluteCompassRotation", direction);
CurrentDirection = direction;
}
}
}
#endif

In the game scene we have one more component - ObjectPicker, that takes care of directing the input to the correct CoherentUIView. First it checks whether the mouse is on a HUD element and if it is not, then raycasts and checks whether the mouse is over the browser window. Make sure the "Support Click Through" checkbox is ticked on the HUD CoherentUIView - this allows you to detect whether the mouse is over a transparent area in the View. If the property is left unchecked the input will never reach any objects in the world, because the system will think that the mouse is always over the HUD.

sample_hud.png
CoherentUIView HUD sample in action

Binding Demo

This sample will demonstrate communication between Unity3D and JavaScript used by the HTML page loaded in a Coherent UI View.

Note
If you're having trouble displaying the local resources, make sure you have selected the UIResources folder located in the root of the project using the Edit → Project Settings → Coherent UI → Select UI folder menu in the editor. This folder will be used for resources addressed with coui:// links.

The sample shows a simple options dialog. The options are passed from JavaScript to Unity3D and back to exercise the binding. This walkthrough will give you a brief overview of the Coherent UI Binding fundamentals but be sure to check out the Binding section in this guide, as well as the Binding for .NET section in the general reference document.

Note
This sample guide is written for C# Unity3D scripts, for UnityScript binding, please check the UnityScript section See the Unity Script Page

First, when passing custom object types between Unity3D and JavaScript, you must first inform Coherent UI about the data in the type. You can do that using the CoherentType attribute:

using Coherent.UI.Binding;
// all properties / fields for Options will be visible to Coherent UI
[CoherentType(PropertyBindingFlags.All)]
public struct GameOptions
{
public string Backend;
public uint Width;
public uint Height;
public string Username
{
get {
return System.Security.Principal.WindowsIdentity.GetCurrent().Name.ToString();
}
}
// rename the NetPort property to NetworkPort
[CoherentProperty("NetworkPort")]
public uint NetPort { get; set; }
}

Now the GameOptions structure will correspond to a JavaScript object having the same properties. Note that you can rename a property using the CoherentProperty attribute. In this case, the "NetPort" property will correspond to "NetworkPork" in JavaScript.

After exposing the properties, we need to register some event handlers. This can be done in two ways. The first way to bind event handlers is to add a handler for the ReadyForBindings event of the UnityViewListener (manual binding). The second way (.NET only) is to add a CoherentMethod attribute to the method you want to bind (automatic binding). See the CoherentMethod section in this guide for more details.

Note
The sample provides two scripts for binding - ManualBinding.cs and AutomaticBinding.cs. Make sure that only one of those scripts is active when exploring the sample.

We'll explore the manual binding first. Start by registering a handler for ReadyForBindings:

m_View = GetComponent<CoherentUIView>();
m_View.Listener.ReadyForBindings += HandleReadyForBindings;

The handler would look like this:

void HandleReadyForBindings (int frameId, string path, bool isMainFrame)
{
if (isMainFrame)
{
// bind ApplyOptions to "ApplyOptions" in JavaScript
m_View.View.BindCall("ApplyOptions", (Action<GameOptions>)this.ApplyOptions);
m_View.View.BindCall("GetLatency", (Func<int>)this.GetNetworkLatency);
m_View.View.BindCall("GetGameTime", (Func<int>)this.GetGameTime);
m_View.View.BindCall("GetMath", (Func<BoundObject>)(() => {
return BoundObject.BindMethods(new MyMath());
}));
// triggered by the view when it has loaded
m_View.View.RegisterForEvent("ViewReady", (Action)this.ViewReady);
}
}

Now, when JavaScript calls engine.call("ApplyOptions", options), Unity3D will execute its handler - namely the (Action<GameOptions>)this.ApplyOptions method registered above.

The options structure passed as a parameter looks like this:

function onApplyButton(){
var options = {};
options.__Type = "GameOptions";
options.Backend = $("#backend").text();
options.Width = Number($("#gameWidth").val());
options.Height = Number($("#gameHeight").val());
options.Username = $("#user").text();
options.NetworkPort = Number($("#netPort").val());
// This will call the C++ engine code with the just created structure. It'll be correctly populated
engine.call("ApplyOptions", options);
}

Note that there is one "internal" property - __Type. This property defines the mapped type and is essential for correct behavior of the binding provided by Coherent UI.

The "ApplyOptions" handler just bounces the options back to JavaScript:

public void ApplyOptions(GameOptions options)
{
m_View.View.TriggerEvent("gameConsole:Trace", options);
}

gameConsole:Trace will dump the options object in the console.

sample_binding.png
Binding sample in action

The automatic binding saves us the first two steps - instead of registering a handler in the UnityViewListener callback you can decorate a method with the CoherentMethod attribute:

[Coherent.UI.CoherentMethod("ApplyOptions", false)]
public void ApplyOptions(GameOptions options)
{
m_View.View.TriggerEvent("gameConsole:Trace", options);
}

The first argument of the attribute is the JavaScript function that we're binding. The second defines whether the function is an event (opposed to a call - calls are single-cast only).

Returning a value to JavaScript

Calls can also return a value. Let's inspect the "GetLatency" binding:

// By default, the second argument of CoherentMethod is false
[Coherent.UI.CoherentMethod("GetLatency")]
public int GetNetworkLatency()
{
// not actual latency :)
return (int)UnityEngine.Random.Range(0, 1000);
}

Since the execution of JavaScript is not synchronous you will receive the result in a callback. Coherent UI provides a promise/future pattern for convenience. This is the "GetLatency" JavaScript call in all its glory:

function getLatency() {
engine.call("GetLatency").then(function() {
$("#latency").text(arguments[0]);
});
}

As you can see from the script, the value returned by Unity3D will be passed to the callback as an argument.

Method Binding

This sample also shows how to use binding of .Net methods. For detailed explanation see "Exposing Methods" in the "Binding for .Net" chapter in the API documentation.

The sample exposes an instance of MyMath to JavaScript.

class MyMath
{
public double Sum(double[] numbers)
{
return numbers.Sum();
}
public double Average(double[] numbers)
{
return numbers.Average();
}
}

When the game is up and running, we request the MyMath instance, store it as a global object and register two console commands that use it.

engine.on('Ready', function () {
//get the exposed MyMath object
engine.call('GetMath').then(function (math) {
// store reference to the object
window.MyMath = math;
// register commands for the console
engine.trigger('gameConsole:AddCommand', 'sum', 'computes the sum of its arguments', function (line) {
var numbers = line.split(/\s+/).map(Number);
numbers.splice(0, 1);
window.MyMath.Sum(numbers).then(function (sum) {
engine.trigger('gameConsole:Trace', 'The sum of', numbers, 'is', sum);
});
});
engine.trigger('gameConsole:AddCommand', 'avg', 'computes the average of its arguments', function (line) {
var numbers = line.split(/\s+/).map(Number);
numbers.splice(0, 1);
window.MyMath.Average(numbers).then(function (avg) {
engine.trigger('gameConsole:Trace', 'The average of', numbers, 'is', avg);
});
});
});
});

To try out the commands press ~ to open the game console and type sum 40 2.

Events

When you need multiple handlers for a JavaScript function you need to register an event. This can be done by the Coherent.UI.View.RegisterForEvent method for manual binding

m_View.View.RegisterForEvent("ViewReady", (Action)this.ViewReady);

and passing true as a second parameter of the CoherentMethod attribute for automatic binding.

[Coherent.UI.CoherentMethod("ViewReady", true)]
public void ViewReady()
{
// show the options
m_View.View.TriggerEvent("OpenOptions", m_GameOptions);
}

Bear in mind that events cannot return a value.

If you want to handle an event in JavaScript, you need to register a handler using the engine.on call.

engine.on('OpenOptions', function (options) {
// Open an options dialog
});

An event can be triggered by JavaScript by using

engine.trigger("EventName", eventArgs);

or by Unity3D using

m_View.View.TriggerEvent("EventName", eventArgs);

where m_View is CoherentUIView.

This concludes the binding demo walkthrough.

Archive resource

This sample demonstrates reading resources from an archive through a custom file handler.

The scene is just a simple camera that has an attached CoherentUIView component and another one that forwards input to the view. The important component for this sample is CustomFileHandlerScript. It sets the CoherentUISystem factory function object in its Awake method so the system is initialized with the custom handler.

void Awake()
{
CoherentUISystem.FileHandlerFactoryFunc = () => { return new CustomFileHandler("UIResources", "ArchiveResource.tar"); };
}

In fact, that's all the component has to do - set the CoherentUISystem.FileHandlerFactoryFunc prior to any Start method being called. The returned CustomFileHandler is the class that does the actual reading/writing. The methods the user needs to implement are:

public override void ReadFile (string url, Coherent.UI.URLRequestBase request,
Coherent.UI.ResourceResponse response)
{
...
}
public override void WriteFile (string url, Coherent.UI.ResourceData resource)
{
...
}

They will be called for all coui:// links and for the cookies (if enabled).

Note
When reading/writing cookies, you may receive a URL that has a file:// scheme.

The input URL can be interpreted in any way you see fit for your handler. In the example we try to open the link coui://UIResources/mainmenu/menu.html. The mainmenu/menu.html is actually compressed in an archive. First we verify that the host part of the URL (UIResources) is what we expect for compressed resources and then proceed to search the archive for the resource.

Since Coherent UI supports asynchronous reading/writing of resources, when done with the I/O operations, you must use the ResourceResponse or ResourceData object to signal the outcome. You can do that by using the SignalSuccess and SignalFailure methods.

Note
At the moment the data you read/write must be converted to a native buffer before usage. This is done with the System.Runtime.InteropServices.Marshal class. Here's a short snippet that reads a file and then copies the managed buffer in an unmanaged buffer provided by the ResourceResponse object:
public override void ReadFile (string url, Coherent.UI.URLRequestBase request,
Coherent.UI.ResourceResponse response)
{
byte[] bytes = File.ReadAllBytes(url);
IntPtr buffer = response.GetBuffer((uint)bytes.Length);
if (buffer == IntPtr.Zero)
{
response.SignalFailure();
return;
}
Marshal.Copy(bytes, 0, buffer, bytes.Length);
response.SignalSuccess();
}

Make sure you check out the code in CustomFileHandlerScript for a complete example.

Mobile Input

Warning
Unity3D 3.5 doesn't support native plugins for iOS simulator builds. There are a couple of articles explaining how to workaround this limitation, but the most helpful is http://tech.enekochan.com/2012/05/28/using-the-xcode-simulator-with-a-unity-3-native-ios-plug-in/ We have added a script with a post-process step that tries to fix the project, so it can be used with the iOS simulator. The script is in Editor/iOSSimulatorProjectFixer.cs.

This sample demonstrates how you can control what part of the input is forwarded to Unity3D by using JavaScript. The sample starts with an overlay that has 3 buttons on the left side, area for testing input forwarding on the right, and a red box in the world. The buttons enable/disable the input forwarding for touches on the right side of the overlay and the third one bumps the box upwards. When you touch the box a little force is applied and it should move forward as if you pushed it. If you touch the box in the right area of the overlay the force is applied only if input forwarding is enabled.

There are also buttons for toggling the overlay and mouse look controller in the top left corner for convenience.

Warning
The HTML code for the sample is not designed for small displays so it may look out of proportion on a phone or a phone simulator. You can try lowering the font size in the accompanying css file.
Note
The Coherent UI View used has its input state set to "Transparent". If you set it to "Take all" input is consumed before reaching Unity3D and if you set it to "Take none" it is sent directly to Unity3D.
Warning
Unfortunately, at the moment you can't see the actual behavior of the sample in the Unity3D Editor. Input is handled differently for the standalone and mobile versions so it recommended that you test your project either on a mobile device or an emulator.

Code-wise speaking, when you make a touch on a "Transparent" Coherent UI View, the engine.checkClickThrough function is called. You can check its code in coherent.js. Basically it obtains the DOM element from the touch coordinates and begins a series of checks. First, if the element is the document body or has the coui-noinput class, input is directly sent to the client (Unity3D). Otherwise, the element is checked for having a coui-inputcallback class. If it does, the element's couiInputCallback is invoked which determines whether the input is forwarded or consumed; if it doesn't have such class, input is consumed.

The sample enables/disables the input forwarding on the right area by removing/adding the coui-noinput class to the corresponding DOM element. In this sample, only the DOM element for the right area has the class coui-inputcallback and its couiInputCallback function is set when the engine has signaled it's ready. The function itself doesn't do anything special, it just always returns true, meaning that the input is consumed in JavaScript and never sent to the client (Unity3D).

You can also bump the box upwards which is a demonstration for the binding for Coherent UI Mobile. It's very much the same as binding for .NET/Unity3D standalone so we'll not go in detail here.

Summing up:

  • if you want the input forwarded to the client when touching an element, simply add the coui-noinput class to the element.
  • if you want an element to consume input, ensure that it does not have the coui-noinput.
  • if you want to have custom processing over an element, ensure that it does not have the coui- noinput, add a coui-inputcallback, and add a function couiInputCallback which ultimately returns true if you want to consume the input or false if you want to forward it to the client.

Note that for obtaining the element below the touch point we're currently using document.elementFromPoint. In the sample, the right area is represented by a <div> and there's some text inside it as a child element. Only the <div> has the coui-inputcallback class. If you touch the text its element will be checked for the coui-inputcallback class and since it doesn't have one input will be consumed. Since we want to apply the logic for all touches inside the area this presents a problem. One solution is to add the coui-inputcallback class to all child elements and set their couiInputCallback functions to the same variable. Another solution is to use the pointer-events CSS property on the children elements, e.g.:

#menu-right > *
{
pointer-events: none;
}

This is how the sample solves the problem. Note that this is an experimental CSS property and prevents elements from being the target of pointer events. This is fine in the sample but may have adverse effects in your code so use it with caution.

Oculus

Note
It is not possible to create a sample scene for Oculus Rift for Unity3D 3.5 using the official Oculus SDK. So our Oculus Rift sample scene is created with Unity3D 4 and can not be packaged in our asset store packages. You can download a package with the scene from: https://s3.amazonaws.com/CoherentLabs/Public/Coherent_UI_Oculus_Sample.unitypackage

This sample demonstrates how you can create UI elements in your games for the Oculus Rift, using the CoherentUI and OculusVR integrations in Unity. The focus of the sample is on creating a HUD element that can be used with the Oculus headset.

Note
You should include the Oculus integration package for Unity in order to use Oculus in Unity3D (you need a Unity Pro 4.01 or higher version). For more information about the Oculus SDK and its integration with Unity, please visit http://www.oculusvr.com/ .

You can get Oculus ready for use in Unity by following these steps:

  • go to the official website of Oculus Rift - http://www.oculusvr.com/ ;
  • download OculusUnityIntegration.unitypackage from there;
  • open an Unity3D instance and go to Assets -> Import Package -> Custom Package. When the dialog box for choosing packages opens, go to the place with the downloaded package and select it. A new dialog box with a list of the files for import will open. Choose 'Import All'. After completing this step you should be able to see a new menu - 'Oculus'.

Now we are ready to proceed with the sample. As you can see, there is an OVRPlayerController in the Scene menu (it can be added from Oculus -> Prefabs -> OVRPlayerController). The controller is comprised of two things: a simple character controller and another OVR prefab - OVRCameraController. The latter is used as an interface between Unity and the two cameras. Double-click it to reveal its children objects. Double-clicking the OVRCameraController will show the cameras and a plane object attached to the right camera. This plane is used as a surface for drawing the HUD. There is an CoherentUIView component attached to it, which uses coui://UIResources/MenuAndHUD/hud/hud.html as a page. It is suggested that for drawing HUD elements you attach the surface to the right camera for optimal results.

Note
To render a view on top of everything, we put an check mark in 'IsIndependentOfZBuffer'.
Warning
Whenever using a plane as a surface for views, choose a material for the plane and use a 'Transparent/Diffuse' shader for it.
Note
If you want to change the draw order of a Coherent UI view, the Left eye camera and a Right eye camera, you can adjust the camera depth property of the camera component for all of the cameras you want to reorder. Cameras with larger depth value will be drawn on top of cameras with lower depth value. When rendering surface views, Coherent UI creates a CoherentRenderingCamera (in the ViewListener.cs script) that has a default depth of 0.

This is basically all you need to draw the HUD. Hit play to see the result

Mobile Surface

The Mobile Surfaces sample shows how to use Coherent UI views on surfaces for mobile platforms. The sample shows a texture with a Coherent UI view on it that is rotating. Every 100 frames the view is changed and the texture is updated by calling the 'UpdateView' method of the view.

Note
To achive transparency of the surface both - the IsTransparent property of the view should be checked and the shader of the material should be set to Transparent/Diffuse.

Live Game Views

Note
Live Game Views are a Desktop-only feature.

The sample shows a simple scene with a Live Game View. The scene consists of a "game world" with a plane as ground, four rotating colored cubes and a light.

On the main Camera a Coherent UI View is attached that serves as an in-game HUD(heads-up-display). The Live Game View is part of the HUD. A Coherent UI Live Game View component is also attached to this camera and hence to the UI - it is the "link" between the View and the provider of the 3D images.

A second camera is fixed on the cubes and provides the source data. Everything this camera renders is automaticcally sent to the UI View linked to it as a dynamic "ImageData" object in the UI JavaScript Code. The HUD.html page draw the Live View with the following code:

window.onload = function() {
var c = document.getElementById("myCanvas");
c.onEngineImageDataUpdated = function (name, image) {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.clearRect(0, 0, c.width, c.height);
ctx.putImageData(image, 0, 0);
ctx.fillStyle = "white";
ctx.font = "16pt Arial";
ctx.fillText("Live Game View!", 15, 25);
}
}

Every time a new frame is drawn by the "live" camera the "onEngineImageDataUpdated" is called on all "canvas" elements that define it in the page. There you can use the data in whatever fashion you need. In this sample we draw the image into the canvas and write some text on it. When you "Play" the game you'll see the four rotating cubes drawn in the HUD in the lower left corner as the "live" camera sees them.

Note that now the images of the camera are part of the UI DOM, so you can achieve all UI effects with it. The canvas elements can be animated, 3D transformed int the UI, post-effects can be applied on them, they can be interactive etc.

Via Live Game Views in a real game you can trivially have 3D animated unit portraits, animated items in the UI, 3D mini-maps, security cameras etc.

IME Sample

This sample demonstrates the usage of Input Method Editor for languages that require more complex input such as Chinese. To have IME enabled for a particular view you should just put a check on the Enable IME property of the CoherentUIView and this is all you need to do to have support for IME in your view.

Open the IME Sample, change your input language to one that requires IME, for example Chinese and hit play. Try to write something in the dialog that appears and hit 'Enter' or just press the 'Say' button. What you just wrote will appear in the dialog window.

Enabling IME does a few things:

  • It subscribes for the OnCaretRectChanged, IMEShouldCancelComposition and OnTextInputControlTypeChanged events.
  • OnTextInputControlTypeChanged event is fired when the type of text input control changes. The method that subscribes for it determines from the new type of control whether IME composition mode in Unity should be turned off or on.
  • OnCaretRectChanged event is fired when the caret has changed its position. It has arguments x and y for the top left position of the caret rectangle and width and height for its width and height, all of them measured in pixels, relatively to the view. This method will help you set the position of the candidate list window.
Note
If you want to set the candidate window on a specific screen position or make the calculations on your own, you can subscribe with a method for the CalculateIMECandidateListPosition handler, which has the same arguments as OnCaretRectChanged and should return the desired position of the candidate window in screen space. Please note that (0, 0) for the IME cursor position in Unity is in the upper left corner in spite of bottom left.