CardBoard, VR by Google for Android, only $45

1677742--105118--cardboard.png

Someone make Unity support this, or maybe i can find someone who can

Here is the complete kit for $19.95

Durovis has a similar product called Dive which they are selling on their website now, and it has a free Android/iOS Unity plugin that is literally drag-and-drop simple. It’ll work with any mobile VR headset including Google Cardboard.

https://www.durovis.com/sdk.html

Thanks, almost bought one on eBay for like $50… Finding proper lenses was a horrible pain. Eventually found some online that ended up being around $15 including shipping. While waiting for the lenses, I popped the lenses out of some old binoculars (ended up not being the proper size). I do not regret buying the lenses anyway since they will hopefully ship faster than 4-6 weeks and I just cannot bear to wait that long. Maybe I will buy this cardboard kit anyway just to have an extra set, at least for the lenses (or maybe a family member).

1 Like

Cheers! I was thinking of using the oculus sdk but that will probably be just the ticket

I found a site in the uk selling plano-convex lenses at the right focal length for £2.90 each so hopefully they will do the job, bought 4

Thanks for the sdk info! I think, is perfect for Cardboard.

i also buy one from http://www.googlecardboard.com/ at a very reasonable price .

I’ve been stuck into making an android attempt for this using OpenDive’s sdk - it’s great fun! I wish my first effort at the headset wasnt so shabby though aha

Anyone have a reliable method for getting button-like input from the magnet slider on the side of the cardboard device?

The magnet needs to be right next to the phone. I had better luck sliding the magnet forward instead of down.

If not using Google’s SDK i’ve found getting the input a matter of reading the magnetometer (re. compass) changes between frames using the Unity api - the change in magnetic field is used to get an input (measure the ā€˜swing’) when the magnet is moved

So far i’m just tapping the phone with a magnet as i haven’t suitable magnets for Cardboard, but this is working as reliable input, you might want to write a little bit of code to visualise the changes to the raw magnetometer moving a nearby magnet makes, and basing the values for an input reading on that.

It goes without saying that any magnet alters this and quite a lot of things are magnetic

Thanks for the reply. The issue with reading from the compass is that its input also changes when you move the device for head-tracking purposes. I’m still working on a method to compare compass data to orientation from the gyro to find a discrepancy, but the fact that the raw input isn’t very intuitive (I suspect quaternions are the culprit) makes the math difficult.

So far my best attempt has been comparing the rate of change of the compass and gryo, and if the gyro doesn’t move but the compass does, register that as magnetic input. However, it has issues when the magnet is moved back and forth quickly since I’m only looking at the magnitude.

I like the idea of comparing the compass orientation to what it ā€œshouldā€ be to detect magnetic fields. I’m just having difficulty figuring out how to code that.

Side Note: Even if the performance is somewhat poor, does anyone know of any free shaders that replicate the fisheye distortion from the pro version? I need it for lens correction. Its literally the only pro feature I need and so I can’t justify shelling out for it.

Ahh yep, i just cached the initial value for the magnetic north and used this and the latest orientation based on that to factor in when a swing considerable enough happens to count as an input - getting the magnetic north on startup and the raw magnetometer reading is in the Input.compass api and the raw value is measured in microteslas, whatever they are, so aren’t relative to quaternions i don’t think?

http://docs.unity3d.com/ScriptReference/Compass.html

With GPS you can get a completely solid due north to base orientation on, to avoid issues with rapid switching of input I think I just lock the next input until the delta caused by the magnet is back below whatever threshold you set for a readable input. I can post my code if it helps, it may be lacking and I may be missing the point, but it’s been fine for exploring and manipulating the environment in a walk-em-up sense kind of pace, it does lack anything clever though, no averaging or using the gyroscope, works in the above circumstance however

Also, not free but affordable, I can supply you with the thing I made to get OR running on Unity Free that has the shader stuff needed but requires https://www.assetstore.unity3d.com/en/#!/content/11614 - it is very slow but might do what you need

Yes, can you please post the code? :slight_smile:

Here’s the code lifted verbatim, so it’s in a use case here… there’s really nothing to it, sorry if it’s a bit dim seeming, code’s not remotely my strong point, and wholly prototypical and I try to get others to do it if possible

using UnityEngine;
using System.Collections;

public class PlayerInteraction : MonoBehaviour
{

