Coherent UI for Unity3D  2.5.3
A modern user interface library for games
 All Classes Namespaces Functions Variables Enumerations Enumerator Properties Events Pages
Important points

Binding

Binding C#, UnityScript and Boo handlers to JavaScript callbacks is the same as binding for the .Net platform. You have to register handlers when the UnityViewListener's ReadyForBindings event is fired. You can do that by using either Coherent.UI.View.BindCall (for single-cast delegates) and Coherent.UI.View.RegisterForEvent (when you have multiple subscribers for the event). For more details see the general reference documentation, chapter Binding for .Net.

private void RegisterBindings(int frame, string url, bool isMain)
{
if (isMain)
{
var view = ViewComponent.View;
if (view != null)
{
// When engine.call('NewGame') is executed in JavaScript,
// the this.NewGame method will be called as well
view.BindCall("NewGame", (System.Action)this.NewGame);
}
}
}

The Coherent.UI.View can be obtained using the View property of the CoherentUIView component.

To take advantage of the Unity3D component and message system each CoherentUIView has the InterceptAllEvents property. If intercepting of all events is enabled, any event triggered in JavaScript on the engine object is forwarded to the game object containing the view. This is done by using SendMessage with Coherent.UI.Binding.Value[] containing all the event arguments.

engine.trigger('Event', 42);
// will execute SendMessage('Event', [42])
Note
Using this method of handling triggered events has some additional overhead over the direct .Net Coherent.UI.View.RegisterForEvent method.

CoherentMethod attribute for .NET scripts

Instead of handling the ReadyForBindings event and doing BindCall or RegisterForEvent by yourself, you can use the CoherentMethod attribute to decorate methods in components.

Warning
This attribute only works if the CoherentUIView's Enable Binding Attribute is set to true. By default it is false.

The decorated methods will be automatically bound to the View owned by the CoherentUIView component in the Game Object. If the Game Object has no CoherentUIView component, the attribute has no effect. The CoherentMethod attribute has a string property for the JavaScript event name, and an optional boolean parameter that specifies whether the method is a call or event handler (calls can have only a single handler, while events may have many). Here's an example component using the attribute:

public class BindingComponent : MonoBehaviour {
[Coherent.UI.CoherentMethod("NewGame")]
void MyCallHandler()
{
Debug.Log("MyCallHandler called in response to engine.call('NewGame')");
}
[Coherent.UI.CoherentMethod("EnemySpotted", true)]
void MyEventHandler()
{
Debug.Log("MyEventHandler called in response to engine.trigger('EnemySpotted')");
}
}

See the Binding Sample for a complete example.

Warning
* Binding methods using the CoherentMethod attribute is easier than doing it manually in ReadyForBindings, but presents possible performance penalties during game startup. When the CoherentUIView component is created, it searches all the other components in the host Game Object for methods marked with CoherentMethod using reflection. This can be a costly operation and to prevent undesirable slowdowns during startup the Enable Binding Attribute property for each CoherentUIView is set to false by default.
* The CoherentMethod attribute currently does NOT support dynamically added components. Methods decorated with the attribute are only bound when the CoherentUIView component is created, which is usually when the Game Object it is part of is created.

JavaScript and Unity3D

Consult the Binding for .NET chapter in the general reference document. Check the Binding Sample and its walkthrough in this guide for an example.

Briefly, Unity3D can call JavaScript using events; JavaScript can call Unity3D using events or calls.

  • Events

Events can be called by JavaScript

engine.trigger("MyEvent", args);

or Unity3D

coherentUIView.View.TriggerEvent("MyEvent", args);

The "MyEvent" will be handled by any registered method in JavaScript

engine.on("MyEvent", function() {...});

or Unity3D

coherentUIView.View.RegisterForEvent("MyEvent", handlerMethod);
  • Calls

Calls, unlike events, can have only one handler. The can also return values. To execute a call from JavaScript use

engine.call("MyCall", args);

It will be handled by a method registered using

coherentUIView.View.BindCall("MyCall", handlerMethod);

Namespaces

