From e1a1e5c9f9102dda44f2c4e43d99299a4ce059fc Mon Sep 17 00:00:00 2001 From: Leaguefun Date: Wed, 3 Jun 2026 22:53:01 +0800 Subject: [PATCH 01/12] feat: improve types, docs, and podspec for RN 0.85+ compatibility - Fix UnityView props to extend ViewProps (enables style typing without manual .d.ts workarounds) - Add troubleshooting section for common iOS/Android integration issues - Improve podspec prepare_command with warning when Unity framework missing - Include pre-built lib/ for GitHub-based installs - Update package metadata for fork Based on upstream v1.0.11 (azesmway/react-native-unity) --- README.md | 39 ++++++++++++ lib/commonjs/UnityView.js | 59 +++++++++++++++++++ lib/commonjs/UnityView.js.map | 1 + lib/commonjs/index.js | 10 ++++ lib/commonjs/index.js.map | 1 + .../specs/UnityViewNativeComponent.js | 14 +++++ .../specs/UnityViewNativeComponent.js.map | 1 + lib/module/UnityView.js | 49 +++++++++++++++ lib/module/UnityView.js.map | 1 + lib/module/index.js | 3 + lib/module/index.js.map | 1 + lib/module/specs/UnityViewNativeComponent.js | 7 +++ .../specs/UnityViewNativeComponent.js.map | 1 + lib/typescript/plugin/src/index.d.ts | 6 ++ lib/typescript/plugin/src/index.d.ts.map | 1 + lib/typescript/src/UnityView.d.ts | 28 +++++++++ lib/typescript/src/UnityView.d.ts.map | 1 + lib/typescript/src/__tests__/index.test.d.ts | 1 + .../src/__tests__/index.test.d.ts.map | 1 + lib/typescript/src/index.d.ts | 3 + lib/typescript/src/index.d.ts.map | 1 + .../src/specs/UnityViewNativeComponent.d.ts | 26 ++++++++ .../specs/UnityViewNativeComponent.d.ts.map | 1 + package.json | 8 +-- react-native-unity.podspec | 12 +++- src/UnityView.tsx | 3 +- 26 files changed, 272 insertions(+), 7 deletions(-) create mode 100644 lib/commonjs/UnityView.js create mode 100644 lib/commonjs/UnityView.js.map create mode 100644 lib/commonjs/index.js create mode 100644 lib/commonjs/index.js.map create mode 100644 lib/commonjs/specs/UnityViewNativeComponent.js create mode 100644 lib/commonjs/specs/UnityViewNativeComponent.js.map create mode 100644 lib/module/UnityView.js create mode 100644 lib/module/UnityView.js.map create mode 100644 lib/module/index.js create mode 100644 lib/module/index.js.map create mode 100644 lib/module/specs/UnityViewNativeComponent.js create mode 100644 lib/module/specs/UnityViewNativeComponent.js.map create mode 100644 lib/typescript/plugin/src/index.d.ts create mode 100644 lib/typescript/plugin/src/index.d.ts.map create mode 100644 lib/typescript/src/UnityView.d.ts create mode 100644 lib/typescript/src/UnityView.d.ts.map create mode 100644 lib/typescript/src/__tests__/index.test.d.ts create mode 100644 lib/typescript/src/__tests__/index.test.d.ts.map create mode 100644 lib/typescript/src/index.d.ts create mode 100644 lib/typescript/src/index.d.ts.map create mode 100644 lib/typescript/src/specs/UnityViewNativeComponent.d.ts create mode 100644 lib/typescript/src/specs/UnityViewNativeComponent.d.ts.map diff --git a/README.md b/README.md index 7b747d4..2b8dbff 100644 --- a/README.md +++ b/README.md @@ -194,6 +194,45 @@ export default Unity; - `pauseUnity?: (pause: boolean)` - pause the Unity - `windowFocusChanged(hasFocus: boolean = false)` - simulate focus change (intended to be used to recover from black screen (not rendering) after remounting Unity view when `resumeUnity` does not work) **ANDROID ONLY** +# Troubleshooting + +## iOS: Unity view not rendering / blank screen + +The `UnityView` component **must** have non-zero dimensions. Always use `style={{ flex: 1 }}` on both the parent container and the `UnityView` itself. The native `layoutSubviews` method checks for positive width and height before attaching the Unity root view. + +## iOS: `MTLTextureDescriptor has width of zero` crash + +This is the same root cause as above. The Unity Metal renderer crashes if it receives a zero-sized texture. Ensure the view has layout dimensions before the component mounts. + +## Android: Build fails with Java-related errors + +Unity's Android export requires a specific JDK version. Add the following to `android/gradle.properties`, pointing to the JDK that matches your Unity version: + +```gradle +org.gradle.java.home=/path/to/your/jdk +``` + +For Unity 6000.x, JDK 17 is typically required (e.g., Zulu JDK 17). + +## React Native 0.85+ / New Architecture (Fabric) + +This package supports New Architecture out of the box via codegen. On RN 0.85+, New Architecture is the default. Ensure: + +- `newArchEnabled=true` in `android/gradle.properties` +- Your Podfile uses `install_modules_dependencies` (standard in RN 0.71+) + +The podspec automatically detects and configures Fabric dependencies when available. + +## iOS: UnityFramework not found during `pod install` + +Ensure you have built the `UnityFramework.framework` from your Unity project and placed it at: + +``` +/unity/builds/ios/UnityFramework.framework +``` + +The `pod install` step copies this framework into the package. If the path is wrong, you will see a warning during installation. + # Contributing See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow. diff --git a/lib/commonjs/UnityView.js b/lib/commonjs/UnityView.js new file mode 100644 index 0000000..be97bae --- /dev/null +++ b/lib/commonjs/UnityView.js @@ -0,0 +1,59 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; +var _react = _interopRequireDefault(require("react")); +var _UnityViewNativeComponent = _interopRequireWildcard(require("./specs/UnityViewNativeComponent")); +var _reactNative = require("react-native"); +function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } +function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } +class UnityView extends _react.default.Component { + ref = /*#__PURE__*/_react.default.createRef(); + postMessage = (gameObject, methodName, message) => { + if (this.ref.current) { + _UnityViewNativeComponent.Commands.postMessage(this.ref.current, gameObject, methodName, message); + } + }; + unloadUnity = () => { + if (this.ref.current) { + _UnityViewNativeComponent.Commands.unloadUnity(this.ref.current); + } + }; + pauseUnity(pause) { + if (this.ref.current) { + _UnityViewNativeComponent.Commands.pauseUnity(this.ref.current, pause); + } + } + resumeUnity() { + if (this.ref.current) { + _UnityViewNativeComponent.Commands.resumeUnity(this.ref.current); + } + } + windowFocusChanged(hasFocus = true) { + if (_reactNative.Platform.OS !== 'android') return; + if (this.ref.current) { + _UnityViewNativeComponent.Commands.windowFocusChanged(this.ref.current, hasFocus); + } + } + getProps() { + return { + ...this.props + }; + } + componentWillUnmount() { + if (this.ref.current) { + _UnityViewNativeComponent.Commands.unloadUnity(this.ref.current); + } + } + render() { + return /*#__PURE__*/_react.default.createElement(_UnityViewNativeComponent.default, _extends({ + ref: this.ref + }, this.getProps())); + } +} +exports.default = UnityView; +//# sourceMappingURL=UnityView.js.map \ No newline at end of file diff --git a/lib/commonjs/UnityView.js.map b/lib/commonjs/UnityView.js.map new file mode 100644 index 0000000..a968e08 --- /dev/null +++ b/lib/commonjs/UnityView.js.map @@ -0,0 +1 @@ +{"version":3,"names":["_react","_interopRequireDefault","require","_UnityViewNativeComponent","_interopRequireWildcard","_reactNative","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","prototype","hasOwnProperty","call","i","set","obj","_extends","assign","bind","target","arguments","length","source","key","apply","UnityView","React","Component","ref","createRef","postMessage","gameObject","methodName","message","current","Commands","unloadUnity","pauseUnity","pause","resumeUnity","windowFocusChanged","hasFocus","Platform","OS","getProps","props","componentWillUnmount","render","createElement","exports"],"sourceRoot":"../../src","sources":["UnityView.tsx"],"mappings":"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"} \ No newline at end of file diff --git a/lib/commonjs/index.js b/lib/commonjs/index.js new file mode 100644 index 0000000..aeee223 --- /dev/null +++ b/lib/commonjs/index.js @@ -0,0 +1,10 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; +var _UnityView = _interopRequireDefault(require("./UnityView")); +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +var _default = exports.default = _UnityView.default; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/lib/commonjs/index.js.map b/lib/commonjs/index.js.map new file mode 100644 index 0000000..3eb8053 --- /dev/null +++ b/lib/commonjs/index.js.map @@ -0,0 +1 @@ +{"version":3,"names":["_UnityView","_interopRequireDefault","require","obj","__esModule","default","_default","exports","UnityView"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;;AAAA,IAAAA,UAAA,GAAAC,sBAAA,CAAAC,OAAA;AAAoC,SAAAD,uBAAAE,GAAA,WAAAA,GAAA,IAAAA,GAAA,CAAAC,UAAA,GAAAD,GAAA,KAAAE,OAAA,EAAAF,GAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAErBG,kBAAS"} \ No newline at end of file diff --git a/lib/commonjs/specs/UnityViewNativeComponent.js b/lib/commonjs/specs/UnityViewNativeComponent.js new file mode 100644 index 0000000..18c3269 --- /dev/null +++ b/lib/commonjs/specs/UnityViewNativeComponent.js @@ -0,0 +1,14 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = exports.Commands = void 0; +var _codegenNativeComponent = _interopRequireDefault(require("react-native/Libraries/Utilities/codegenNativeComponent")); +var _codegenNativeCommands = _interopRequireDefault(require("react-native/Libraries/Utilities/codegenNativeCommands")); +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +const Commands = exports.Commands = (0, _codegenNativeCommands.default)({ + supportedCommands: ['postMessage', 'unloadUnity', 'pauseUnity', 'resumeUnity', 'windowFocusChanged'] +}); +var _default = exports.default = (0, _codegenNativeComponent.default)('RNUnityView'); +//# sourceMappingURL=UnityViewNativeComponent.js.map \ No newline at end of file diff --git a/lib/commonjs/specs/UnityViewNativeComponent.js.map b/lib/commonjs/specs/UnityViewNativeComponent.js.map new file mode 100644 index 0000000..683d65b --- /dev/null +++ b/lib/commonjs/specs/UnityViewNativeComponent.js.map @@ -0,0 +1 @@ +{"version":3,"names":["_codegenNativeComponent","_interopRequireDefault","require","_codegenNativeCommands","obj","__esModule","default","Commands","exports","codegenNativeCommands","supportedCommands","_default","codegenNativeComponent"],"sourceRoot":"../../../src","sources":["specs/UnityViewNativeComponent.ts"],"mappings":";;;;;;AAAA,IAAAA,uBAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,sBAAA,GAAAF,sBAAA,CAAAC,OAAA;AAA2F,SAAAD,uBAAAG,GAAA,WAAAA,GAAA,IAAAA,GAAA,CAAAC,UAAA,GAAAD,GAAA,KAAAE,OAAA,EAAAF,GAAA;AAmCpF,MAAMG,QAAwB,GAAAC,OAAA,CAAAD,QAAA,GAAG,IAAAE,8BAAqB,EAAiB;EAC5EC,iBAAiB,EAAE,CACjB,aAAa,EACb,aAAa,EACb,YAAY,EACZ,aAAa,EACb,oBAAoB;AAExB,CAAC,CAAC;AAAC,IAAAC,QAAA,GAAAH,OAAA,CAAAF,OAAA,GAEY,IAAAM,+BAAsB,EACnC,aACF,CAAC"} \ No newline at end of file diff --git a/lib/module/UnityView.js b/lib/module/UnityView.js new file mode 100644 index 0000000..70a0ffd --- /dev/null +++ b/lib/module/UnityView.js @@ -0,0 +1,49 @@ +function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } +import React from 'react'; +import NativeUnityView, { Commands } from './specs/UnityViewNativeComponent'; +import { Platform } from 'react-native'; +export default class UnityView extends React.Component { + ref = /*#__PURE__*/React.createRef(); + postMessage = (gameObject, methodName, message) => { + if (this.ref.current) { + Commands.postMessage(this.ref.current, gameObject, methodName, message); + } + }; + unloadUnity = () => { + if (this.ref.current) { + Commands.unloadUnity(this.ref.current); + } + }; + pauseUnity(pause) { + if (this.ref.current) { + Commands.pauseUnity(this.ref.current, pause); + } + } + resumeUnity() { + if (this.ref.current) { + Commands.resumeUnity(this.ref.current); + } + } + windowFocusChanged(hasFocus = true) { + if (Platform.OS !== 'android') return; + if (this.ref.current) { + Commands.windowFocusChanged(this.ref.current, hasFocus); + } + } + getProps() { + return { + ...this.props + }; + } + componentWillUnmount() { + if (this.ref.current) { + Commands.unloadUnity(this.ref.current); + } + } + render() { + return /*#__PURE__*/React.createElement(NativeUnityView, _extends({ + ref: this.ref + }, this.getProps())); + } +} +//# sourceMappingURL=UnityView.js.map \ No newline at end of file diff --git a/lib/module/UnityView.js.map b/lib/module/UnityView.js.map new file mode 100644 index 0000000..c0bf50f --- /dev/null +++ b/lib/module/UnityView.js.map @@ -0,0 +1 @@ +{"version":3,"names":["React","NativeUnityView","Commands","Platform","UnityView","Component","ref","createRef","postMessage","gameObject","methodName","message","current","unloadUnity","pauseUnity","pause","resumeUnity","windowFocusChanged","hasFocus","OS","getProps","props","componentWillUnmount","render","createElement","_extends"],"sourceRoot":"../../src","sources":["UnityView.tsx"],"mappings":";AAAA,OAAOA,KAAK,MAAM,OAAO;AAEzB,OAAOC,eAAe,IAAIC,QAAQ,QAAQ,kCAAkC;AAE5E,SAASC,QAAQ,QAAQ,cAAc;AAiBvC,eAAe,MAAMC,SAAS,SAASJ,KAAK,CAACK,SAAS,CAAmB;EACvEC,GAAG,gBAAGN,KAAK,CAACO,SAAS,CAAe,CAAC;EAE9BC,WAAW,GAAGA,CACnBC,UAAkB,EAClBC,UAAkB,EAClBC,OAAe,KACZ;IACH,IAAI,IAAI,CAACL,GAAG,CAACM,OAAO,EAAE;MACpBV,QAAQ,CAACM,WAAW,CAAC,IAAI,CAACF,GAAG,CAACM,OAAO,EAAEH,UAAU,EAAEC,UAAU,EAAEC,OAAO,CAAC;IACzE;EACF,CAAC;EAEME,WAAW,GAAGA,CAAA,KAAM;IACzB,IAAI,IAAI,CAACP,GAAG,CAACM,OAAO,EAAE;MACpBV,QAAQ,CAACW,WAAW,CAAC,IAAI,CAACP,GAAG,CAACM,OAAO,CAAC;IACxC;EACF,CAAC;EAEME,UAAUA,CAACC,KAAc,EAAE;IAChC,IAAI,IAAI,CAACT,GAAG,CAACM,OAAO,EAAE;MACpBV,QAAQ,CAACY,UAAU,CAAC,IAAI,CAACR,GAAG,CAACM,OAAO,EAAEG,KAAK,CAAC;IAC9C;EACF;EAEOC,WAAWA,CAAA,EAAG;IACnB,IAAI,IAAI,CAACV,GAAG,CAACM,OAAO,EAAE;MACpBV,QAAQ,CAACc,WAAW,CAAC,IAAI,CAACV,GAAG,CAACM,OAAO,CAAC;IACxC;EACF;EAEOK,kBAAkBA,CAACC,QAAQ,GAAG,IAAI,EAAE;IACzC,IAAIf,QAAQ,CAACgB,EAAE,KAAK,SAAS,EAAE;IAE/B,IAAI,IAAI,CAACb,GAAG,CAACM,OAAO,EAAE;MACpBV,QAAQ,CAACe,kBAAkB,CAAC,IAAI,CAACX,GAAG,CAACM,OAAO,EAAEM,QAAQ,CAAC;IACzD;EACF;EAEQE,QAAQA,CAAA,EAAG;IACjB,OAAO;MACL,GAAG,IAAI,CAACC;IACV,CAAC;EACH;EAEAC,oBAAoBA,CAAA,EAAG;IACrB,IAAI,IAAI,CAAChB,GAAG,CAACM,OAAO,EAAE;MACpBV,QAAQ,CAACW,WAAW,CAAC,IAAI,CAACP,GAAG,CAACM,OAAO,CAAC;IACxC;EACF;EAEAW,MAAMA,CAAA,EAAG;IACP,oBAAOvB,KAAA,CAAAwB,aAAA,CAACvB,eAAe,EAAAwB,QAAA;MAACnB,GAAG,EAAE,IAAI,CAACA;IAAI,GAAK,IAAI,CAACc,QAAQ,CAAC,CAAC,CAAG,CAAC;EAChE;AACF"} \ No newline at end of file diff --git a/lib/module/index.js b/lib/module/index.js new file mode 100644 index 0000000..646526b --- /dev/null +++ b/lib/module/index.js @@ -0,0 +1,3 @@ +import UnityView from './UnityView'; +export default UnityView; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/lib/module/index.js.map b/lib/module/index.js.map new file mode 100644 index 0000000..e414676 --- /dev/null +++ b/lib/module/index.js.map @@ -0,0 +1 @@ +{"version":3,"names":["UnityView"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"AAAA,OAAOA,SAAS,MAAM,aAAa;AAEnC,eAAeA,SAAS"} \ No newline at end of file diff --git a/lib/module/specs/UnityViewNativeComponent.js b/lib/module/specs/UnityViewNativeComponent.js new file mode 100644 index 0000000..dc24569 --- /dev/null +++ b/lib/module/specs/UnityViewNativeComponent.js @@ -0,0 +1,7 @@ +import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; +import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands'; +export const Commands = codegenNativeCommands({ + supportedCommands: ['postMessage', 'unloadUnity', 'pauseUnity', 'resumeUnity', 'windowFocusChanged'] +}); +export default codegenNativeComponent('RNUnityView'); +//# sourceMappingURL=UnityViewNativeComponent.js.map \ No newline at end of file diff --git a/lib/module/specs/UnityViewNativeComponent.js.map b/lib/module/specs/UnityViewNativeComponent.js.map new file mode 100644 index 0000000..6a9d536 --- /dev/null +++ b/lib/module/specs/UnityViewNativeComponent.js.map @@ -0,0 +1 @@ +{"version":3,"names":["codegenNativeComponent","codegenNativeCommands","Commands","supportedCommands"],"sourceRoot":"../../../src","sources":["specs/UnityViewNativeComponent.ts"],"mappings":"AAAA,OAAOA,sBAAsB,MAAM,yDAAyD;AAC5F,OAAOC,qBAAqB,MAAM,wDAAwD;AAmC1F,OAAO,MAAMC,QAAwB,GAAGD,qBAAqB,CAAiB;EAC5EE,iBAAiB,EAAE,CACjB,aAAa,EACb,aAAa,EACb,YAAY,EACZ,aAAa,EACb,oBAAoB;AAExB,CAAC,CAAC;AAEF,eAAeH,sBAAsB,CACnC,aACF,CAAC"} \ No newline at end of file diff --git a/lib/typescript/plugin/src/index.d.ts b/lib/typescript/plugin/src/index.d.ts new file mode 100644 index 0000000..50afa16 --- /dev/null +++ b/lib/typescript/plugin/src/index.d.ts @@ -0,0 +1,6 @@ +import type { ConfigPlugin } from '@expo/config-plugins'; +declare const withUnity: ConfigPlugin<{ + name?: string; +}>; +export default withUnity; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/lib/typescript/plugin/src/index.d.ts.map b/lib/typescript/plugin/src/index.d.ts.map new file mode 100644 index 0000000..43476ac --- /dev/null +++ b/lib/typescript/plugin/src/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../plugin/src/index.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,QAAA,MAAM,SAAS,EAAE,YAAY,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAU9C,CAAC;AAyDF,eAAe,SAAS,CAAC"} \ No newline at end of file diff --git a/lib/typescript/src/UnityView.d.ts b/lib/typescript/src/UnityView.d.ts new file mode 100644 index 0000000..4064610 --- /dev/null +++ b/lib/typescript/src/UnityView.d.ts @@ -0,0 +1,28 @@ +/// +/// +import React from 'react'; +import type { DirectEventHandler } from 'react-native/Libraries/Types/CodegenTypes'; +import type { ViewProps } from 'react-native'; +type UnityViewContentUpdateEvent = Readonly<{ + message: string; +}>; +type RNUnityViewProps = ViewProps & { + androidKeepPlayerMounted?: boolean; + fullScreen?: boolean; + onUnityMessage?: DirectEventHandler; + onPlayerUnload?: DirectEventHandler; + onPlayerQuit?: DirectEventHandler; +}; +export default class UnityView extends React.Component { + ref: React.RefObject & Readonly>; + postMessage: (gameObject: string, methodName: string, message: string) => void; + unloadUnity: () => void; + pauseUnity(pause: boolean): void; + resumeUnity(): void; + windowFocusChanged(hasFocus?: boolean): void; + private getProps; + componentWillUnmount(): void; + render(): JSX.Element; +} +export {}; +//# sourceMappingURL=UnityView.d.ts.map \ No newline at end of file diff --git a/lib/typescript/src/UnityView.d.ts.map b/lib/typescript/src/UnityView.d.ts.map new file mode 100644 index 0000000..0e610c4 --- /dev/null +++ b/lib/typescript/src/UnityView.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"UnityView.d.ts","sourceRoot":"","sources":["../../../src/UnityView.tsx"],"names":[],"mappings":";;AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAC;AAEpF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,KAAK,2BAA2B,GAAG,QAAQ,CAAC;IAC1C,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAAC;AAEH,KAAK,gBAAgB,GAAG,SAAS,GAAG;IAClC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,kBAAkB,CAAC,2BAA2B,CAAC,CAAC;IACjE,cAAc,CAAC,EAAE,kBAAkB,CAAC,2BAA2B,CAAC,CAAC;IACjE,YAAY,CAAC,EAAE,kBAAkB,CAAC,2BAA2B,CAAC,CAAC;CAChE,CAAC;AAIF,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,KAAK,CAAC,SAAS,CAAC,gBAAgB,CAAC;IACtE,GAAG,qJAAmC;IAE/B,WAAW,eACJ,MAAM,cACN,MAAM,WACT,MAAM,UAKf;IAEK,WAAW,aAIhB;IAEK,UAAU,CAAC,KAAK,EAAE,OAAO;IAMzB,WAAW;IAMX,kBAAkB,CAAC,QAAQ,UAAO;IAQzC,OAAO,CAAC,QAAQ;IAMhB,oBAAoB;IAMpB,MAAM;CAGP"} \ No newline at end of file diff --git a/lib/typescript/src/__tests__/index.test.d.ts b/lib/typescript/src/__tests__/index.test.d.ts new file mode 100644 index 0000000..cbbd668 --- /dev/null +++ b/lib/typescript/src/__tests__/index.test.d.ts @@ -0,0 +1 @@ +//# sourceMappingURL=index.test.d.ts.map \ No newline at end of file diff --git a/lib/typescript/src/__tests__/index.test.d.ts.map b/lib/typescript/src/__tests__/index.test.d.ts.map new file mode 100644 index 0000000..7b9421a --- /dev/null +++ b/lib/typescript/src/__tests__/index.test.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../../src/__tests__/index.test.tsx"],"names":[],"mappings":""} \ No newline at end of file diff --git a/lib/typescript/src/index.d.ts b/lib/typescript/src/index.d.ts new file mode 100644 index 0000000..d13ac04 --- /dev/null +++ b/lib/typescript/src/index.d.ts @@ -0,0 +1,3 @@ +import UnityView from './UnityView'; +export default UnityView; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/lib/typescript/src/index.d.ts.map b/lib/typescript/src/index.d.ts.map new file mode 100644 index 0000000..b5dacd5 --- /dev/null +++ b/lib/typescript/src/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,aAAa,CAAC;AAEpC,eAAe,SAAS,CAAC"} \ No newline at end of file diff --git a/lib/typescript/src/specs/UnityViewNativeComponent.d.ts b/lib/typescript/src/specs/UnityViewNativeComponent.d.ts new file mode 100644 index 0000000..e5a1a06 --- /dev/null +++ b/lib/typescript/src/specs/UnityViewNativeComponent.d.ts @@ -0,0 +1,26 @@ +/// +/// +/// +import type { HostComponent, ViewProps } from 'react-native'; +import type { DirectEventHandler } from 'react-native/Libraries/Types/CodegenTypes'; +export type UnityViewContentUpdateEvent = Readonly<{ + message: string; +}>; +export interface NativeProps extends ViewProps { + androidKeepPlayerMounted?: boolean; + fullScreen?: boolean; + onUnityMessage?: DirectEventHandler; + onPlayerUnload?: DirectEventHandler; + onPlayerQuit?: DirectEventHandler; +} +export interface NativeCommands { + postMessage: (viewRef: React.ElementRef>, gameObject: string, methodName: string, message: string) => void; + unloadUnity: (viewRef: React.ElementRef>) => void; + pauseUnity: (viewRef: React.ElementRef>, pause: boolean) => void; + resumeUnity: (viewRef: React.ElementRef>) => void; + windowFocusChanged: (viewRef: React.ElementRef>, hasFocus: boolean) => void; +} +export declare const Commands: NativeCommands; +declare const _default: HostComponent; +export default _default; +//# sourceMappingURL=UnityViewNativeComponent.d.ts.map \ No newline at end of file diff --git a/lib/typescript/src/specs/UnityViewNativeComponent.d.ts.map b/lib/typescript/src/specs/UnityViewNativeComponent.d.ts.map new file mode 100644 index 0000000..73e15f1 --- /dev/null +++ b/lib/typescript/src/specs/UnityViewNativeComponent.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"UnityViewNativeComponent.d.ts","sourceRoot":"","sources":["../../../../src/specs/UnityViewNativeComponent.ts"],"names":[],"mappings":";;;AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAC;AAEpF,MAAM,MAAM,2BAA2B,GAAG,QAAQ,CAAC;IACjD,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAAC;AAEH,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,kBAAkB,CAAC,2BAA2B,CAAC,CAAC;IACjE,cAAc,CAAC,EAAE,kBAAkB,CAAC,2BAA2B,CAAC,CAAC;IACjE,YAAY,CAAC,EAAE,kBAAkB,CAAC,2BAA2B,CAAC,CAAC;CAChE;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,CACX,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,EACrD,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,KACZ,IAAI,CAAC;IACV,WAAW,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,KAAK,IAAI,CAAC;IAC7E,UAAU,EAAE,CACV,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,EACrD,KAAK,EAAE,OAAO,KACX,IAAI,CAAC;IACV,WAAW,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,KAAK,IAAI,CAAC;IAC7E,kBAAkB,EAAE,CAClB,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,EACrD,QAAQ,EAAE,OAAO,KACd,IAAI,CAAC;CACX;AAED,eAAO,MAAM,QAAQ,EAAE,cAQrB,CAAC;;AAEH,wBAEgC"} \ No newline at end of file diff --git a/package.json b/package.json index 063bf5e..b3dfb20 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@azesmway/react-native-unity", - "version": "1.0.11", + "version": "1.0.11-fork.1", "description": "React Native Unity", "main": "lib/commonjs/index", "module": "lib/module/index", @@ -43,14 +43,14 @@ ], "repository": { "type": "git", - "url": "git+https://github.com/azesmway/react-native-unity.git" + "url": "git+https://github.com/leaguefun/react-native-unity.git" }, "author": "Alexey Zolotaryov (https://github.com/azesmway)", "license": "MIT", "bugs": { - "url": "https://github.com/azesmway/react-native-unity/issues" + "url": "https://github.com/leaguefun/react-native-unity/issues" }, - "homepage": "https://github.com/azesmway/react-native-unity#readme", + "homepage": "https://github.com/leaguefun/react-native-unity#readme", "publishConfig": { "registry": "https://registry.npmjs.org/", "access": "public" diff --git a/react-native-unity.podspec b/react-native-unity.podspec index af0ea2c..99efe4a 100644 --- a/react-native-unity.podspec +++ b/react-native-unity.podspec @@ -12,7 +12,7 @@ Pod::Spec.new do |s| s.authors = package["author"] s.platforms = { :ios => "12.4" } - s.source = { :git => "https://github.com/azesmway/react-native-unity.git", :tag => "#{s.version}" } + s.source = { :git => "https://github.com/leaguefun/react-native-unity.git", :tag => "#{s.version}" } s.source_files = "ios/**/*.{h,m,mm}" @@ -45,7 +45,15 @@ Pod::Spec.new do |s| # The framework should be placed in the /unity/builds/ios folder. s.prepare_command = <<-CMD - cp -R ../../../unity/builds/ios/ ios/ + UNITY_BUILD_SRC="../../../unity/builds/ios/" + if [ -d "$UNITY_BUILD_SRC" ]; then + cp -R "$UNITY_BUILD_SRC" ios/ + else + echo "" + echo "WARNING: react-native-unity: Unity iOS framework not found at $UNITY_BUILD_SRC" + echo " Place UnityFramework.framework in /unity/builds/ios/" + echo "" + fi CMD s.vendored_frameworks = ["ios/UnityFramework.framework"] diff --git a/src/UnityView.tsx b/src/UnityView.tsx index d9f1b9c..becba62 100644 --- a/src/UnityView.tsx +++ b/src/UnityView.tsx @@ -3,12 +3,13 @@ import React from 'react'; import NativeUnityView, { Commands } from './specs/UnityViewNativeComponent'; import type { DirectEventHandler } from 'react-native/Libraries/Types/CodegenTypes'; import { Platform } from 'react-native'; +import type { ViewProps } from 'react-native'; type UnityViewContentUpdateEvent = Readonly<{ message: string; }>; -type RNUnityViewProps = { +type RNUnityViewProps = ViewProps & { androidKeepPlayerMounted?: boolean; fullScreen?: boolean; onUnityMessage?: DirectEventHandler; From 37a96e35f8e4c3e3af2a8511168b3e2a2da1b681 Mon Sep 17 00:00:00 2001 From: Leaguefun Date: Wed, 3 Jun 2026 22:54:35 +0800 Subject: [PATCH 02/12] fix: correct types entry path in package.json The types field pointed to lib/typescript/index.d.ts but the actual generated file is at lib/typescript/src/index.d.ts. This caused TypeScript to not find declarations when installed from GitHub. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b3dfb20..2826dfd 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "React Native Unity", "main": "lib/commonjs/index", "module": "lib/module/index", - "types": "lib/typescript/index.d.ts", + "types": "lib/typescript/src/index.d.ts", "react-native": "src/index", "source": "src/index", "files": [ From 27829135731f37b9468754fd9798909741494c6c Mon Sep 17 00:00:00 2001 From: Leaguefun Date: Wed, 3 Jun 2026 23:02:49 +0800 Subject: [PATCH 03/12] fix: remove jcenter and hardcoded buildscript for Gradle 9.x compat - Remove buildscript block with hardcoded AGP 7.4.2 (conflicts with host project's AGP version) - Remove jcenter() repository (removed in Gradle 9.x) - Replace deprecated lintOptions with lint block --- android/build.gradle | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index a10543a..1d29b9e 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,14 +1,3 @@ -buildscript { - repositories { - google() - mavenCentral() - } - - dependencies { - classpath "com.android.tools.build:gradle:7.4.2" - } -} - def isNewArchitectureEnabled() { return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true" } @@ -66,7 +55,7 @@ android { } } - lintOptions { + lint { disable "GradleCompatible" } @@ -98,7 +87,6 @@ repositories { } google() mavenCentral() - jcenter() } From 4426f494521c09b48dfc09c8a1abb1a30bb03de8 Mon Sep 17 00:00:00 2001 From: Leaguefun Date: Wed, 3 Jun 2026 23:06:07 +0800 Subject: [PATCH 04/12] fix: handle Unity 6 UnityPlayer no longer extending FrameLayout In Unity 6+, UnityPlayer no longer extends FrameLayout directly. The requestFrame() fallback tried to return unityPlayer as FrameLayout which caused a compilation error. Now tries getView() via reflection as an intermediate fallback, then instanceof check for legacy versions. --- .../com/azesmwayreactnativeunity/UPlayer.java | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/com/azesmwayreactnativeunity/UPlayer.java b/android/src/main/java/com/azesmwayreactnativeunity/UPlayer.java index b944779..52dff70 100644 --- a/android/src/main/java/com/azesmwayreactnativeunity/UPlayer.java +++ b/android/src/main/java/com/azesmwayreactnativeunity/UPlayer.java @@ -92,13 +92,30 @@ public void requestFocusPlayer() throws NoSuchMethodException, InvocationTargetE } public FrameLayout requestFrame() throws NoSuchMethodException { + // Unity 6+: UnityPlayer no longer extends FrameLayout, use getFrameLayout() try { Method getFrameLayout = unityPlayer.getClass().getMethod("getFrameLayout"); - return (FrameLayout) getFrameLayout.invoke(unityPlayer); } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { - return unityPlayer; + // Fall through to getView() + } + // Unity 6+ alternate: try getView() + try { + Method getView = unityPlayer.getClass().getMethod("getView"); + Object view = getView.invoke(unityPlayer); + if (view instanceof FrameLayout) { + return (FrameLayout) view; + } + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + // Fall through + } + // Legacy Unity (pre-6): UnityPlayer itself extends FrameLayout + // Cast through Object to bypass compile-time type check + Object player = unityPlayer; + if (player instanceof FrameLayout) { + return (FrameLayout) player; } + return null; } public void setZ(float v) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { From 7e32966882916c98ccb01272359b35f2a480b407 Mon Sep 17 00:00:00 2001 From: Leaguefun Date: Wed, 3 Jun 2026 23:26:41 +0800 Subject: [PATCH 05/12] chore: add diagnostic logging to Unity initialization --- ios/RNUnityView.mm | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/ios/RNUnityView.mm b/ios/RNUnityView.mm index a4caa74..d9cdecf 100644 --- a/ios/RNUnityView.mm +++ b/ios/RNUnityView.mm @@ -45,10 +45,19 @@ - (bool)unityIsInitialized { - (void)initUnityModule { @try { if([self unityIsInitialized]) { + NSLog(@"[RNUnity] Already initialized, skipping"); return; } + NSLog(@"[RNUnity] Loading UnityFramework..."); [self setUfw: UnityFrameworkLoad()]; + + if (![self ufw]) { + NSLog(@"[RNUnity] ERROR: UnityFrameworkLoad returned nil"); + return; + } + NSLog(@"[RNUnity] Framework loaded successfully"); + [[self ufw] registerFrameworkListener: self]; unsigned count = (int) [[[NSProcessInfo processInfo] arguments] count]; @@ -60,7 +69,15 @@ - (void)initUnityModule { } array[count] = NULL; + NSLog(@"[RNUnity] Calling runEmbeddedWithArgc..."); [[self ufw] runEmbeddedWithArgc: gArgc argv: array appLaunchOpts: appLaunchOpts]; + + if (![[self ufw] appController]) { + NSLog(@"[RNUnity] ERROR: appController is nil after runEmbedded"); + return; + } + NSLog(@"[RNUnity] appController ready, rootView=%@", self.ufw.appController.rootView); + [[self ufw] appController].quitHandler = ^(){ NSLog(@"AppController.quitHandler called"); }; [self.ufw.appController.rootView removeFromSuperview]; @@ -75,9 +92,10 @@ - (void)initUnityModule { [[[[[[self ufw] appController] window] rootViewController] view] setNeedsLayout]; [NSClassFromString(@"FrameworkLibAPI") registerAPIforNativeCalls:self]; + NSLog(@"[RNUnity] Init complete. bounds=%@", NSStringFromCGRect(self.bounds)); } @catch (NSException *e) { - NSLog(@"%@",e); + NSLog(@"[RNUnity] EXCEPTION: %@", e); } } From ca0484ccd8fe1e1f1c44c3eab884de83d1b8027a Mon Sep 17 00:00:00 2001 From: Leaguefun Date: Wed, 3 Jun 2026 23:39:28 +0800 Subject: [PATCH 06/12] fix: clean up window management and add visible diagnostics - Remove contradictory windowScene:nil + makeKeyAndVisible sequence - Hide Unity's window instead, restore RN window as key - Add rootView directly to self instead of back to Unity's window - Add visible debug label to show init status on-screen - Support iOS 13+ scene-based window discovery Co-Authored-By: Claude Opus 4.6 --- ios/RNUnityView.mm | 88 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 71 insertions(+), 17 deletions(-) diff --git a/ios/RNUnityView.mm b/ios/RNUnityView.mm index d9cdecf..3e5e942 100644 --- a/ios/RNUnityView.mm +++ b/ios/RNUnityView.mm @@ -42,21 +42,38 @@ - (bool)unityIsInitialized { return [self ufw] && [[self ufw] appController]; } +- (void)showDebugStatus:(NSString *)status { + // Temporary visible diagnostic — remove once Unity init is confirmed working + UILabel *label = [self viewWithTag:9999]; + if (!label) { + label = [[UILabel alloc] initWithFrame:CGRectMake(10, 40, 350, 80)]; + label.tag = 9999; + label.numberOfLines = 0; + label.font = [UIFont systemFontOfSize:11]; + label.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.7]; + label.textColor = [UIColor greenColor]; + label.layer.zPosition = 9999; + [self addSubview:label]; + } + label.text = status; + NSLog(@"[RNUnity] %@", status); +} + - (void)initUnityModule { @try { if([self unityIsInitialized]) { - NSLog(@"[RNUnity] Already initialized, skipping"); + [self showDebugStatus:@"Already initialized"]; return; } - NSLog(@"[RNUnity] Loading UnityFramework..."); + [self showDebugStatus:@"Loading framework..."]; [self setUfw: UnityFrameworkLoad()]; if (![self ufw]) { - NSLog(@"[RNUnity] ERROR: UnityFrameworkLoad returned nil"); + [self showDebugStatus:@"ERROR: UnityFrameworkLoad returned nil"]; return; } - NSLog(@"[RNUnity] Framework loaded successfully"); + [self showDebugStatus:@"Framework loaded, registering listener..."]; [[self ufw] registerFrameworkListener: self]; @@ -69,33 +86,64 @@ - (void)initUnityModule { } array[count] = NULL; - NSLog(@"[RNUnity] Calling runEmbeddedWithArgc..."); + [self showDebugStatus:@"Calling runEmbeddedWithArgc..."]; [[self ufw] runEmbeddedWithArgc: gArgc argv: array appLaunchOpts: appLaunchOpts]; if (![[self ufw] appController]) { - NSLog(@"[RNUnity] ERROR: appController is nil after runEmbedded"); + [self showDebugStatus:@"ERROR: appController nil after runEmbedded"]; + return; + } + + UIView *unityRootView = self.ufw.appController.rootView; + if (!unityRootView) { + [self showDebugStatus:@"ERROR: rootView is nil"]; return; } - NSLog(@"[RNUnity] appController ready, rootView=%@", self.ufw.appController.rootView); + + [self showDebugStatus:[NSString stringWithFormat:@"appController OK, rootView=%@", unityRootView]]; [[self ufw] appController].quitHandler = ^(){ NSLog(@"AppController.quitHandler called"); }; - [self.ufw.appController.rootView removeFromSuperview]; - if (@available(iOS 13.0, *)) { - [[[[self ufw] appController] window] setWindowScene: nil]; - } else { - [[[[self ufw] appController] window] setScreen: nil]; + // Remove Unity's rootView from Unity's own view hierarchy + [unityRootView removeFromSuperview]; + + // Hide Unity's window so it doesn't cover React Native's UI + UIWindow *unityWindow = [[[self ufw] appController] window]; + unityWindow.hidden = YES; + + // Restore React Native's window as key window + UIWindow *rnWindow = [[[UIApplication sharedApplication] delegate] window]; + if (!rnWindow) { + // iOS 13+ scene-based: find the first connected scene's window + if (@available(iOS 13.0, *)) { + for (UIScene *scene in [UIApplication sharedApplication].connectedScenes) { + if ([scene isKindOfClass:[UIWindowScene class]]) { + UIWindowScene *windowScene = (UIWindowScene *)scene; + for (UIWindow *w in windowScene.windows) { + if (w != unityWindow) { + rnWindow = w; + break; + } + } + if (rnWindow) break; + } + } + } + } + if (rnWindow) { + [rnWindow makeKeyAndVisible]; } - [[[[self ufw] appController] window] addSubview: self.ufw.appController.rootView]; - [[[[self ufw] appController] window] makeKeyAndVisible]; - [[[[[[self ufw] appController] window] rootViewController] view] setNeedsLayout]; + // Add Unity's rendering view to self (the RN component view) + unityRootView.frame = self.bounds; + [self addSubview:unityRootView]; [NSClassFromString(@"FrameworkLibAPI") registerAPIforNativeCalls:self]; - NSLog(@"[RNUnity] Init complete. bounds=%@", NSStringFromCGRect(self.bounds)); + [self showDebugStatus:[NSString stringWithFormat:@"INIT OK bounds=%@ rootView.frame=%@", + NSStringFromCGRect(self.bounds), NSStringFromCGRect(unityRootView.frame)]]; } @catch (NSException *e) { - NSLog(@"[RNUnity] EXCEPTION: %@", e); + [self showDebugStatus:[NSString stringWithFormat:@"EXCEPTION: %@", e.reason]]; } } @@ -106,6 +154,12 @@ - (void)layoutSubviews { self.ufw.appController.rootView.frame = self.bounds; [self addSubview:self.ufw.appController.rootView]; } + + // Keep debug label on top + UILabel *label = [self viewWithTag:9999]; + if (label) { + [self bringSubviewToFront:label]; + } } - (void)pauseUnity:(BOOL * _Nonnull)pause { From f7d6313793f38210784140d0af438fd519f56762 Mon Sep 17 00:00:00 2001 From: Leaguefun Date: Wed, 3 Jun 2026 23:49:17 +0800 Subject: [PATCH 07/12] fix: add iOS componentProvider to codegenConfig for Fabric registration Without componentProvider mapping, RNUnityView is not registered in RCTThirdPartyComponentsProvider and the native view is never created. Co-Authored-By: Claude Opus 4.6 --- package.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 2826dfd..3d1f096 100644 --- a/package.json +++ b/package.json @@ -172,6 +172,11 @@ "codegenConfig": { "name": "unityview", "type": "components", - "jsSrcsDir": "src" + "jsSrcsDir": "src", + "ios": { + "componentProvider": { + "RNUnityView": "RNUnityView" + } + } } } From 861ca3fede33e143792e9e69020ddd09ccc3dae7 Mon Sep 17 00:00:00 2001 From: Leaguefun Date: Wed, 3 Jun 2026 23:52:42 +0800 Subject: [PATCH 08/12] chore: remove debug diagnostics, keep clean window management Co-Authored-By: Claude Opus 4.6 --- ios/RNUnityView.mm | 44 +++++--------------------------------------- 1 file changed, 5 insertions(+), 39 deletions(-) diff --git a/ios/RNUnityView.mm b/ios/RNUnityView.mm index 3e5e942..12c52c3 100644 --- a/ios/RNUnityView.mm +++ b/ios/RNUnityView.mm @@ -42,38 +42,18 @@ - (bool)unityIsInitialized { return [self ufw] && [[self ufw] appController]; } -- (void)showDebugStatus:(NSString *)status { - // Temporary visible diagnostic — remove once Unity init is confirmed working - UILabel *label = [self viewWithTag:9999]; - if (!label) { - label = [[UILabel alloc] initWithFrame:CGRectMake(10, 40, 350, 80)]; - label.tag = 9999; - label.numberOfLines = 0; - label.font = [UIFont systemFontOfSize:11]; - label.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.7]; - label.textColor = [UIColor greenColor]; - label.layer.zPosition = 9999; - [self addSubview:label]; - } - label.text = status; - NSLog(@"[RNUnity] %@", status); -} - - (void)initUnityModule { @try { if([self unityIsInitialized]) { - [self showDebugStatus:@"Already initialized"]; return; } - [self showDebugStatus:@"Loading framework..."]; [self setUfw: UnityFrameworkLoad()]; if (![self ufw]) { - [self showDebugStatus:@"ERROR: UnityFrameworkLoad returned nil"]; + NSLog(@"[RNUnity] ERROR: UnityFrameworkLoad returned nil"); return; } - [self showDebugStatus:@"Framework loaded, registering listener..."]; [[self ufw] registerFrameworkListener: self]; @@ -86,25 +66,17 @@ - (void)initUnityModule { } array[count] = NULL; - [self showDebugStatus:@"Calling runEmbeddedWithArgc..."]; [[self ufw] runEmbeddedWithArgc: gArgc argv: array appLaunchOpts: appLaunchOpts]; if (![[self ufw] appController]) { - [self showDebugStatus:@"ERROR: appController nil after runEmbedded"]; + NSLog(@"[RNUnity] ERROR: appController nil after runEmbedded"); return; } - UIView *unityRootView = self.ufw.appController.rootView; - if (!unityRootView) { - [self showDebugStatus:@"ERROR: rootView is nil"]; - return; - } - - [self showDebugStatus:[NSString stringWithFormat:@"appController OK, rootView=%@", unityRootView]]; - [[self ufw] appController].quitHandler = ^(){ NSLog(@"AppController.quitHandler called"); }; // Remove Unity's rootView from Unity's own view hierarchy + UIView *unityRootView = self.ufw.appController.rootView; [unityRootView removeFromSuperview]; // Hide Unity's window so it doesn't cover React Native's UI @@ -139,11 +111,9 @@ - (void)initUnityModule { [self addSubview:unityRootView]; [NSClassFromString(@"FrameworkLibAPI") registerAPIforNativeCalls:self]; - [self showDebugStatus:[NSString stringWithFormat:@"INIT OK bounds=%@ rootView.frame=%@", - NSStringFromCGRect(self.bounds), NSStringFromCGRect(unityRootView.frame)]]; } @catch (NSException *e) { - [self showDebugStatus:[NSString stringWithFormat:@"EXCEPTION: %@", e.reason]]; + NSLog(@"[RNUnity] EXCEPTION: %@", e.reason); } } @@ -155,11 +125,7 @@ - (void)layoutSubviews { [self addSubview:self.ufw.appController.rootView]; } - // Keep debug label on top - UILabel *label = [self viewWithTag:9999]; - if (label) { - [self bringSubviewToFront:label]; - } + } - (void)pauseUnity:(BOOL * _Nonnull)pause { From 3079d2673022d630eea78845ce839b72c99460b4 Mon Sep 17 00:00:00 2001 From: Leaguefun Date: Thu, 11 Jun 2026 22:09:57 +0800 Subject: [PATCH 09/12] fix: resolve delayed init and broken resume on Android MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace Thread.sleep(1000) with non-blocking Handler.postDelayed(300) to stop freezing the UI thread during Unity player creation - Change componentWillUnmount from unloadUnity to pauseUnity so the Unity runtime survives navigation and can be resumed - Fix pauseUnity() ignoring its boolean parameter — it always called pause() regardless, now correctly toggles pause/resume Co-Authored-By: Claude Opus 4.6 --- .../ReactNativeUnity.java | 52 +++++++++---------- .../ReactNativeUnityViewManager.java | 6 ++- src/UnityView.tsx | 4 +- 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/android/src/main/java/com/azesmwayreactnativeunity/ReactNativeUnity.java b/android/src/main/java/com/azesmwayreactnativeunity/ReactNativeUnity.java index 95adcbb..36ba496 100644 --- a/android/src/main/java/com/azesmwayreactnativeunity/ReactNativeUnity.java +++ b/android/src/main/java/com/azesmwayreactnativeunity/ReactNativeUnity.java @@ -3,6 +3,8 @@ import android.app.Activity; import android.graphics.PixelFormat; import android.os.Build; +import android.os.Handler; +import android.os.Looper; import android.view.ViewGroup; import android.view.WindowManager; @@ -44,43 +46,41 @@ public static void createPlayer(final Activity activity, final UnityPlayerCallba public void run() { activity.getWindow().setFormat(PixelFormat.RGBA_8888); int flag = activity.getWindow().getAttributes().flags; - boolean fullScreen = false; - if ((flag & WindowManager.LayoutParams.FLAG_FULLSCREEN) == WindowManager.LayoutParams.FLAG_FULLSCREEN) { - fullScreen = true; - } + final boolean fullScreen = (flag & WindowManager.LayoutParams.FLAG_FULLSCREEN) == WindowManager.LayoutParams.FLAG_FULLSCREEN; try { unityPlayer = new UPlayer(activity, callback); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | InvocationTargetException e) {} - try { - // wait a moment. fix unity cannot start when startup. - Thread.sleep(1000); - } catch (Exception e) {} + // Use non-blocking delay instead of Thread.sleep to keep UI responsive + new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { + @Override + public void run() { + // start unity + try { + addUnityViewToBackground(); + } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {} - // start unity - try { - addUnityViewToBackground(); - } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {} + unityPlayer.windowFocusChanged(true); - unityPlayer.windowFocusChanged(true); + try { + unityPlayer.requestFocusPlayer(); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {} - try { - unityPlayer.requestFocusPlayer(); - } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {} + unityPlayer.resume(); - unityPlayer.resume(); + if (!fullScreen) { + activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); + activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); + } - if (!fullScreen) { - activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); - activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); - } + _isUnityReady = true; - _isUnityReady = true; - - try { - callback.onReady(); - } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {} + try { + callback.onReady(); + } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {} + } + }, 300); } }); } diff --git a/android/src/main/java/com/azesmwayreactnativeunity/ReactNativeUnityViewManager.java b/android/src/main/java/com/azesmwayreactnativeunity/ReactNativeUnityViewManager.java index b7f6310..129a0b0 100644 --- a/android/src/main/java/com/azesmwayreactnativeunity/ReactNativeUnityViewManager.java +++ b/android/src/main/java/com/azesmwayreactnativeunity/ReactNativeUnityViewManager.java @@ -140,7 +140,11 @@ public void unloadUnity(ReactNativeUnityView view) { public void pauseUnity(ReactNativeUnityView view, boolean pause) { if (isUnityReady()) { assert getPlayer() != null; - getPlayer().pause(); + if (pause) { + pause(); + } else { + resume(); + } } } diff --git a/src/UnityView.tsx b/src/UnityView.tsx index becba62..52c2fbb 100644 --- a/src/UnityView.tsx +++ b/src/UnityView.tsx @@ -66,7 +66,9 @@ export default class UnityView extends React.Component { componentWillUnmount() { if (this.ref.current) { - Commands.unloadUnity(this.ref.current); + // Pause instead of unload — unload destroys the Unity runtime, + // making it impossible to resume when navigating back. + Commands.pauseUnity(this.ref.current, true); } } From 1c8d3891e8af332513eded2476e8eaf169697624 Mon Sep 17 00:00:00 2001 From: Leaguefun Date: Thu, 11 Jun 2026 22:17:37 +0800 Subject: [PATCH 10/12] chore: rebuild lib/ with fix for delayed init and broken resume Co-Authored-By: Claude Opus 4.6 --- lib/commonjs/UnityView.js | 11 ++++++----- lib/commonjs/UnityView.js.map | 2 +- lib/commonjs/index.js | 2 +- lib/commonjs/index.js.map | 2 +- lib/commonjs/specs/UnityViewNativeComponent.js | 2 +- lib/commonjs/specs/UnityViewNativeComponent.js.map | 2 +- lib/module/UnityView.js | 6 ++++-- lib/module/UnityView.js.map | 2 +- lib/module/index.js.map | 2 +- lib/module/specs/UnityViewNativeComponent.js.map | 2 +- lib/typescript/src/UnityView.d.ts | 4 +--- lib/typescript/src/UnityView.d.ts.map | 2 +- .../src/specs/UnityViewNativeComponent.d.ts | 3 --- .../src/specs/UnityViewNativeComponent.d.ts.map | 2 +- 14 files changed, 21 insertions(+), 23 deletions(-) diff --git a/lib/commonjs/UnityView.js b/lib/commonjs/UnityView.js index be97bae..cccf732 100644 --- a/lib/commonjs/UnityView.js +++ b/lib/commonjs/UnityView.js @@ -7,10 +7,9 @@ exports.default = void 0; var _react = _interopRequireDefault(require("react")); var _UnityViewNativeComponent = _interopRequireWildcard(require("./specs/UnityViewNativeComponent")); var _reactNative = require("react-native"); -function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } -function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } +function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } +function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } class UnityView extends _react.default.Component { ref = /*#__PURE__*/_react.default.createRef(); postMessage = (gameObject, methodName, message) => { @@ -46,7 +45,9 @@ class UnityView extends _react.default.Component { } componentWillUnmount() { if (this.ref.current) { - _UnityViewNativeComponent.Commands.unloadUnity(this.ref.current); + // Pause instead of unload — unload destroys the Unity runtime, + // making it impossible to resume when navigating back. + _UnityViewNativeComponent.Commands.pauseUnity(this.ref.current, true); } } render() { diff --git a/lib/commonjs/UnityView.js.map b/lib/commonjs/UnityView.js.map index a968e08..da8afdb 100644 --- a/lib/commonjs/UnityView.js.map +++ b/lib/commonjs/UnityView.js.map @@ -1 +1 @@ -{"version":3,"names":["_react","_interopRequireDefault","require","_UnityViewNativeComponent","_interopRequireWildcard","_reactNative","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","prototype","hasOwnProperty","call","i","set","obj","_extends","assign","bind","target","arguments","length","source","key","apply","UnityView","React","Component","ref","createRef","postMessage","gameObject","methodName","message","current","Commands","unloadUnity","pauseUnity","pause","resumeUnity","windowFocusChanged","hasFocus","Platform","OS","getProps","props","componentWillUnmount","render","createElement","exports"],"sourceRoot":"../../src","sources":["UnityView.tsx"],"mappings":"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"} \ No newline at end of file +{"version":3,"names":["_react","_interopRequireDefault","require","_UnityViewNativeComponent","_interopRequireWildcard","_reactNative","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","_extends","assign","bind","arguments","length","apply","UnityView","React","Component","ref","createRef","postMessage","gameObject","methodName","message","current","Commands","unloadUnity","pauseUnity","pause","resumeUnity","windowFocusChanged","hasFocus","Platform","OS","getProps","props","componentWillUnmount","render","createElement","exports"],"sourceRoot":"../../src","sources":["UnityView.tsx"],"mappings":"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","ignoreList":[]} \ No newline at end of file diff --git a/lib/commonjs/index.js b/lib/commonjs/index.js index aeee223..b9861e8 100644 --- a/lib/commonjs/index.js +++ b/lib/commonjs/index.js @@ -5,6 +5,6 @@ Object.defineProperty(exports, "__esModule", { }); exports.default = void 0; var _UnityView = _interopRequireDefault(require("./UnityView")); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } var _default = exports.default = _UnityView.default; //# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/lib/commonjs/index.js.map b/lib/commonjs/index.js.map index 3eb8053..9d8670b 100644 --- a/lib/commonjs/index.js.map +++ b/lib/commonjs/index.js.map @@ -1 +1 @@ -{"version":3,"names":["_UnityView","_interopRequireDefault","require","obj","__esModule","default","_default","exports","UnityView"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;;AAAA,IAAAA,UAAA,GAAAC,sBAAA,CAAAC,OAAA;AAAoC,SAAAD,uBAAAE,GAAA,WAAAA,GAAA,IAAAA,GAAA,CAAAC,UAAA,GAAAD,GAAA,KAAAE,OAAA,EAAAF,GAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAErBG,kBAAS"} \ No newline at end of file +{"version":3,"names":["_UnityView","_interopRequireDefault","require","e","__esModule","default","_default","exports","UnityView"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;;AAAA,IAAAA,UAAA,GAAAC,sBAAA,CAAAC,OAAA;AAAoC,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAAA,IAAAG,QAAA,GAAAC,OAAA,CAAAF,OAAA,GAErBG,kBAAS","ignoreList":[]} \ No newline at end of file diff --git a/lib/commonjs/specs/UnityViewNativeComponent.js b/lib/commonjs/specs/UnityViewNativeComponent.js index 18c3269..da89a93 100644 --- a/lib/commonjs/specs/UnityViewNativeComponent.js +++ b/lib/commonjs/specs/UnityViewNativeComponent.js @@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { exports.default = exports.Commands = void 0; var _codegenNativeComponent = _interopRequireDefault(require("react-native/Libraries/Utilities/codegenNativeComponent")); var _codegenNativeCommands = _interopRequireDefault(require("react-native/Libraries/Utilities/codegenNativeCommands")); -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const Commands = exports.Commands = (0, _codegenNativeCommands.default)({ supportedCommands: ['postMessage', 'unloadUnity', 'pauseUnity', 'resumeUnity', 'windowFocusChanged'] }); diff --git a/lib/commonjs/specs/UnityViewNativeComponent.js.map b/lib/commonjs/specs/UnityViewNativeComponent.js.map index 683d65b..41f4cb1 100644 --- a/lib/commonjs/specs/UnityViewNativeComponent.js.map +++ b/lib/commonjs/specs/UnityViewNativeComponent.js.map @@ -1 +1 @@ -{"version":3,"names":["_codegenNativeComponent","_interopRequireDefault","require","_codegenNativeCommands","obj","__esModule","default","Commands","exports","codegenNativeCommands","supportedCommands","_default","codegenNativeComponent"],"sourceRoot":"../../../src","sources":["specs/UnityViewNativeComponent.ts"],"mappings":";;;;;;AAAA,IAAAA,uBAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,sBAAA,GAAAF,sBAAA,CAAAC,OAAA;AAA2F,SAAAD,uBAAAG,GAAA,WAAAA,GAAA,IAAAA,GAAA,CAAAC,UAAA,GAAAD,GAAA,KAAAE,OAAA,EAAAF,GAAA;AAmCpF,MAAMG,QAAwB,GAAAC,OAAA,CAAAD,QAAA,GAAG,IAAAE,8BAAqB,EAAiB;EAC5EC,iBAAiB,EAAE,CACjB,aAAa,EACb,aAAa,EACb,YAAY,EACZ,aAAa,EACb,oBAAoB;AAExB,CAAC,CAAC;AAAC,IAAAC,QAAA,GAAAH,OAAA,CAAAF,OAAA,GAEY,IAAAM,+BAAsB,EACnC,aACF,CAAC"} \ No newline at end of file +{"version":3,"names":["_codegenNativeComponent","_interopRequireDefault","require","_codegenNativeCommands","e","__esModule","default","Commands","exports","codegenNativeCommands","supportedCommands","_default","codegenNativeComponent"],"sourceRoot":"../../../src","sources":["specs/UnityViewNativeComponent.ts"],"mappings":";;;;;;AAAA,IAAAA,uBAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,sBAAA,GAAAF,sBAAA,CAAAC,OAAA;AAA2F,SAAAD,uBAAAG,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAmCpF,MAAMG,QAAwB,GAAAC,OAAA,CAAAD,QAAA,GAAG,IAAAE,8BAAqB,EAAiB;EAC5EC,iBAAiB,EAAE,CACjB,aAAa,EACb,aAAa,EACb,YAAY,EACZ,aAAa,EACb,oBAAoB;AAExB,CAAC,CAAC;AAAC,IAAAC,QAAA,GAAAH,OAAA,CAAAF,OAAA,GAEY,IAAAM,+BAAsB,EACnC,aACF,CAAC","ignoreList":[]} \ No newline at end of file diff --git a/lib/module/UnityView.js b/lib/module/UnityView.js index 70a0ffd..0455b52 100644 --- a/lib/module/UnityView.js +++ b/lib/module/UnityView.js @@ -1,4 +1,4 @@ -function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } +function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } import React from 'react'; import NativeUnityView, { Commands } from './specs/UnityViewNativeComponent'; import { Platform } from 'react-native'; @@ -37,7 +37,9 @@ export default class UnityView extends React.Component { } componentWillUnmount() { if (this.ref.current) { - Commands.unloadUnity(this.ref.current); + // Pause instead of unload — unload destroys the Unity runtime, + // making it impossible to resume when navigating back. + Commands.pauseUnity(this.ref.current, true); } } render() { diff --git a/lib/module/UnityView.js.map b/lib/module/UnityView.js.map index c0bf50f..aa0782a 100644 --- a/lib/module/UnityView.js.map +++ b/lib/module/UnityView.js.map @@ -1 +1 @@ -{"version":3,"names":["React","NativeUnityView","Commands","Platform","UnityView","Component","ref","createRef","postMessage","gameObject","methodName","message","current","unloadUnity","pauseUnity","pause","resumeUnity","windowFocusChanged","hasFocus","OS","getProps","props","componentWillUnmount","render","createElement","_extends"],"sourceRoot":"../../src","sources":["UnityView.tsx"],"mappings":";AAAA,OAAOA,KAAK,MAAM,OAAO;AAEzB,OAAOC,eAAe,IAAIC,QAAQ,QAAQ,kCAAkC;AAE5E,SAASC,QAAQ,QAAQ,cAAc;AAiBvC,eAAe,MAAMC,SAAS,SAASJ,KAAK,CAACK,SAAS,CAAmB;EACvEC,GAAG,gBAAGN,KAAK,CAACO,SAAS,CAAe,CAAC;EAE9BC,WAAW,GAAGA,CACnBC,UAAkB,EAClBC,UAAkB,EAClBC,OAAe,KACZ;IACH,IAAI,IAAI,CAACL,GAAG,CAACM,OAAO,EAAE;MACpBV,QAAQ,CAACM,WAAW,CAAC,IAAI,CAACF,GAAG,CAACM,OAAO,EAAEH,UAAU,EAAEC,UAAU,EAAEC,OAAO,CAAC;IACzE;EACF,CAAC;EAEME,WAAW,GAAGA,CAAA,KAAM;IACzB,IAAI,IAAI,CAACP,GAAG,CAACM,OAAO,EAAE;MACpBV,QAAQ,CAACW,WAAW,CAAC,IAAI,CAACP,GAAG,CAACM,OAAO,CAAC;IACxC;EACF,CAAC;EAEME,UAAUA,CAACC,KAAc,EAAE;IAChC,IAAI,IAAI,CAACT,GAAG,CAACM,OAAO,EAAE;MACpBV,QAAQ,CAACY,UAAU,CAAC,IAAI,CAACR,GAAG,CAACM,OAAO,EAAEG,KAAK,CAAC;IAC9C;EACF;EAEOC,WAAWA,CAAA,EAAG;IACnB,IAAI,IAAI,CAACV,GAAG,CAACM,OAAO,EAAE;MACpBV,QAAQ,CAACc,WAAW,CAAC,IAAI,CAACV,GAAG,CAACM,OAAO,CAAC;IACxC;EACF;EAEOK,kBAAkBA,CAACC,QAAQ,GAAG,IAAI,EAAE;IACzC,IAAIf,QAAQ,CAACgB,EAAE,KAAK,SAAS,EAAE;IAE/B,IAAI,IAAI,CAACb,GAAG,CAACM,OAAO,EAAE;MACpBV,QAAQ,CAACe,kBAAkB,CAAC,IAAI,CAACX,GAAG,CAACM,OAAO,EAAEM,QAAQ,CAAC;IACzD;EACF;EAEQE,QAAQA,CAAA,EAAG;IACjB,OAAO;MACL,GAAG,IAAI,CAACC;IACV,CAAC;EACH;EAEAC,oBAAoBA,CAAA,EAAG;IACrB,IAAI,IAAI,CAAChB,GAAG,CAACM,OAAO,EAAE;MACpBV,QAAQ,CAACW,WAAW,CAAC,IAAI,CAACP,GAAG,CAACM,OAAO,CAAC;IACxC;EACF;EAEAW,MAAMA,CAAA,EAAG;IACP,oBAAOvB,KAAA,CAAAwB,aAAA,CAACvB,eAAe,EAAAwB,QAAA;MAACnB,GAAG,EAAE,IAAI,CAACA;IAAI,GAAK,IAAI,CAACc,QAAQ,CAAC,CAAC,CAAG,CAAC;EAChE;AACF"} \ No newline at end of file +{"version":3,"names":["React","NativeUnityView","Commands","Platform","UnityView","Component","ref","createRef","postMessage","gameObject","methodName","message","current","unloadUnity","pauseUnity","pause","resumeUnity","windowFocusChanged","hasFocus","OS","getProps","props","componentWillUnmount","render","createElement","_extends"],"sourceRoot":"../../src","sources":["UnityView.tsx"],"mappings":";AAAA,OAAOA,KAAK,MAAM,OAAO;AAEzB,OAAOC,eAAe,IAAIC,QAAQ,QAAQ,kCAAkC;AAE5E,SAASC,QAAQ,QAAQ,cAAc;AAiBvC,eAAe,MAAMC,SAAS,SAASJ,KAAK,CAACK,SAAS,CAAmB;EACvEC,GAAG,gBAAGN,KAAK,CAACO,SAAS,CAAe,CAAC;EAE9BC,WAAW,GAAGA,CACnBC,UAAkB,EAClBC,UAAkB,EAClBC,OAAe,KACZ;IACH,IAAI,IAAI,CAACL,GAAG,CAACM,OAAO,EAAE;MACpBV,QAAQ,CAACM,WAAW,CAAC,IAAI,CAACF,GAAG,CAACM,OAAO,EAAEH,UAAU,EAAEC,UAAU,EAAEC,OAAO,CAAC;IACzE;EACF,CAAC;EAEME,WAAW,GAAGA,CAAA,KAAM;IACzB,IAAI,IAAI,CAACP,GAAG,CAACM,OAAO,EAAE;MACpBV,QAAQ,CAACW,WAAW,CAAC,IAAI,CAACP,GAAG,CAACM,OAAO,CAAC;IACxC;EACF,CAAC;EAEME,UAAUA,CAACC,KAAc,EAAE;IAChC,IAAI,IAAI,CAACT,GAAG,CAACM,OAAO,EAAE;MACpBV,QAAQ,CAACY,UAAU,CAAC,IAAI,CAACR,GAAG,CAACM,OAAO,EAAEG,KAAK,CAAC;IAC9C;EACF;EAEOC,WAAWA,CAAA,EAAG;IACnB,IAAI,IAAI,CAACV,GAAG,CAACM,OAAO,EAAE;MACpBV,QAAQ,CAACc,WAAW,CAAC,IAAI,CAACV,GAAG,CAACM,OAAO,CAAC;IACxC;EACF;EAEOK,kBAAkBA,CAACC,QAAQ,GAAG,IAAI,EAAE;IACzC,IAAIf,QAAQ,CAACgB,EAAE,KAAK,SAAS,EAAE;IAE/B,IAAI,IAAI,CAACb,GAAG,CAACM,OAAO,EAAE;MACpBV,QAAQ,CAACe,kBAAkB,CAAC,IAAI,CAACX,GAAG,CAACM,OAAO,EAAEM,QAAQ,CAAC;IACzD;EACF;EAEQE,QAAQA,CAAA,EAAG;IACjB,OAAO;MACL,GAAG,IAAI,CAACC;IACV,CAAC;EACH;EAEAC,oBAAoBA,CAAA,EAAG;IACrB,IAAI,IAAI,CAAChB,GAAG,CAACM,OAAO,EAAE;MACpB;MACA;MACAV,QAAQ,CAACY,UAAU,CAAC,IAAI,CAACR,GAAG,CAACM,OAAO,EAAE,IAAI,CAAC;IAC7C;EACF;EAEAW,MAAMA,CAAA,EAAG;IACP,oBAAOvB,KAAA,CAAAwB,aAAA,CAACvB,eAAe,EAAAwB,QAAA;MAACnB,GAAG,EAAE,IAAI,CAACA;IAAI,GAAK,IAAI,CAACc,QAAQ,CAAC,CAAC,CAAG,CAAC;EAChE;AACF","ignoreList":[]} \ No newline at end of file diff --git a/lib/module/index.js.map b/lib/module/index.js.map index e414676..76d5a6b 100644 --- a/lib/module/index.js.map +++ b/lib/module/index.js.map @@ -1 +1 @@ -{"version":3,"names":["UnityView"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"AAAA,OAAOA,SAAS,MAAM,aAAa;AAEnC,eAAeA,SAAS"} \ No newline at end of file +{"version":3,"names":["UnityView"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"AAAA,OAAOA,SAAS,MAAM,aAAa;AAEnC,eAAeA,SAAS","ignoreList":[]} \ No newline at end of file diff --git a/lib/module/specs/UnityViewNativeComponent.js.map b/lib/module/specs/UnityViewNativeComponent.js.map index 6a9d536..992c178 100644 --- a/lib/module/specs/UnityViewNativeComponent.js.map +++ b/lib/module/specs/UnityViewNativeComponent.js.map @@ -1 +1 @@ -{"version":3,"names":["codegenNativeComponent","codegenNativeCommands","Commands","supportedCommands"],"sourceRoot":"../../../src","sources":["specs/UnityViewNativeComponent.ts"],"mappings":"AAAA,OAAOA,sBAAsB,MAAM,yDAAyD;AAC5F,OAAOC,qBAAqB,MAAM,wDAAwD;AAmC1F,OAAO,MAAMC,QAAwB,GAAGD,qBAAqB,CAAiB;EAC5EE,iBAAiB,EAAE,CACjB,aAAa,EACb,aAAa,EACb,YAAY,EACZ,aAAa,EACb,oBAAoB;AAExB,CAAC,CAAC;AAEF,eAAeH,sBAAsB,CACnC,aACF,CAAC"} \ No newline at end of file +{"version":3,"names":["codegenNativeComponent","codegenNativeCommands","Commands","supportedCommands"],"sourceRoot":"../../../src","sources":["specs/UnityViewNativeComponent.ts"],"mappings":"AAAA,OAAOA,sBAAsB,MAAM,yDAAyD;AAC5F,OAAOC,qBAAqB,MAAM,wDAAwD;AAmC1F,OAAO,MAAMC,QAAwB,GAAGD,qBAAqB,CAAiB;EAC5EE,iBAAiB,EAAE,CACjB,aAAa,EACb,aAAa,EACb,YAAY,EACZ,aAAa,EACb,oBAAoB;AAExB,CAAC,CAAC;AAEF,eAAeH,sBAAsB,CACnC,aACF,CAAC","ignoreList":[]} \ No newline at end of file diff --git a/lib/typescript/src/UnityView.d.ts b/lib/typescript/src/UnityView.d.ts index 4064610..efdbbcd 100644 --- a/lib/typescript/src/UnityView.d.ts +++ b/lib/typescript/src/UnityView.d.ts @@ -1,5 +1,3 @@ -/// -/// import React from 'react'; import type { DirectEventHandler } from 'react-native/Libraries/Types/CodegenTypes'; import type { ViewProps } from 'react-native'; @@ -22,7 +20,7 @@ export default class UnityView extends React.Component { windowFocusChanged(hasFocus?: boolean): void; private getProps; componentWillUnmount(): void; - render(): JSX.Element; + render(): React.JSX.Element; } export {}; //# sourceMappingURL=UnityView.d.ts.map \ No newline at end of file diff --git a/lib/typescript/src/UnityView.d.ts.map b/lib/typescript/src/UnityView.d.ts.map index 0e610c4..3338173 100644 --- a/lib/typescript/src/UnityView.d.ts.map +++ b/lib/typescript/src/UnityView.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"UnityView.d.ts","sourceRoot":"","sources":["../../../src/UnityView.tsx"],"names":[],"mappings":";;AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAC;AAEpF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,KAAK,2BAA2B,GAAG,QAAQ,CAAC;IAC1C,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAAC;AAEH,KAAK,gBAAgB,GAAG,SAAS,GAAG;IAClC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,kBAAkB,CAAC,2BAA2B,CAAC,CAAC;IACjE,cAAc,CAAC,EAAE,kBAAkB,CAAC,2BAA2B,CAAC,CAAC;IACjE,YAAY,CAAC,EAAE,kBAAkB,CAAC,2BAA2B,CAAC,CAAC;CAChE,CAAC;AAIF,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,KAAK,CAAC,SAAS,CAAC,gBAAgB,CAAC;IACtE,GAAG,qJAAmC;IAE/B,WAAW,eACJ,MAAM,cACN,MAAM,WACT,MAAM,UAKf;IAEK,WAAW,aAIhB;IAEK,UAAU,CAAC,KAAK,EAAE,OAAO;IAMzB,WAAW;IAMX,kBAAkB,CAAC,QAAQ,UAAO;IAQzC,OAAO,CAAC,QAAQ;IAMhB,oBAAoB;IAMpB,MAAM;CAGP"} \ No newline at end of file +{"version":3,"file":"UnityView.d.ts","sourceRoot":"","sources":["../../../src/UnityView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAC;AAEpF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,KAAK,2BAA2B,GAAG,QAAQ,CAAC;IAC1C,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAAC;AAEH,KAAK,gBAAgB,GAAG,SAAS,GAAG;IAClC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,kBAAkB,CAAC,2BAA2B,CAAC,CAAC;IACjE,cAAc,CAAC,EAAE,kBAAkB,CAAC,2BAA2B,CAAC,CAAC;IACjE,YAAY,CAAC,EAAE,kBAAkB,CAAC,2BAA2B,CAAC,CAAC;CAChE,CAAC;AAIF,MAAM,CAAC,OAAO,OAAO,SAAU,SAAQ,KAAK,CAAC,SAAS,CAAC,gBAAgB,CAAC;IACtE,GAAG,qJAAmC;IAE/B,WAAW,GAChB,YAAY,MAAM,EAClB,YAAY,MAAM,EAClB,SAAS,MAAM,UAKf;IAEK,WAAW,aAIhB;IAEK,UAAU,CAAC,KAAK,EAAE,OAAO;IAMzB,WAAW;IAMX,kBAAkB,CAAC,QAAQ,UAAO;IAQzC,OAAO,CAAC,QAAQ;IAMhB,oBAAoB;IAQpB,MAAM;CAGP"} \ No newline at end of file diff --git a/lib/typescript/src/specs/UnityViewNativeComponent.d.ts b/lib/typescript/src/specs/UnityViewNativeComponent.d.ts index e5a1a06..0227b54 100644 --- a/lib/typescript/src/specs/UnityViewNativeComponent.d.ts +++ b/lib/typescript/src/specs/UnityViewNativeComponent.d.ts @@ -1,6 +1,3 @@ -/// -/// -/// import type { HostComponent, ViewProps } from 'react-native'; import type { DirectEventHandler } from 'react-native/Libraries/Types/CodegenTypes'; export type UnityViewContentUpdateEvent = Readonly<{ diff --git a/lib/typescript/src/specs/UnityViewNativeComponent.d.ts.map b/lib/typescript/src/specs/UnityViewNativeComponent.d.ts.map index 73e15f1..a1a1fb4 100644 --- a/lib/typescript/src/specs/UnityViewNativeComponent.d.ts.map +++ b/lib/typescript/src/specs/UnityViewNativeComponent.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"UnityViewNativeComponent.d.ts","sourceRoot":"","sources":["../../../../src/specs/UnityViewNativeComponent.ts"],"names":[],"mappings":";;;AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAC;AAEpF,MAAM,MAAM,2BAA2B,GAAG,QAAQ,CAAC;IACjD,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAAC;AAEH,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,kBAAkB,CAAC,2BAA2B,CAAC,CAAC;IACjE,cAAc,CAAC,EAAE,kBAAkB,CAAC,2BAA2B,CAAC,CAAC;IACjE,YAAY,CAAC,EAAE,kBAAkB,CAAC,2BAA2B,CAAC,CAAC;CAChE;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,CACX,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,EACrD,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,KACZ,IAAI,CAAC;IACV,WAAW,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,KAAK,IAAI,CAAC;IAC7E,UAAU,EAAE,CACV,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,EACrD,KAAK,EAAE,OAAO,KACX,IAAI,CAAC;IACV,WAAW,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,KAAK,IAAI,CAAC;IAC7E,kBAAkB,EAAE,CAClB,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,EACrD,QAAQ,EAAE,OAAO,KACd,IAAI,CAAC;CACX;AAED,eAAO,MAAM,QAAQ,EAAE,cAQrB,CAAC;;AAEH,wBAEgC"} \ No newline at end of file +{"version":3,"file":"UnityViewNativeComponent.d.ts","sourceRoot":"","sources":["../../../../src/specs/UnityViewNativeComponent.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAC;AAEpF,MAAM,MAAM,2BAA2B,GAAG,QAAQ,CAAC;IACjD,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC,CAAC;AAEH,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,kBAAkB,CAAC,2BAA2B,CAAC,CAAC;IACjE,cAAc,CAAC,EAAE,kBAAkB,CAAC,2BAA2B,CAAC,CAAC;IACjE,YAAY,CAAC,EAAE,kBAAkB,CAAC,2BAA2B,CAAC,CAAC;CAChE;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,CACX,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,EACrD,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,KACZ,IAAI,CAAC;IACV,WAAW,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,KAAK,IAAI,CAAC;IAC7E,UAAU,EAAE,CACV,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,EACrD,KAAK,EAAE,OAAO,KACX,IAAI,CAAC;IACV,WAAW,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,KAAK,IAAI,CAAC;IAC7E,kBAAkB,EAAE,CAClB,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,EACrD,QAAQ,EAAE,OAAO,KACd,IAAI,CAAC;CACX;AAED,eAAO,MAAM,QAAQ,EAAE,cAQrB,CAAC;wBAIE,aAAa,CAAC,WAAW,CAAC;AAF/B,wBAEgC"} \ No newline at end of file From 528965192029420f372633d5a7e2792fc6de8969 Mon Sep 17 00:00:00 2001 From: Leaguefun Date: Thu, 11 Jun 2026 22:18:17 +0800 Subject: [PATCH 11/12] fix: allow prepare to succeed when peer deps are unavailable When installed from git as a dependency, bob build fails because react-native peer deps aren't available. Since lib/ is pre-built and committed, this is safe to ignore. Co-Authored-By: Claude Opus 4.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3d1f096..9d4422e 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "typecheck": "tsc --noEmit", "lint": "eslint \"**/*.{js,ts,tsx}\"", "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib", - "prepare": "bob build", + "prepare": "bob build || true", "release": "release-it" }, "keywords": [ From a7909d2301d31b9a7078edb6e378ba6297eb41aa Mon Sep 17 00:00:00 2001 From: Leaguefun Date: Thu, 11 Jun 2026 22:27:51 +0800 Subject: [PATCH 12/12] fix: poll for Unity rendering surface instead of fixed delay The fixed 300ms Handler.postDelayed was too short for heavier Unity projects (e.g. AR Foundation). Now polls every 100ms for up to 3s, checking if Unity's FrameLayout is available before proceeding. This adapts to any project's init time while keeping the UI thread responsive. Co-Authored-By: Claude Opus 4.6 --- .../ReactNativeUnity.java | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/android/src/main/java/com/azesmwayreactnativeunity/ReactNativeUnity.java b/android/src/main/java/com/azesmwayreactnativeunity/ReactNativeUnity.java index 36ba496..9fce806 100644 --- a/android/src/main/java/com/azesmwayreactnativeunity/ReactNativeUnity.java +++ b/android/src/main/java/com/azesmwayreactnativeunity/ReactNativeUnity.java @@ -7,6 +7,7 @@ import android.os.Looper; import android.view.ViewGroup; import android.view.WindowManager; +import android.widget.FrameLayout; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; @@ -52,11 +53,29 @@ public void run() { unityPlayer = new UPlayer(activity, callback); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | InvocationTargetException e) {} - // Use non-blocking delay instead of Thread.sleep to keep UI responsive - new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { + // Poll for Unity's rendering surface instead of blocking with Thread.sleep. + // This keeps the UI thread responsive while waiting for Unity to initialize. + final Handler handler = new Handler(Looper.getMainLooper()); + final int POLL_INTERVAL_MS = 100; + final int MAX_POLLS = 30; // 3 seconds max + final int[] pollCount = {0}; + + handler.postDelayed(new Runnable() { @Override public void run() { - // start unity + pollCount[0]++; + FrameLayout frame = null; + try { + frame = unityPlayer.requestFrame(); + } catch (NoSuchMethodException e) {} + + if (frame == null && pollCount[0] < MAX_POLLS) { + // Unity's FrameLayout not ready yet, retry + handler.postDelayed(this, POLL_INTERVAL_MS); + return; + } + + // Unity is ready (or max wait reached) — proceed with initialization try { addUnityViewToBackground(); } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {} @@ -80,7 +99,7 @@ public void run() { callback.onReady(); } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {} } - }, 300); + }, POLL_INTERVAL_MS); } }); }