Skip to content

Commit

Permalink
release 2020.2.0
Browse files Browse the repository at this point in the history
release 2020.2.0
  • Loading branch information
Philipp Molitor authored Mar 22, 2021
2 parents 29ea327 + 991786f commit 3191dae
Show file tree
Hide file tree
Showing 17 changed files with 824 additions and 332 deletions.
9 changes: 2 additions & 7 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,7 @@ module.exports = {
browser: true,
es2021: true,
},
extends: [
'plugin:react/recommended',
'airbnb-typescript',
'prettier',
'prettier/@typescript-eslint',
'prettier/react',
],
extends: ['plugin:react/recommended', 'airbnb-typescript', 'prettier'],
plugins: [
'react',
'@typescript-eslint',
Expand Down Expand Up @@ -49,6 +43,7 @@ module.exports = {
'max-classes-per-file': 'off',
'import/prefer-default-export': 'off',
'class-methods-use-this': 'off',
'no-underscore-dangle': ['error', { allow: ['__UnityBridgeRegistry__'] }],
'comma-dangle': [
'error',
{
Expand Down
25 changes: 16 additions & 9 deletions .github/workflows/ci-dev.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Build/CI
name: CI

on:
push:
Expand All @@ -9,24 +9,31 @@ on:
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x]
steps:
- name: checkout
uses: actions/checkout@v2

- name: install node ${{ matrix.node-version }}
- name: install node
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
node-version: 14.x

- name: cache node_modules
uses: actions/cache@v2
with:
path: '**/node_modules'
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}

- run: yarn --frozen-lockfile
- run: yarn test
- run: yarn build
- name: install dependencies
run: yarn --frozen-lockfile

- name: execute unit tests
run: yarn test --verbose

- name: generate codecov report
uses: codecov/codecov-action@v1
with:
fail_ci_if_error: true

- name: build dist
run: yarn build
7 changes: 2 additions & 5 deletions .github/workflows/release-npmjs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,14 @@ on:
jobs:
publish:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x]
steps:
- name: checkout
uses: actions/checkout@v2

- name: install node ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
node-version: 14.x
registry-url: 'https://registry.npmjs.org'

- name: cache node_modules
Expand All @@ -28,7 +25,7 @@ jobs:
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}