Coherent UI classes are placed in the Coherent.UI namespace for Desktop and Coherent.UI.Mobile for the Mobile version. You can check the Coherent UI files - for instance CoherentUIView and take a look at the beginning of the file at how the namespaces are imported depending on the Unity platform targeted. Exceptions to that rule are classes that cannot be in a namespace because Unity doesn't allow it, such as components that derive from MonoBehaviour.

Subclassing CoherentUIView and UnityViewListener

The default CoherentUIView component and the UnityViewListener provide the most common functionality and are usually enough for normal usage of Coherent UI. If you need custom behavior, you need to subclass them.

The class you derive from UnityViewListener would usually subscribe to various events that aren't handled by default. It is recommended not to override the OnViewCreated callbacks since the UnityViewListener class contains important logic that you would have to implement yourself otherwise.

The class you derive from CoherentUIView would only need to create an instance of your custom View Listener. This can be done by copying the Update method of CoherentUIView and editing it appropriately.

Note that when subclassing CoherentUIView you will no longer be able to view or edit the properties in the Inspector. That's because we're using C# properties in our component instead of fields and they are not automatically shown. To show the properties of a given C# script we need to make a new Editor script (inside the Editor folder of your Assets) that shows the properties for a specific type. We've already done that for CoherentUIView, but you'll have to do it yourself for derived classes. The script contents should be the following:

using UnityEngine;
using System.Collections;
using UnityEditor;
[CustomEditor(typeof(<YourType>))]
public class <YourType>ViewEditor : Editor {
private <YourType> m_Target;
private CoherentPropertyField[] m_Fields;
public void OnEnable() {
m_Target = target as <YourType>;
m_Fields = CoherentExposeProperties.GetProperties(m_Target);
}
public override void OnInspectorGUI() {
if(m_Target == null)
return;
this.DrawDefaultInspector();
CoherentExposeProperties.Expose(m_Fields);
}
}

Just replace <YourType> with the actual name of your class.

Note
In most cases, subclassing is unnecessary. See Facebook Sample for an example how to subscribe for UnityViewListener events.

Coherent UI system lifetime

Since initialization of the CoherentUISystem component is a costly operation, it is designed to be done once in the first scene of your game. The component itself has the same lifetime as the application. Since Unity tears down the state of the game when you load a new scene, the component is marked not be destroyed using the DontDestroyOnLoad() function. This makes it persist through scenes and is available using the Object.FindObjectOfType function. Getting the system can be done with the following line of code:

var uiSystem = Object.FindObjectOfType(typeof(CoherentUISystem)) as CoherentUISystem;

Customizing initialization of the Coherent UI System

When using only CoherentUIView components, the Coherent UI System will be automatically initialized using the default parameters. These parameters define global system settings such as whether cookies are enabled, local storage and cache paths, debugger port and others. Check the CoherentUISystem component for a full list.

The Coherent UI System can be initialized with parameters other than the defaults in the following ways. Either drag the CoherentUISystem component to any object and edit the properties in the Inspector window, or edit the CoherentUISystem.cs script located in Standard Assets/Scripts/CoherentUI to fit your needs.

custom_uisystem.jpg
Custom CoherentUISystem component

The CoherentUISystem component is designed to be only one in the whole game. Adding more than one CoherentUISystems to your level will result in undefined behavior.

Update cycle

In a standard C++ or .NET application you need to poll Coherent UI for surfaces each frame using the Update and FetchSurfaces API calls. In our Unity integration, this is all hidden from you and you don't have to worry about it. The CoherentUIViewRenderer component issues rendering events which are handled by our library. All that's left for you is to drag a CoherentUIView component on an object!

Input forwarding - Desktop

A CoherentUIView requires focus to receive user input. Usually you'd want to forward input to a single view, but for flexibility Coherent UI supports multiple focused views. A CoherentUIView's focus is controlled by the ReceivesInput property. To avoid confusion with multiple views, the property is set to false by default, meaning no input will be forwarded to Coherent UI unless you explicitly set it in your Game Object. It is NOT exposed in the Inspector, as it designed to be modified in code only.

Note
The forwarding happens in the CoherentUISystem's LateUpdate method, allowing you to do all your logic for input focus management in the Update methods of your components.