    public AIPath player;
    public float pushPower = 2.0F;
    public LayerMask walkable;
    public float interactDistance;
    public Camera rayCam;
    public GameObject reticle;
    public float reticleSpeed;
    public Color reticleClicked;
    public Color reticleInteractive;
    public Color reticleInteractiveNear;
    public Color reticleInteracting;
    public float magDirChange;
    public int inputDelayFrames;
    public GameObject interactLabel;
    private float previousMagneticNorth;
    private Color reticleStartCol;
    private int ticker;
    private bool interacting;
    private GameObject activeObject;
    private GameObject UIRoot;
    private RaycastHit hit;

    // Use this for initialization
    void Start()
    {
        Input.compass.enabled = true;
        previousMagneticNorth = Input.compass.magneticHeading;
        reticleStartCol = reticle.renderer.material.color;
        UIRoot = GameObject.FindGameObjectWithTag("UIRoot");
        interactLabel = Instantiate(interactLabel) as GameObject;
        interactLabel.transform.parent = UIRoot.transform;
        interactLabel.SetActive(false);
    }

    // Update is called once per frame
    void FixedUpdate()
    {
        if (interacting == false)
        {
            if (reticle.renderer.material.color != reticleStartCol) ticker++;
            if (ticker > inputDelayFrames) { reticle.renderer.material.color = reticleStartCol; ticker = 0; if (interactLabel.activeSelf == true) interactLabel.SetActive(false); }


            Ray ray = rayCam.ViewportPointToRay(new Vector3(0.5F, 0.5F, 0));

            if (Physics.Raycast(ray, out hit, walkable))
            {
                reticle.transform.position = Vector3.Lerp(reticle.transform.position, hit.point, Time.deltaTime * reticleSpeed);

                if (ticker == 0)
                {
                    if (hit.collider.gameObject.tag == "Interactive")
                    {
                        if ((hit.point - transform.position).sqrMagnitude < interactDistance * 2)
                        {
                            reticle.renderer.material.color = reticleInteractiveNear;
                        }
                        else
                        {
                            reticle.renderer.material.color = reticleInteractive;
                        }
                        interactLabel.SetActive(true);
                        interactLabel.transform.position = hit.point;
                        interactLabel.GetComponentInChildren<UILabel>().text = hit.collider.gameObject.GetComponent<Interaction>().tipName;
                    }
                }

                if (Mathf.Abs(Input.compass.magneticHeading - previousMagneticNorth) > 30.0f || Input.GetMouseButtonDown(0) == true)
                {
                    if (hit.collider.gameObject.tag == "Interactive" && (hit.point - transform.position).sqrMagnitude < interactDistance)
                    {
                        print((hit.point - transform.position).sqrMagnitude);
                        interacting = true;
                        interactLabel.SetActive(false);
                        reticle.renderer.material.color = reticleInteracting;
                        activeObject = hit.collider.gameObject;
                        activeObject.SendMessage("Interact");
                    }

                    if (hit.collider.gameObject.tag != "Interactive")
                    {
                        player.target.position = hit.point;
                        reticle.renderer.material.color = reticleClicked;
                    }
                    previousMagneticNorth = Input.compass.magneticHeading;
                }
            }
        }

        if (interacting == true)
        {
            if (activeObject.GetComponent<Interaction>().freezeReticule)
            {
                if (Mathf.Abs(Input.compass.magneticHeading - previousMagneticNorth) > 30.0f || Input.GetMouseButtonDown(0) == true)
                {
                    Ray ray = rayCam.ViewportPointToRay(new Vector3(0.5F, 0.5F, 0));

                    if (Physics.Raycast(ray, out hit, walkable))
                    {
                        if (hit.collider.gameObject.tag != "Interactive")
                        {
                            interacting = false;
                            activeObject.SendMessage("Deactivate");
                            activeObject = null;
                        }
                    }
                }
            }
            if (activeObject && !activeObject.GetComponent<Interaction>().activated)
            {
                interacting = false;
                activeObject = null;
            }
        }
    }

    void OnControllerColliderHit(ControllerColliderHit hit)
    {
        Rigidbody body = hit.collider.attachedRigidbody;
        if (body == null || body.isKinematic)
            return;

        if (hit.moveDirection.y < -0.3F)
            return;

        Vector3 pushDir = new Vector3(hit.moveDirection.x, 0, hit.moveDirection.z);
        body.velocity = pushDir * pushPower;
    }
}

The cardboards are sold at http://www.googlecardboard.com .

Today I published my game ā€œCardboard Catapultā€ on Google Play.
It is the first android game with full support for the Google Cardboard, including the magnet-button. Have fun!

Download on Google Play: https://play.google.com/store/apps/details?id=com.schoendevelopment.cardboardcatapult

Hey just downloaded your game its super fun!