- run: yarn --frozen-lockfile
- run: yarn test
- run: yarn test --verbose
- run: yarn build
- run: yarn publish --access public
env:
Expand Down
33 changes: 3 additions & 30 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"editor.autoClosingBrackets": "always",
"editor.autoClosingBrackets": "languageDefined",
"editor.linkedEditing": true,
"editor.semanticHighlighting.enabled": true,
"editor.codeActionsOnSave": {
Expand All @@ -8,13 +8,14 @@
"editor.quickSuggestions": {
"other": true,
"comments": false,
"strings": true
"strings": false
},
"typescript.updateImportsOnFileMove.enabled": "always",
"eslint.validate": [
"html",
"javascript",
"javascriptreact",
"typescript",
"typescriptreact"
],
"[javascript]": {
Expand All @@ -25,14 +26,6 @@
"source.fixAll.eslint": true
}
},
"[javascriptreact]": {
"editor.tabSize": 2,
"editor.detectIndentation": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
},
"[typescript]": {
"editor.tabSize": 2,
"editor.detectIndentation": true,
Expand All @@ -57,31 +50,11 @@
"source.fixAll.eslint": true
}
},
"[css]": {
"editor.tabSize": 2,
"editor.detectIndentation": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[less]": {
"editor.tabSize": 2,
"editor.detectIndentation": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[scss]": {
"editor.tabSize": 2,
"editor.detectIndentation": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.tabSize": 2,
"editor.detectIndentation": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[jsonc]": {
"editor.tabSize": 2,
"editor.detectIndentation": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[yml]": {
"editor.tabSize": 2,
"editor.detectIndentation": true,
Expand Down
133 changes: 103 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,29 @@

<p align="center">

<img src="https://github.com/PhilippMolitor/react-unity-renderer/actions/workflows/ci-dev.yaml/badge.svg?branch=dev">
<img src="https://github.com/PhilippMolitor/react-unity-renderer/actions/workflows/release-npmjs.yaml/badge.svg?event=release">
<a href="https://github.com/PhilippMolitor/react-unity-renderer/actions/workflows/ci-dev.yaml">
<img src="https://github.com/PhilippMolitor/react-unity-renderer/actions/workflows/ci-dev.yaml/badge.svg?branch=dev">
</a>
<a href="https://github.com/PhilippMolitor/react-unity-renderer/actions/workflows/release-npmjs.yaml">
<img src="https://github.com/PhilippMolitor/react-unity-renderer/actions/workflows/release-npmjs.yaml/badge.svg">
</a>

<a href="https://codecov.io/gh/PhilippMolitor/react-unity-renderer">
<img src="https://codecov.io/gh/PhilippMolitor/react-unity-renderer/branch/dev/graph/badge.svg?token=4D72B9VWYK"/>
</a>

<img src="https://img.shields.io/npm/l/react-unity-renderer">
<img src="https://img.shields.io/npm/dw/react-unity-renderer">
<img src="https://img.shields.io/github/stars/PhilippMolitor/react-unity-renderer">
<img src="https://img.shields.io/npm/v/react-unity-renderer">
<img src="https://img.shields.io/bundlephobia/minzip/react-unity-renderer">

</p>

> This project is heavily inspired by [react-unity-webgl](https://github.com/elraccoone/react-unity-webgl) made by Jeffrey Lanters.
> This is a modernized, `FunctionComponent` based interpretation of his ideas.
<a href="https://npmjs.com/package/react-unity-renderer">
<img src="https://img.shields.io/npm/dw/react-unity-renderer">
<img src="https://img.shields.io/npm/v/react-unity-renderer">
<img src="https://img.shields.io/bundlephobia/minzip/react-unity-renderer">
</a>

## Introduction
</p>

TODO
> This project is heavily inspired by [react-unity-webgl](https://github.com/elraccoone/react-unity-webgl) made by Jeffrey Lanters. This implementation uses function components + hooks, is getting tested continously and has strict linting and formatting rules which are always enforced.
## Installation

Expand Down Expand Up @@ -49,7 +56,7 @@ import {
UnityContext,
UnityRenderer,
UnityLoaderConfig,
} from 'react-unity-webgl';
} from 'react-unity-renderer';

// get those URLs from your Unity WebGL build.
// you *could* put a JSON in your WebGL template containing this information
Expand All @@ -66,22 +73,16 @@ const config: UnityLoaderConfig = {
companyName: '',
productName: '',
productVersion: '',
modules: {},
};

export const UnityGameComponent: VFC = (): JSX.Element => {
// your need to construct a config or pass it from the props
// You need to construct a config or pass it from the props:
const [ctx] = useState<UnityContext>(new UnityContext(config));

// You can keep track of the game progress and ready state like this.
// Keep track of the game progress and ready state like this:
const [progress, setProgress] = useState<number>(0);
const [ready, setReady] = useState<boolean>(false);

// Attach some event handlers to the context
useEffect(() => {
ctx.on('message', (m: string) => console.log(message));
}, []);

return (
<UnityRenderer
context={ctx}
Expand All @@ -98,6 +99,8 @@ export const UnityGameComponent: VFC = (): JSX.Element => {
};
```

:warning: It is recommended to store the `UnityContext`, as well as the progress, ready and error states in a global state. This way you can keep track of the game state in every part of your application. Consider [zustand](https://github.com/pmndrs/zustand) as a lightweight alternative to Redux, MobX & co., as it has every feature needed for this use case and takes way less effort to implement.

## Mitigating the "keyboard capturing issue"

By default, Unity WebGL builds capture the keyboard as soon as they are loaded. This means that all keyboard input on the website is captured by the game, and rendering all `<input>`, `<textarea>` and similar input methods useless.
Expand Down Expand Up @@ -189,24 +192,93 @@ export async function fetchLoaderConfig(

You can then use it to construct a `UnityContext` and pass this context to your `UnityRenderer` via the `context` prop.

## Sending events from Unity
## Receiving events from Unity

### On the Unity side

In order to send events from Unity to the react application, use the global method for that in your `*.jslib` mapping file:
In order to send events from Unity to the React application, use the global method for that in your `*.jslib` mapping file:

```javascript
mergeInto(LibraryManager.library, {
RunSomeActionInJavaScript: function (message, number) {
RunSomeActionInJavaScript: function (message, counter) {
// surround with try/catch to make unity not crash in case the method is
// not defined in the global scope yet
try {
window.UnityBridge('event-name')(Pointer_stringify(message), number);
const messageString = Pointer_stringify(message);

// UnityBridge(event: string) returns a callback that calls
// every registered event handler with the provided arguments.
// It also handles unregistered events with a warning!
window.UnityBridge('event-name')(messageString, number);
} catch (e) {}
},
});
```

If the event name has no registered event handlers, the `UnityBridge(event: string)` function will log a warning via `console.warn(...)`.

:warning: Please note that returning values from the `UnityBridge()` method is not supported, as it may call multiple event handlers internally from different `UnityContext`s that are listening for a certain event, e.g. when having two or more renderers in your application. The preferred way to handle this is to emit a message to the correct Unity instance, which this library also supports. This also helps making the communication paths simpler: **Events only go from Unity to JavaScript, Messages only go from JavaScript to Unity.**

### On the React side

```tsx
import { VFC, useState } from 'react';
import { UnityContext, UnityRenderer } from 'react-unity-renderer';

export const UnityGameComponent: VFC = (): JSX.Element => {
const [ctx] = useState<UnityContext>(new UnityContext({ ... }));

// Register your handlers (make sure your context is valid!)
useEffect(() => {
// No context, no handlers!
if(!ctx) return;

ctx.on('message', (m: string) => console.log(message));
ctx.on('other-message', (n: number) => console.log(message));

// You can also unregister event handlers again!
ctx.off('other-message');
}, [ctx]);

return (
<UnityRenderer context={ctx} />
);
};

```

## Emitting messages to Unity

While events are a way to handle actions that were initiated in the Unity game,
messages are a way to communicate the other way, from JavaScript to Unity.

Messages are emitted from the `UnityContext`, the API for emitting then is the same as in the Unity WebGL documentation:

```tsx
import { VFC, useState } from 'react';
import { UnityContext, UnityRenderer } from 'react-unity-renderer';

export const UnityGameComponent: VFC = (): JSX.Element => {
const [ctx] = useState<UnityContext>(new UnityContext({ ... }));

const [ready, setReady] = useState<boolean>(false);

// Listen for the Unity instance to be ready
useEffect(() => {
if(ready === true) {
ctx.emit('GameObjectName', 'ScriptMethodName', 'StringOrNumberArgument');
}
}, [ready]);

return (
<UnityRenderer
context={ctx}
onUnityReadyStateChange={(s) => setReady(s)}
/>
);
};
```

## Module augmentation

Take the following example:
Expand All @@ -227,23 +299,24 @@ In order to make use of TypeScript to its fullest extent, you can augment an Int
Put this either in a file importing `react-unity-renderer` or create a new `unity.d.ts` somewhere in your `src` or (if you have that) `typings` directory:

```typescript
// must be imported, else the module will be redefined,
// and this causes all sorts of errors.
import 'react-unity-renderer';
// The "{} from" part just imports the TypeScript definitions, so
// we do not re-define the whole module, but just augment it.
import {} from 'react-unity-renderer';

// module augmentation
declare module 'react-unity-renderer' {
// this is the interface providing autocompletion
interface EventSignatures {
// "info" is the event name
// the type on the right side is anything that would match TypeScript's
// Parameters<> helper type
// The type on the right side is anything that would match TypeScript's
// Parameters<> helper type.
info: [message: string];

// also possible:
info: [string];
// Note that all parameter names are just labels, so they are fully optional.
// Though, they are displayed when autocompleting, so labels are quite helpful here.
'some-event': [number, debug: string];
// note that all parametrs names are just labels, so they are fully optional.
}
}
```
Expand Down
Loading

0 comments on commit 3191dae

Please sign in to comment.