Input forwarding - Mobile

Due to differences in the input management for iOS/Android, Coherent UI provides a helper class for getting the list of touches for the current frame. The Coherent touch structure is InputManager.CoherentTouch - very much the same as Unity3D's Touch structure. The equivalent methods for Input.touchCount and Input.GetTouch(index) are InputManager.TouchesCount and InputManger.GetTouch(index), respectively.

For iOS there's practically no difference between the Coherent and Unity3D touches. For Android, however, Coherent touches contain only touches that reached the game (i.e. the touch wasn't filtered using the techniques described in the next paragraph). The Unity3D supplied touches on Android aren't filtered and you get all of them when using the Input.touches array, regardless of whether they are on the UI or not. When using Coherent UI for mobile, it is recommended to use Coherent touches instead of Unity3D touches to avoid platform differences between iOS and Android.

On iOS/Android all Coherent UI Views are composited in 2D on-top of your Unity3D application content. When the user start a touch event or performs a gesture there is a mechanism that decides if that event should be handled by the UI or the application. It works like this: in the properties of the View the user can select one of three input modes for a every View - "Take All", "Take None", "Transparent". Keep in mind that all those modifiers are in effect only for events that happend are in the bounds of the View. If the user touches outside a particular View the event is always handled by the game.

  • "Take All" specifies that all events are handled by the View and nothing goes to the game. It is usable if you want to have for instance an in-game browser. All touches on it should be handled by itself and not influence the game.
  • "Take None" specifies that the View passes all input to the game. This is usable if you need to just show some non-interactive views or disable their input completely in some situation.
  • "Transparent" specifies that the input is either handled by the View or the game - usable for HUDs, Menus etc. For Views with "Transparent" input mode the user is the one in charge of deciding if an element on the page is interactive - hence should receive input or is 'input transparent'.
    Note
    iOS: Input "Transparent" views work correctly ONLY if you have included coherent.js in your HTML page.
    Android: Input on any view works correctly ONLY if you have included coherent.js in your HTML page.
    Upon touch within a View, Coherent UI Mobile inspects the touched element:
  • if the element has the CSS class coui-noinput it passes input to the game. The element does not accept input.
  • if the element has the CSS class coui-inputcallback, a method called couiInputCallback(x, y) is called on the element with the coordinates of the event. It should return "true" if the user wants the element to handle the input and "false" if the game should handle it. This allows for custom fine-grained control in JavaScript on which elements are interactive.
  • if the class coui-noinput and coui-inputcallback are missing from the element, it is assumed that it is interactable and takes the input.

To summarize: If a View has an Input State set to "Transparent" all elements are by default interactive and take input. You can mark elements with the CSS class coui-noinput to make them transparent to input. If you need more advanced logic when deciding if an element is interactive or not you can decorate it with coui-inputcallback and implement a method couiInputCallback(x, y) on it.

Mobile Preview

The preview for the mobile versions of Coherent UI allows you to easily see how your page behaves without testing it on a device or simulator. There are a few notable differences, however. First, the input redirection is based on the Android version, meaning you need to import coherent.js in your HTML files for it to work. All other notes for the input regarding Android apply for the preview as well. Another difference is that on the devices the CoherentUIView is always shown on top. Due to the specifics of Unity this is not easy to simulate automatically without interfering with some client functionality. That's why it's up to the user to simulate this behaviour in the preview. You should ensure that the camera you have your view on is always drawn last so the views are displayed the same, both in Editor preview and on the device.

Custom file handler

The CoherentUISystem component makes use of a static factory function object (FileHandlerFactoryFunc) to create the FileHandler object that is used reading URLs with the coui scheme. The default function returns a handler that reads resources from the path set by Edit → Project Settings → Coherent UI → Select UI folder for the Editor and in the Data folder for built games.

The factory function object is public and can be customized. The FileHandler it returns is passed to the UI initialization routine in the Start method of the CoherentUISystem component. That means the user should set the factory function prior to the invocation of the Start method of the components - e.g. in the Awake method.

Note
You can check the execution order of event function in Unity3D on this page

This is an example usage of a custom file handler:

