Andrew Lee
Andrew Lee

Reputation: 49

Is there a AR library that is available to use with Expo and React Native?

My friends and I are currently trying to make a Pokemon Go clone. The pieces of our game include a real time map where the player and the Pokemon spawn (done using React Native maps and Expo) and a Pokemon battle component. Our issue lies with the latter - we are trying to render a 3D Pokemon model onto the player’s camera (e.g. AR).

However, it seems like Expo’s native support for AR+3D models has been deprecated as of a few versions ago and other solutions that we looked into (e.g. Viro) don’t appear to be compatible with Expo (which we are heavily reliant on).

Has anyone recently tried to do something with AR plus React Native/Expo that would have any suggestions for tools/technologies that we could look into?

Upvotes: 4

Views: 3237

Answers (1)

Nate Vaughan
Nate Vaughan

Reputation: 3839

It can be done by using Viro React with a project that you expo eject. You can still use all your existing expo code, but you will be on an Expo Bare Workflow, not a Managed Workflow.

Here's a rough outline of the steps:

  • Run expo eject on your existing project (You can still use Expo Go to develop any views that do not use AR)
  • Run npx pod-install. You will need to re-run this command any time you add a library that has native modules.
  • Plug your iOS device in via USB and build your app using npx react-native run-ios --device to install your app (the process is similar for android devices). iOS and Android simulators do not support AR.
  • The above command will start Metro (which bundles and serves your JS assets) automatically and you should get a hot-reload similar to when you use Expo Go. If you ever stop metro, you can always re-start it with npx react-native start.

Congrats! You now have an Expo Bare Workflow. You should still be able to run expo start and open your app in Expo Go, and you should also have an installed development version of your app on your device.

Only once you have the above working should you attempt to add Viro React:

  • Run yarn add @viro-community/react-viro
  • Run npx pod-install (and remember to do this each time you add a new library with native modules)
  • Create a new AR view (and a link to navigate to it) in your existing app

Your "hello, world" view should look something like the following:

import React, { FC, useState } from "react";
import { StyleSheet, Text, View } from "react-native";
import {
  ViroARScene,
  ViroARSceneNavigator,
  ViroConstants,
  ViroFlexView,
  ViroImage,
} from '@viro-community/react-viro';

interface MyARViewProps {
  foo: string | undefined
}

const ARView: FC<MyARViewProps> = (
  props: MyARViewProps
) => {
  return (
      <View style={{flex: 1}}>
        <ViroARSceneNavigator
            autofocus={true}
            initialScene={{
              scene: HelloWorldSceneAR,
            }}
            style={styles.f1}
        />
        <View style={[styles.buttons]}>
          <View style={[styles.button]}>
            <Text style={[styles.buttonLabel]}>A button</Text>
          </View>
        </View>
      </View>
  );
};

export default ARView;

const HelloWorldSceneAR = () => {
  const [tracking, setTracking] = useState(false);

  function onInitialized(state, reason) {
    if (state === ViroConstants.TRACKING_NORMAL) {
      setTracking(true);
    } else if (state === ViroConstants.TRACKING_NONE) {
      setTracking(false)
    }
  }

  return (
    <ViroARScene onTrackingUpdated={onInitialized}>
      {tracking && (<ViroFlexView
          style={{flexDirection: 'row', padding: 0.1}}
          width={2.0}
          height={.4}
          position={[0, 0.25, -1]}
      >
        <ViroText text="hello, world" />
      </ViroFlexView>)}
    </ViroARScene>
  );
};

let styles = StyleSheet.create({
  container: {
    marginHorizontal: 10,
    alignItems: "center"
  },
  buttons: {
    height: 100,
    width: '100%',
    display: 'flex',
    flexDirection: 'row',
    justifyContent: 'center',
    position: 'absolute',
    bottom: 0,
    left: 0,
  },
  button: {
    height: 100,
    width: 100,
    borderRadius: 50,
    display: 'flex',
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#123456',
  },
  buttonLabel: {
    color: '#ffffff',
    fontSize: 16,
  },
  f1: {flex: 1},
  helloWorldTextStyle: {
    fontFamily: 'Arial',
    fontSize: 128,
    color: '#ffffff',
    textAlignVertical: 'center',
    textAlign: 'center',
  },
});

Upvotes: 1

Related Questions