Development of unity3d openvr virtual reality bowling brick game

Time:2022-4-1

It is said that brother Shui bought a valve index device. Since this device is so expensive, I feel sorry for this device if I don’t develop some interesting games. This paper will start to develop a bowling brick game with little playability and strong appreciation in the future. This is just an entry-level game. The amount of code and production steps are super small, which is suitable for entry

Before starting, please refer to the environment construction and some necessary knowledge blogs provided by Shuige

Before reading this article, I hope you have some knowledge of unity3d development. This article will not mention much about the introduction of unity3d. If you don’t understand anything, please turn to the introduction of unity3d by yourself

The way to play this game is to pick up the bowling ball with both hands, smash down a wall and push the brick down the floor. The effect video is as follows

Writing code is like moving bricks. Let’s use it firstUnity openvr virtual reality introduction II: the simplest virtual reality game / programBuild the content of a sample in the steamvr SDK and start building the wall

Remember to add a rigid body to each brick in the above wall and set the mass to 0.2 at the same time, otherwise we can’t break the brick

Next, let’s create a bowling ball bullet, create a prefabs folder as agreed, and create a ball called bullet in it

As shown in the figure above, add a rigid body to the bullet and set a relatively large mass. As shown in the figure above, the quality is 10, so as to hit the brick under the floor. Please don’t add rigid body to the floor. The default rigid body is gravity. Just after debugging, I found that the floor fell off. This is not a horror game

Let’s write some code to create a bowling bullet when pulling the trigger

How to get the current trigger status in steamvr game? In fact, according toUnity3d openvr steamvr input actionAs suggested by the blog, I don’t develop code to get the current trigger state. What we need to develop is to define an action, such as the action of interacetui, and obtain the value of this action to determine the logic. The advantage of this is that it is convenient for users to configure and support other different interactive devices. If a device does not have a trigger, but the device has another button, which can also achieve this effect, the user can bind a new button

We are still in the wild era of VR application or game development, and many interactions are in the exploratory stage. In order to better adapt to new hardware and interactions in the future, it is more adaptable to define action names instead of binding specific hardware devices

Let’s create a c# script file called shotwithrotation and put it in the scripts folder according to international practice

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Valve.VR;
using Valve.VR.InteractionSystem;

public class PlayerDemoScript : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

Let’s add a field according toUnity3d openvr steamvr input actionFor the content of the blog, I need a bool value to get whether the current trigger is pressed. In steamvr, Boolean is usedSteamVR_Action_BooleanType representation. Get the value through the state attribute. The code is as follows

public SteamVR_Action_Boolean Shooting;

The code to get whether the trigger is pressed is as follows

if (Shooting.state)
            {
                Shoot();
            }

Through state, you can get whether the current trigger is pressed or not. The shot method of the above code is the actual shooting code. This part of the code is written below. Go back to the definition of the shooting field. Because my main business is WPF development, according to my coding habits, the field will not be exposed and starts with an underscore, but this conflicts with the coding specification of unity3d, so I regard the field as an attribute, and the first character is capitalized

For the shooting field defined in the above code, if you want to obtain the interaction itself, you need to carry out binding interaction in unity3d. For the method of binding interaction, please refer toUnity openvr virtual reality entry 6: control the player’s movement through the rockerThe content of this article. The general approach is to attach the script to a game object first. If we attach this script to the player object, then click the drop-down of shooting and select interaction

I choose the action of interacetui, which is the interaction of pulling the trigger in steamvr by default. Of course, users can also set it to other keys by themselves

At this time, I recommend that if you have not done steamvr interaction before, please try to add unity3d debugging in visual studio and get the value of shooting field in update method to understand this part of interaction

As shown in the figure above, we bind the shooting field to the interaction UI action

The bullet field and shot speed field in the figure above will be defined as follows

public GameObject Bullet;
    public SteamVR_Action_Boolean Shooting;

    public float Speed = 5;

    public float ShootSpeed = 2;

The bullet of the above code is the template of bowling bullet, which is used to create bowling bullet, and shotspeed is the firing frequency. In VR application, if you create bullets without judging the frequency in update, the bullet creation speed will be super fast due to super high refresh. The code here only uses an intuitive and fast method to judge the frequency

The following code can be used to limit the speed of sending bullets