public class CustomFileHandlerScript : MonoBehaviour {
class CustomFileHandler : Coherent.UI.FileHandler
{
public override void ReadFile (string url,
Coherent.UI.URLRequestBase request,
Coherent.UI.ResourceResponse response)
{
// Implementation here
}
public override void WriteFile (string url, Coherent.UI.ResourceData resource)
{
// Implementation here
}
}
//----------------------------------------------------------------------------------
void Awake()
{
CoherentUISystem.FileHandlerFactoryFunc = () => { return new CustomFileHandler(); };
}
}

See Archive resource demo for an example.

UI Resources

Files for Coherent UI are by default selected from the folder set by Edit → Project Settings → Coherent UI → Select UI folder. Resources found there will be used by the editor and will automatically be copied in your game upon build.

The selected UI resources folder is per-user so that different developers working on the game can have their UI folders wherever they want on their machine. You can also set a per-project folder for the UI resources. This is done by extending the CoherentPostProcessor class by setting a static const setting named ProjectUIResources:

public partial class CoherentPostProcessor {
public static string ProjectUIResources = "relative/path/to/ui/resources";
}

The per-project path must be relative to the folder of the project and the extension class should live under the 'Editor' folder in Unity. This feature is very handy also if you build your game on machines that can't start Unity and you use the command line. The per-user setting overrides the per-project one so that developers can still put their resources wherever they want.

Warning
When using the "Build & run" option for Android, the required resources will NOT be packaged because this is done as a post-build step. Unity3D pushes the non-repacked APK first, and then executes the post-build step which results in an APK without UI resources and including unneeded files. To work around that, you should either use the "Build" option, which produces an APK on your computer that can be installed on a device using the ADB tool in the Android SDK, or generate an Eclipse project and run it from the IDE.

Click-to-focus Views - Desktop only

When the ClickToFocus property is enabled on a View, it will automatically take all the input focus when you click on it and lose it when you click somewhere else. When focused, all mouse and keyboard input will be forwarded to the View. "Click-to-focus" views have their ReceivesInput property managed by the CoherentUISystem and you should NOT set it manually. If you do so, you'll receive a warning message in Unity3D and the input forwarding behavior will be unexpected.

Warning
There is no way to prevent the standard Unity character controller scripts from moving the character, even when the input event is used. You have to manually disable your character controller when you want the user to type in in a view and stands still. For an explanation see the Menu And HUD sample.
Note
"Click-to-focus" views perform raycasts to obtain the object in the 3D world below the cursor. For a raycast to report the correct texture coordinates of the hitpoint, you need to set up a Mesh Collider on the objects with Coherent UI Views placed.

"Click-to-focus" Views are useful in cases when you want keyboard input forwarded to a View regardless of the mouse position, e.g. input fields.

Note
To function properly, "Click-to-focus" views need to know which camera is the main camera in the scene. For simple scenes, this can be obtained from the Camera.main property in Unity3D. This is what Coherent UI assumes is the main camera, and obtains it in the MonoBehaviour.OnEnable callback, which is executed when a scene is loaded. This is done only if there is no currently set camera for the m_MainCamera field so it does not interfere with custom user code. For complex scenes with multiple cameras, however, it is up to you to set the public m_MainCamera field to the appropriate camera (also visible in the Inspector window).

Which CoherentUIViews receive input is up to your gameplay needs. Here we'll walk you through a simple script that you'll see used in the samples - it forwards input to the closest view under the cursor. First, it sets the ReceivesInput property to all views to false. Then it queries the CoherentUIView attached to the main camera (if any) whether the mouse is over a solid or transparent pixel (make sure to set the SupportClickThrough property of the HUD view to true to support this operation). If the mouse is over a solid pixel, then the HUD is focused and receives input. Otherwise, a raycast is generated that finds the object under the cursor. If that object has a CoherentUIView component, that's what gets the focus.

Here's the script itself:

