使用Vuforia创建PokémonGO风格增强现实游戏:第2部分

您将要创造的

我们已经开始开发名为Shoot the Cubes的增强现实游戏。 现在是时候通过增加互动和增加体验来改进游戏了。 我们将主要关注Unity给我们带来的可能性,而忽略Vuforia的细节。 并非必须具有Unity引擎的经验。

1.使立方体看起来活着

让我们开始游戏吧。 到目前为止,我们已经成功创建了一个可以与用户设备一起移动的增强现实场景。 我们将通过使多维数据集生成并在周围飞行,并让玩家使用激光射击搜索并销毁它们来改进此应用程序。

产生元素

我们已经根据设备摄像机的旋转设置了_SpawnController的初始位置。 现在,我们将在此点附近建立一个区域,在该区域将生成多维数据集。 现在,我们将更新SpawnScript以使_SpawnController实例化相对于_SpawnController具有不同大小和随机位置的多维数据集元素。

让我们编辑SpawnScript类,添加一些变量来控制生成过程。

public class SpawnScript : MonoBehaviour {
    // Cube element to spawn
    public GameObject mCubeObj;
    
    // Qtd of Cubes to be Spawned
    public int mTotalCubes      = 10;

    // Time to spawn the Cubes
    public float mTimeToSpawn	= 1f;

    // hold all cubes on stage
    private GameObject[] mCubes;

    // define if position was set
    private bool mPositionSet;
}

我们将创建一个名为SpawnLoop的协同程序来管理生成过程。 游戏开始时,还将负责设置_SpawnController的初始位置。 注意, Random.insideUnitSphere方法使多维数据集在_SpawnManager周围的球形区域内的随机位置处实例化。

public class SpawnScript : MonoBehaviour {
    
    // Loop Spawning cube elements
    private IEnumerator SpawnLoop() 
	{
		// Defining the Spawning Position
		StartCoroutine( ChangePosition() );

		yield return new WaitForSeconds(0.2f);

		// Spawning the elements
		int i = 0;
		while ( i <= (mTotalCubes-1) ) {

			mCubes[i] = SpawnElement();
			i++;
			yield return new WaitForSeconds(Random.Range(mTimeToSpawn, mTimeToSpawn*3));
		}
	}

	// Spawn a cube
	private GameObject SpawnElement() 
	{
		// spawn the element on a random position, inside a imaginary sphere
		GameObject cube = Instantiate(mCubeObj, (Random.insideUnitSphere*4) + transform.position, transform.rotation ) as GameObject;
		// define a random scale for the cube
		float scale = Random.Range(0.5f, 2f);
		// change the cube scale
		cube.transform.localScale = new Vector3( scale, scale, scale );
		return cube;
	}
}

最后,编辑Start()函数。 确保删除StartCoroutine( ChangePosition() ); 行并替换为启动SpawnLoop协程的调用。

public class SpawnScript : MonoBehaviour {
    void Start () {
	    // Initializing spawning loop
	    StartCoroutine( SpawnLoop() );

	    // Initialize Cubes array according to
	    // the desired quantity
	    mCubes = new GameObject[ mTotalCubes ];
    }
}

现在回到Unity,您必须创建一个多维数据集预制模块,以通过脚本实例化。

  • 在“ 项目”窗口中创建一个名为Prefabs的文件夹。
  • 将所有轴上的多维数据集元素比例更改为1,并将所有轴上的旋转比例更改为0
  • 多维数据集 拖到Prefabs文件夹。
  • 从“ 层次结构”窗口中删除多维数据集。
  • 选择_SpawnController并将Cube预制件从Prefabs文件夹拖到位于检查器SpawnScript区域中的M Cube Obj字段。



最后,删除位于_SpawnManager里面的

现在,如果您在Unity中按play并在设备上运行项目,则应该看到生成了多维数据集。

旋转立方体

我们需要向这些立方体添加运动以使事情变得更加有趣。 让我们绕立方体的轴旋转并越过ARCamera 。 在立方体运动上添加一些随机因素以创建更自然的感觉也是很酷的。

将“ 多维数据集预制”从“预制”文件夹拖到层次结构中。

  • 在“ 脚本”文件夹中,创建一个名为CubeBehaviorScript的新C#脚本
  • 将脚本拖到Cube预制件上并打开以进行编辑。

每个立方体将具有随机特征。 大小,旋转速度和旋转方向将使用先前定义的一些参考随机定义。 让我们创建一些控制器变量并初始化多维数据集的状态。

using UnityEngine;
using System.Collections;

public class CubeBehaviorScript : MonoBehaviour {
    // Cube's Max/Min scale
    public float mScaleMax  = 2f;
    public float mScaleMin  = 0.5f;

    // Orbit max Speed
    public float mOrbitMaxSpeed = 30f;

    // Orbit speed
    private float mOrbitSpeed;

    // Anchor point for the Cube to rotate around
    private Transform mOrbitAnchor;

    // Orbit direction
    private Vector3 mOrbitDirection;

