Unity入门:第二个游戏

跟着教程做了一个space shooter:

【CSDN怎么传不了图了???!!!】

1、背景图

就是用一个quad,给这个quad添加一个material,material有texture。

2、导入Player模型

直接拖进hierarchy,然后添加粒子系统。

3、控制Player移动

PlayerController.cs:

	void FixedUpdate()
	{
		float moveHorizontal = Input.GetAxis ("Horizontal");
		float moveVertical = Input.GetAxis ("Vertical");
		Vector3 movement=new Vector3 (moveHorizontal,0.0f,moveVertical);
		rb.velocity = movement*speed;

		rb.position = new Vector3 
		(
			Mathf.Clamp(rb.position.x,boundary.xMin,boundary.xMax),
			0.0f,
			Mathf.Clamp(rb.position.z,boundary.zMin,boundary.zMax)
		);
		rb.rotation = Quaternion.Euler (0.0f,0.0f,rb.velocity.x*(-tilt));
	}

比较简单,用InputManager即可。speed是一个public变量,可以在Unity Editor里设置。为了让飞船不移出边界,用Clamp设置它的position属性。最后的rotation设置飞船旋转,这里涉及四元数和欧拉角,简单来说,四元数可以用来表示一个旋转,例如q=(a,b,c,d),其中a=cos(θ/2), b=xsin(θ/2), c=ysin(θ/2), d=zsin(θ/2),表示绕轴(x,y,z)、旋转角为θ的一个旋转。欧拉角同样可以表示旋转,旋转的规则是:首先绕着世界坐标系旋转α,然后绕着自身的坐标系x轴旋转β,最后绕着自身的坐标系z轴旋转γ。

4、子弹

新建一个空的GameObject,新建一个Quad作为它的孩子,用一个有贴图的material关联上去,当作子弹。注意渲染方式是Particles/Additive(这样黑色就被剔除掉了,因为黑色的rgb都是0,addtive表示叠加,0和任何东西叠加都是那个东西本身)

用下面的脚本让子弹动起来:

public class Mover : MonoBehaviour {
	private Rigidbody rb;
	public float speed;
	void Start()
	{
		rb = GetComponent<Rigidbody> ();
		rb.velocity = transform.forward * speed;
	}
}

注意:forward的方向就是z的方向。

记得把子弹放到Prefabs里!Prefab放的是我们要在游戏场景中反复使用的东西。

(为什么要用一个GameObject来作为Quad的parent???如果直接用Quad也可以得到子弹啊???)

too simple

5、关联飞船和子弹

PlayerController:

	void Update()
	{
		if (Input.GetButton ("Fire1") && Time.time > nextFire)
		{
			nextFire = Time.time + fireRate;
			//GameObject clone=
			Instantiate (shot, shotSpawn.position, shotSpawn.rotation);//as GameObject;
			audio.Play();
		}
	}
这里有点难度了。在Player下面新建一个GameObject:ShotSpawn,但是要注意脚本里的ShotSpawn是一个Transform(为了简化,其实申明成GameObject也可以,但是这样还是要去访问它的transform,所以不如直接用transform)。

Fire1是在InputManager里定义过的,默认是鼠标左键点击。

注意脚本里的几个时间:Time.time,nextfire(初始化为0),和fireRate,Time.time获取从游戏开始到现在的时间,如果按下了鼠标并且当前时间比下一次开火的时间大,就更新nextFire,让它比Time.time略大,这样的效果就是连续按下鼠标不会出现“连弹”。

另一个值得注意的地方是Instantiate()函数,因为这里的子弹只要实例化出来就可以了,所以不需要用注释里的clone来引用它(但是如果我们确实要用一个引用来管理这个实例,在实例化的时候应该在后面加上as GameObject告诉Unity把它实例化成一个GameObject)。

6、销毁走出边界的实例

制造一个包围盒(就是一个Cube)围住可见的游戏区域。离开这个包围盒的实例就销毁:

public class DestroyByBoundary : MonoBehaviour {

	void OnTriggerExit(Collider other)
	{
		Destroy (other.gameObject);
	}
}
这主要是针对玩家射出的子弹。

7、制造陨石雨

新建一个GameObject,导入陨石的model。

如果陨石撞到子弹或者玩家会发生爆炸:

DestroyByContact.cs:

	void OnTriggerEnter(Collider other)
	{
		if (other.tag == "Boundary")
		{
			return;
		}
		Instantiate (explosion,transform.position,transform.rotation);
		if (other.tag == "Player") {
			Instantiate (playerExplosion, other.transform.position, other.transform.rotation);
			gameController.GameOver ();
		}
		gameController.AddScore (scoreValue);
		Destroy (other.gameObject);
		Destroy (gameObject);
	}
注意这里的tag,如果没有tag,陨石在一开始就会爆炸。
做好一个陨石以后就可以做陨石雨了:

GameController.cs:

	IEnumerator Spawnwaves()
	{
		yield return new WaitForSeconds (startWait);
		while (true) 
		{
			for (int i = 0; i < hazardCount; i++) 
			{
				Vector3 spawnPosition = new Vector3 (Random.Range (-spawnVaules.x, spawnVaules.x), spawnVaules.y, spawnVaules.z);
				Quaternion spawnRotation = Quaternion.identity;
				Instantiate (hazard, spawnPosition, spawnRotation);
				yield return new WaitForSeconds (spawnWait);
			}
			yield return new WaitForSeconds (waveWait);
			if (gameOver) 
			{
				restartText.text="Press 'R' for restart";
				restart = true;
				break;
			}
		}
	}

做这里的时候要解决的问题是陨石之间的碰撞,用spawnWait来给每次实例化一个间隔,这样就能避免陨石之间的碰撞了。

startWave是给玩家的准备时间,waveWait是每一波陨石雨的间隔。

8、添加音效

比较简单,略。

9、计分

这是第一次遇到在两个脚本之间传数据的情况。在GameController中初始化Text和分数,每次击毁陨石得分的逻辑应该写在DestroyByContact里。

在视频中出现的一个问题:DestroyByContact是添加到Prefab中的Asteroid上的,不能直接把Hierarchy Window中的Game Controller拖到槽中,视频中的解释:

prefabs are templates of game objects that can be instantiated in any scene in our game,it doesnt make sense that a template that can be added to any scene in our game can hold a refrence to an instance in just one scene

子弹被实例化以后可以拥有game controller的实例的reference

	private GameController gameController;

	void Start()
	{
		GameObject gameControllerObject = GameObject.FindWithTag ("GameController");
		if (gameControllerObject != null)
		{
			gameController = gameControllerObject.GetComponent<GameController> ();
		}
		else 
		{
			//do nothing here...
		}
	}

10、重新开始游戏

GameController.cs中的主要代码:

	void Update()
	{
		if (restart) 
		{
			if (Input.GetKeyDown (KeyCode.R)) 
			{
				Application.LoadLevel (Application.loadedLevel);//reload the scene
			}
		}
	}

后续会添加敌人......

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值