#if UNITY_STANDALONE || UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX
#define COHERENT_UNITY_STANDALONE
#endif
using UnityEngine;
using System.Collections;
#if COHERENT_UNITY_STANDALONE || UNITY_EDITOR
public class ObjectPicker : MonoBehaviour {
private Camera m_MainCamera;
private CoherentUISystem m_UISystem;
// Use this for initialization
void Start () {
m_MainCamera = GameObject.Find("Main Camera").GetComponent<Camera>();
m_UISystem = Component.FindObjectOfType(typeof(CoherentUISystem)) as CoherentUISystem;
}
// Update is called once per frame
void Update () {
if (m_UISystem.HasFocusedView)
{
return;
}
// Reset input processing for all views
foreach (var item in m_UISystem.UIViews) {
if (!item.ClickToFocus) {
item.ReceivesInput = false;
}
}
var cameraView = m_MainCamera.gameObject.GetComponent<CoherentUIView>();
if (cameraView && !cameraView.ClickToFocus)
{
var view = cameraView.View;
if (view != null)
{
var factorY = cameraView.Height / m_MainCamera.pixelHeight;
//Normalize the view coordinates. We need this when we use view dimensions
//are different than the camera ones
var normX = Input.mousePosition.x / cameraView.Width;
var normY = 1 - Input.mousePosition.y / cameraView.Height;
//After the normalizations, the Normalized Y coordinate will be displaced because Y coords
//grow downwards and we have to put it back into the [0-1] range.
//E.g. if the view height is two times smaller
//than the camera height, the normalized Y coords will start from -1 and end to +1.
//If the view's height is 4 times smaller, the normalized coords will start from -3 and end to +1
//The formula puts the Y coord back in [0-1] range.
normY = ( (normY * factorY) + (1 - factorY) ) / factorY;
if (normX >= 0 && normX <= 1 && normY >= 0 && normY <= 1)
{
view.IssueMouseOnUIQuery(normX, normY);
view.FetchMouseOnUIQuery();
if (view.IsMouseOnView())
{
cameraView.ReceivesInput = true;
return;
}
}
}
}
// Activate input processing for the view below the mouse cursor
RaycastHit hitInfo;
if (Physics.Raycast(m_MainCamera.ScreenPointToRay(Input.mousePosition), out hitInfo))
{
//Debug.Log (hitInfo.collider.name);
CoherentUIView viewComponent = hitInfo.collider.gameObject.GetComponent(typeof(CoherentUIView)) as CoherentUIView;
if (viewComponent == null)
{
viewComponent = hitInfo.collider.gameObject.GetComponentInChildren(typeof(CoherentUIView)) as CoherentUIView;
}
if (viewComponent != null && !viewComponent.ClickToFocus)
{
viewComponent.ReceivesInput = true;
viewComponent.SetMousePosition(
(int)(hitInfo.textureCoord.x * viewComponent.Width),
(int)(hitInfo.textureCoord.y * viewComponent.Height));
}
}
}
}
#endif

To summarize, you can apply any logic you like for input forwarding - e.g. forward input to objects in the view frustum, HUD only, etc. Coherent UI supports multiple focused views. View focus can be modified using the ReceivesInput property of CoherentUIView which is controlled only by the script code.

You can also mark views as "Click to focus" which makes them take all the focus when clicking them (and lose focus when clicking somewhere else). You should take care not to set the ReceivesInput property on "Click to focus"-enabled Views as it is automatically managed. Setting the ReceivesInput property on such views manually will result in unexpected behavior and will produce a warning message.

View Filters - Desktop only

Coherent UI provides three types of filtering:

  • Point Filtering - applies point filtering to the view texture.
  • Linear Filtering - applies linear filtering to the view texture.

Hit testing - Desktop only

Note
For and explanation about input forwarding for Mobile check Input Forwarding Mobile

Forwarding input to Views attached to the camera is straight-forward - you only have to mark your view as an input receiver using the ReceivesInput property of CoherentUIView. The mouse position will be obtained from the Input.mousePosition property.