    // Max Cube Scale
    private Vector3 mCubeMaxScale;
    
    // Growing Speed
    public float mGrowingSpeed	= 10f;
    private bool mIsCubeScaled	= false;

    void Start () {
        CubeSettings();
    }

    // Set initial cube settings
    private void CubeSettings(){
        // defining the anchor point as the main camera
        mOrbitAnchor = Camera.main.transform;

        // defining the orbit direction
        float x = Random.Range(-1f,1f);
        float y = Random.Range(-1f,1f);
        float z = Random.Range(-1f,1f);
        mOrbitDirection = new Vector3( x, y , z );

        // defining speed
        mOrbitSpeed = Random.Range( 5f, mOrbitMaxSpeed );

        // defining scale
        float scale = Random.Range(mScaleMin, mScaleMax);
        mCubeMaxScale = new Vector3( scale, scale, scale );

        // set cube scale to 0, to grow it lates
        transform.localScale = Vector3.zero;
    }
}

现在是时候向立方体添加一些运动了。 让我们使用之前定义的随机速度和方向使其围绕自身和ARCamera旋转。

// Update is called once per frame
    void Update () {
		// makes the cube orbit and rotate
		RotateCube();
	}
    
    // Makes the cube rotate around a anchor point
    // and rotate around its own axis
	private void RotateCube(){
		// rotate cube around camera
		transform.RotateAround(
			mOrbitAnchor.position, mOrbitDirection, mOrbitSpeed * Time.deltaTime);

		// rotating around its axis
		transform.Rotate( mOrbitDirection * 30 * Time.deltaTime);
	}

为了使其更加有机,在生成多维数据集之后,多维数据集将从零开始放大。

// Update is called once per frame
    void Update () {
		// makes the cube orbit and rotate
		RotateCube();

		// scale cube if needed
		if ( !mIsCubeScaled )
			ScaleObj();
	}
    
    // Scale object from 0 to 1
    private void ScaleObj(){

		// growing obj
		if ( transform.localScale != mCubeMaxScale )
			transform.localScale = Vector3.Lerp( transform.localScale, mCubeMaxScale, Time.deltaTime * mGrowingSpeed );
		else
			mIsCubeScaled = true;
	}

2.搜索和销毁

那些立方体像那样飞来飞去太高兴了。 我们必须用激光摧毁它们! 让我们在游戏中制造一把枪,然后开始射击。

射击激光

激光束必须连接到ARCamera及其旋转。 每次播放器“敲击”设备屏幕时,都会发射激光。 我们将使用Physics.Raycast类来检查激光是否击中目标,如果是,我们将从中移除一些生命值。

  • 创建一个名为_PlayerController一个新的空对象和另一个叫它_LaserController内空的对象。
  • Scripts文件夹内添加一个名为LaserScriptC#脚本 ,并将其拖到_LaserController

LaserScript内部,我们将使用LineRenderer通过连接到ARCamera底部的原点显示激光 。 为了获得激光的起点(虚拟枪的枪管),我们Transform在发射激光时将相机Transform为“ Transform ”并将其向下移动10个单位。

首先,让我们创建一些变量来控制激光设置并获取mLaserLine

using UnityEngine;
using System.Collections;

public class LaserScript : MonoBehaviour {

    public float mFireRate  = .5f;
    public float mFireRange = 50f;
    public float mHitForce  = 100f;
    public int mLaserDamage = 100;

    // Line render that will represent the Laser
    private LineRenderer mLaserLine;

    // Define if laser line is showing
    private bool mLaserLineEnabled;

    // Time that the Laser lines shows on screen
    private WaitForSeconds mLaserDuration = new WaitForSeconds(0.05f);

    // time of the until the next fire
    private float mNextFire;
    
    // Use this for initialization
    void Start () {
		// getting the Line Renderer
		mLaserLine = GetComponent<LineRenderer>();
	}
}

负责射击的函数是Fire() 。 每当玩家按下击键时,就会调用该命令。 请注意,正在使用Camera.main.transform来获取ARCamera的位置和旋转,并且将激光器放置在其下方10个单位处。 这会将激光定位在相机的底部。

// Shot the Laser
    private void Fire(){
        // Get ARCamera Transform
		Transform cam = Camera.main.transform;

		// Define the time of the next fire
		mNextFire = Time.time + mFireRate;

		// Set the origin of the RayCast
		Vector3 rayOrigin = cam.position;

		// Set the origin position of the Laser Line
		// It will always 10 units down from the ARCamera
		// We adopted this logic for simplicity
		mLaserLine.SetPosition(0, transform.up * -10f );
}

为了检查目标是否被击中,我们将使用Raycast

// Shot the Laser
    private void Fire(){
        // Hold the Hit information
    	RaycastHit hit;

		// Checks if the RayCast hit something
		if ( Physics.Raycast( rayOrigin, cam.forward, out hit, mFireRange )){

			// Set the end of the Laser Line to the object hit
			mLaserLine.SetPosition(1, hit.point );

		} else {
			// Set the enfo of the laser line to be forward the camera
			// using the Laser range
			mLaserLine.SetPosition(1, cam.forward * mFireRange );
		}
}