public GameObject Bullet;
    public SteamVR_Action_Boolean Shooting;

    public float Speed = 5;

    public float ShootSpeed = 2;

    private float _shootTime = 0;
    private float _shootTimerInterval = 0;

    void Start()
    {
        _shootTimerInterval = 1 / ShootSpeed;
    }

    void Update()
    {
        _shootTime += Time.deltaTime;
        if(_shootTime> _shootTimerInterval)
        {
            _shootTime -= _shootTimerInterval;
            if (Shooting.state)
            {
                Shoot();
            }
        }
    }

The following is the preparation of shot code. I have prepared several versions, which have been tested by brother Shui. That is, the interaction of the version that does not comment out the code is the best (although the playability is also particularly bad). Therefore, let’s write the logic of this version in the future

Through GameObject The instance method creates a bullet, and then places the bullet next to it

private void Shoot()
    {
        var sphere = GameObject.Instantiate(Bullet);

        sphere.transform.Translate(new Vector3(0, 0.25f, 0.1f));
    }

Because our player and floor do not have the function of adding transmission, when setting the player at the origin, just put the bullet at (0,0.25,0.1). The reason why y is 0.25 is that the size of the just hit ball is 0.5, and the midpoint of the coordinate is the center of the ball, which can be just placed on the floor through half of the ball. The setting of 0.1 in the Z direction can make the ball just in front

At this time, bind the bullet field in unity to the bullet in prefbabs set above. Run. Through the logic of rigid body, you can use both hands to pick up the ball and start playing

Next is an interactive way to be killed. This interactive way is to pull the trigger and shoot in the direction of the front

When creating a bullet, set the rotation direction of the bullet to be the same as that of the current HMD (head mounted display), and then set the speed direction to the front of the object. The code is as follows

private void Shoot()
    {
        var sphere = GameObject.Instantiate(Bullet);

        sphere.transform.Translate(new Vector3(0, 0.25f, 0.1f));

        //Towards the direction seen by the user
        sphere.transform.rotation = Player.instance.hmdTransform.transform.rotation;

        var rigidbody = sphere.GetComponent();

        rigidbody.velocity = sphere.transform.forward * Speed;
    }

The following is the full code of shotwithrotation

using System;
using System.Collections;
using System.Collections.Generic;

using UnityEngine;

using Valve.VR;
using Valve.VR.InteractionSystem;

public class ShootWithRotation : MonoBehaviour
{
    public GameObject Bullet;
    public SteamVR_Action_Boolean Shooting;

    public float Speed = 5;

    public float ShootSpeed = 2;

    private float _shootTime = 0;
    private float _shootTimerInterval = 0;

    // Start is called before the first frame update
    void Start()
    {
        _shootTimerInterval = 1 / ShootSpeed;
    }

    // Update is called once per frame
    void Update()
    {
        _shootTime += Time.deltaTime;
        if(_shootTime> _shootTimerInterval)
        {
            _shootTime -= _shootTimerInterval;
            if (Shooting.state)
            {
                Shoot();
            }
        }
    }

    private void Shoot()
    {
        var sphere = GameObject.Instantiate(Bullet);

        //sphere.transform.Translate(Player.instance.hmdTransform.position);
        sphere.transform.Translate(new Vector3(0, 0.25f, 0.1f));

        //Towards the direction seen by the user
        sphere.transform.rotation = Player.instance.hmdTransform.transform.rotation;

        var rigidbody = sphere.GetComponent();

        //rigidbody.velocity = sphere.transform.forward * Speed;

        ////Rotary emission
        //var rotation = Player.transform.eulerAngles.y;
        //var vx = 1 * Mathf.Cos(rotation);
        //var vy = -1 * Mathf.Sin(rotation);
        //rigidbody.velocity = new Vector3(vx, 0, vy) * Speed;
        //Destroy(sphere, 5);
    }
}

At present, Shuige has also developed an interactive way through grasping, which looks more fun. The implementation method is to add an interactive script to the bullet, which is brought into the steamvr SDK. When adding this script, you need to give its activateactionsetonattach field\actions\defaultinteractive

Add a throwable script to the bullet so that the ball can be thrown away

The current game can catch the ball and throw it out

The development of this game is not difficult, but there is a lot of knowledge to understand, and a little Federer. After debugging for several hours, I looked at the picture of the tool man Shuige test on the screen and felt like vomiting

Series blog

Recommended Today

Introduction to js decorator (introduction to ts decorator)

reference js decorator @Decorator Decorator – Ruan Yifeng TS Decorator(2): Metadata TS Documentation – Decorators hint TypeScript has fully implemented the decorator, and the js decorator is a syntax that is still in the proposal. If you use js instead of ts, you need to configure Babel to use it. The prerequisite knowledge you need […]