If you want to forward an input event to a View that's attached on an object in the 3D world, you'll have to do a bit more work. You'll have to use a raycast to find the object below the cursor and then transform the texture coordinates of the hit point into the space of the Coherent UI View. Note that Unity provides texture coordinates only when the object has a Mesh Collider component attached. The coordinates must be transformed from [0, 1] to [view.Width, view.Height]. This can usually be done simply by multiplying the coordinates by the dimensions of the View (which are available as properties). Then, you have to set the resulting coordinates to the CoherentUIView component using the SetMousePosition method. Check Input Forwarding for an example script that forwards input to the view on the object that is currently below the cursor. Note that in the samples the MeshCollider component has the same geometry as the renderable mesh. This may not always be true and in such cases you would have to make a transformation of the coordinates that works for you.

For a sample how hit testing works see the Menu and HUD sample.

Mobile Surface Views

Displaying CoherentUI view on a surface is straightforward for Desktop platforms. Unfortunately the performance and API restrictions of the current platforms do not allow us to fully support views on surfaces for mobile. Mobile Surface Views allow displaying of HTML5 content on a surface in mobile games with the following limitations:

  • the view must be explicitly updated using the MobileSurfaceView.UpdateView method.
  • there is no input for the view. Input could be simulated using JavaScript.

To create a Mobile Surface View, simply add the component to a object with a renderer component. The MobileSurfaceView component will create a new texture for the renderer and replace the main texture of the material with the view.

See also the Mobile Surface Sample.

Logging

Coherent UI logs are automatically redirected to the Unity console (or game log for built games) using the Debug.Log method. You can control the minimum severity of the Coherent UI logs when initializing the Coherent UI System.

Live Game Views

Note
Live Game Views are a Desktop-only feature.

Live Game Views are one of the most powerful yet easy to use fetures in Coherent UI for Unity 3D. They allow you to have 3D rendered images (by a Unity3D Camera) as part of the UI itself. The images are automatically updated in a high-performance way and made available to the UI JavaScript code.

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..

The steps to get a Live Game View are trivial:

  1. Add the Coherent UI "Live Game View" Component to a GameObject that already has a Coherent UI View.
  2. Give the link a Name
  3. Set the size
  4. Drag a Camera that will send the data
  5. (Optional) You can select a texture too in the Component. If you don't select a Camera - this texture will be rendered instead. In this way you can send just textures in the UI.

The "Live Game View" Component represents a link between the View and a Unity Camera or a texture. When you attach it - it will automatically start sending the updated image drawn by the linked Camera to the JavaScript code of the page currently displayed by the View.

Every such link has a Name that is used to identify it inside the page's JS code. You can have as many Live Game Views attached to the same Coherent UI View as you want.

After you press "Play", the Live Game View will be operational and everything the Camera "sees" will be available in the UI as an ImageData object.

To use it - add a "canvas" element in the page and a "onEngineImageDataUpdated" function to it. This function will be called every time the image is updated and the name will be passed so that you can identify just the one you need.

In the "onEngineImageDataUpdated" function you can do whatever you need with the image - draw it in the canvas, apply filters, write text etc..

This snippet shows a sample UI JavaScript function that draws the image in a "canvas" element and writes text on it:

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);
}
}

As you can see we just listen for when a new image has arrived and re-draw the content of the canvas named "myCanvas". The "name" parameter received is the "Name" of the Live Game View as specified in the Unity Inspector and allows us to identify the different links.

Note
For a sample scene with Live Game Views check the "Sample_LiveGameViews" scene available in the Coherent UI package.

Font Rendering

Coherent UI uses ClearType on Microsoft Windows. This allows fonts to look the same way as they do in the operating system and the rest of applications.

However, there are fonts that look fuzzy in certain sizes when they are rendered with ClearType. Here is a screenshot of the Lato font using ClearType:

cleartype.png
Lato font with ClearType
Coherent UI has a CSS property -coherent-font-cleartype that gives you control over whether ClearType should be used or standard antialiasing. -coherent-font-cleartype has two values:

  • on - use ClearType if possible. This is the default value
  • off - do not use ClearType at all

To turn off ClearType for a certain element you can use

<p style="-coherent-font-cleartype: off">
Grumpy wizards make toxic brew for the evil Queen and Jack.
</p>

And here is the result with -coherent-font-cleartype: off:

cleartype_off.png
Lato font without ClearType

Note that the result of using or turning off ClearType depends a lot on the font itself, the font size and weight.