最后,是时候检查射击按钮是否按下并在射击时调用激光效果了。

// Update is called once per frame
void Update () {
    if ( Input.GetButton("Fire1") && Time.time > mNextFire ){
        Fire();
        }    
    }

private void Fire() {
    // anterior code supressed for simplicity
    
    // Show the Laser using a Coroutine
    StartCoroutine(LaserFx());
}

// Show the Laser Effects
private IEnumerator LaserFx(){
    mLaserLine.enabled = true;

    // Way for a specific time to remove the LineRenderer
    yield return mLaserDuration;
    mLaserLine.enabled = false;
}

回到Unity,我们需要向_LaserController对象添加LineRenderer组件。

  • 选择_LaserController,然后在“ 检查器”窗口中,单击“ 添加组件” 。 将其命名为“ Line Renderer ”,然后选择新组件。
  • 创建一个名为Materials的新文件夹,并在其中创建一个名为Laser的新材料。
  • 选择激光材料并将其更改为所需的任何颜色。
  • 选择_LaserController并将Laser材质拖动到LineRenderer组件的Materials字段。
  • 仍在LineRenderer中 ,在“ 参数”下将“ 开始1”和“ 结束0”

如果现在测试游戏,您应该会从屏幕底部看到一束激光。 随意用激光声音效果_LaserController添加的AudioSource组件香料它。

击中立方体

我们的激光器需要击中目标,对其造成伤害并最终破坏立方体。 我们需要向立方体添加一个RigidBody ,对其施加力和损坏。

  • Cube预制件从prefabs文件夹中拖到舞台上的任何位置。
  • 选择 多维数据集,然后选择添加组件   检查器窗口。 将新组件命名为“ RigidBody ”并选择它。
  • 关于RigidBody分量集的重力运动
  • 将这些更改应用于预制件。

现在,让我们编辑CubeBehavior脚本,以创建一个函数,该函数负责对多维数据集施加损害,而另一个函数则在运行状况低于0时销毁该多维数据集。

public class CubeBehaviorScript : MonoBehaviour {
    // Cube Health
    public int mCubeHealth	= 100;
    
    // Define if the Cube is Alive
    private bool mIsAlive    	= true;
    
    // Cube got Hit
    // return 'false' when cube was destroyed
    public bool Hit( int hitDamage ){
		mCubeHealth -= hitDamage;
		if ( mCubeHealth >= 0 && mIsAlive ) {
			StartCoroutine( DestroyCube());
			return true;
		}
		return false;
	}

	// Destroy Cube
	private IEnumerator DestroyCube(){
		mIsAlive = false;

        // Make the cube desappear
		GetComponent<Renderer>().enabled = false;

        // we'll wait some time before destroying the element
        // this is usefull when using some kind of effect
        // like a explosion sound effect.
        // in that case we could use the sound lenght as waiting time
		yield return new WaitForSeconds(0.5f);
		Destroy(gameObject);
	}
}

好的,魔方现在可以受到伤害并被摧毁。 让我们编辑LaserScript以对立方体施加伤害。 我们要做的就是更改Fire()函数以调用CubeBehavior脚本的Hit方法。

public class LaserScript : MonoBehaviour {
    
    // Shot the Laser
    private void Fire(){
		// code supressed for simplicity ...

		// Checks if the RayCast hit something
		if ( Physics.Raycast( rayOrigin, cam.forward, out hit, mFireRange )){

			// Set the end of the Laser Line to the object hitted
			mLaserLine.SetPosition(1, hit.point );

			// Get the CubeBehavior script to apply damage to target
            CubeBehaviorScript cubeCtr = hit.collider.GetComponent<CubeBehaviorScript>();
			if ( cubeCtr != null ) {
				if ( hit.rigidbody != null ) {
                    // apply force to the target
					hit.rigidbody.AddForce(-hit.normal*mHitForce);
                    // apply damage the target
					cubeCtr.Hit( mLaserDamage );
				}
			}
	}
}

3.结论

恭喜你! 我们的增强现实游戏结束了! 是的,游戏可能会更加精致,但是基础知识已经存在,整体体验非常吸引人。 为了使它更有趣,您可以像在视频中一样添加粒子爆炸,此外,还可以添加计分系统或带有计时器的波动系统,使其更具挑战性。 下一步由您决定!

下一步是什么?

我们在Unity上使用Vuforia创建了一个有趣的AR实验,但是我们仍然要涵盖很多很酷的功能。 我们没有看到任何更复杂的Vuforia资源:目标,智能地形,云等。 请继续关注下一个教程,在本文中,我们将始终使用相同的逐步方法来介绍更多这些功能。

再见!

翻译自: https://code.tutsplus.com/tutorials/pokemon-go-style-augmented-reality-with-vuforia-part-2--cms-27232

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值