unity官方教程space shooter 学习文档

本文详细介绍了使用Unity开发宇宙射击游戏的过程,包括场景保存、飞机模型添加与配置、摄像机调整、背景设置、玩家控制、子弹发射与碰撞处理、陨石添加与交互、爆炸效果与音效整合、得分系统实现及游戏结束提示。通过逐步指导,帮助开发者掌握从概念到实现的完整流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


如题,在学习unity的过程中,发现可恶的只能在线看视频,网速严重受限的我感觉很是烦恼,快进一下,诶,不动了,过了一会儿。。。黑屏,就能看到刷新的字样

千辛万苦找到可以下载的视频,打开一看,字幕是英文的。。。英文的。。。英文的(为什么说三遍你懂得)

虽然我英文不是很菜。。。基础的都能看懂,但是专业术语看着还是很伤心。。。用翻译又翻译的连亲妈都认不出来

英文版下载链接http://pan.baidu.com/s/1c0DHDs8

所以我就写篇文档,方便随时查看  (又没WiFi了,我现在在用手机流量写这篇博客。。。大哭


写的有点粗糙加无脑。。。凑活着看吧

 

          Unity            space shooter

1save scene 

2,拖动飞机模型到场景中并reset

3,为飞机添加rigidbody组件

4,为飞机添加胶囊触发器 capsule collider,后来又改成mesh collider

5,调整方向directionz

6,添加prefab里的喷射粒子特效

二,

1,调整摄像机 reset

2x角度为90度,使摄像机朝下,调整y

3,调整投射为直角orthographic

4,移动飞机位置,采用飞机位于中心点不动,移动camera视角的方法

5clear flags 设为 solid color

6create directional light

7, reset

8,rotation x = 20 , y = -115 照射使右边亮

9,光照强度 intensity 调为 0.75 更接近太阳光

10,复制一个光,并命名为fill light ,使其角度照射左边,设intensity0.15,比右边稍暗

设置color,淡蓝色。。。其实光照这部分复杂而且效果。。。就当学习了

11Ctrl + shift +n 创建空的gameobject,将两个光移动到里面,方便整理

 

 

1,禁用player create 3d object, quad 命名为 BackGround,看不到quad,换到scene场景,调整x角度为90

2,取消 mesh coliider,用不到

3,拖动texture中的背景图到quadBackGround)中,这是纹理,我们没创建材质(纹理是材质的一部分),unity自动帮我们创建,放在mesh  renderer中,创建的纹理默认使用diffue shader(但是我这儿是standard)。。。后面作者换成了specular,即standardDiffuse属于漫反射,后者属于镜面反射。最后换成unlit texture,不受光照,这时候变亮了

4,图片拉伸,为防止拉伸后失真,要保证图片宽高比不变,竖屏游戏中,宽拉满,高乘比例。: 15, : 30。。。。。(先分层,设置不同layer,调整背景层y为负值,使其与飞机分开层

1,为player创建脚本Done_PlayerController

建立FixedUpdate函数,在每个固定物理时间步被调用,放置物理行为代码的地方

2,在函数中编写

public float speed; 速度

 

float moveHorizontal = Input.GetAxis ("Horizontal");  水平轴

float moveVertical = Input.GetAxis ("Vertical");    垂直轴

 

Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);

GetComponent<Rigidbody>().velocity = movement * speed;

使飞船可以移动

3,继续编写代码设定飞船可移动范围

 

[System.Serializable]     序列化(储存并转移信息的一种方法)该类,unity才能显示出来

public class Done_Boundary    另外定义一个共有类,里面的属性可以被其他对象共用

{

public float xMin, xMax, zMin, zMax;

}

 

在我们的类Done_PlayerController中实例化Done_Boundary 

public Done_Boundary boundary;

 

GetComponent<Rigidbody>().position = new Vector3   定义xz范围

(

Mathf.Clamp (GetComponent<Rigidbody>().position.x, boundary.xMin, boundary.xMax), 

0.0f

Mathf.Clamp (GetComponent<Rigidbody>().position.z, boundary.zMin, boundary.zMax)

);

 

保存在unity中调试xMin, xMax, zMin, zMax的值 -6,6-4,8

 

4public float tilt;

GetComponent<Rigidbody>().rotation = Quaternion.Euler (0.0f0.0fGetComponent<Rigidbody>().velocity.x * -tilt);

 

根据速度返回一个z轴上旋转角度,使飞机左右移动时会倾斜

 

四,创建子弹

1,创建一个gameobject命名为bolt(别忘了reset),创建一个quad,命名为VFXresetx旋转90),将其拖到bolt中,后面创建的材质放这里

2,在materiascreate一个材质命名为 fx_bolt_orange(实际上资源包里已经创建好了)

3,将texture中的fx_lazer_orange_dff纹理与刚才创建的材质建立联系,有两种方法:

1)直接拖到纹理到材质中

2)点击材质旁的select选择纹理

4,这时候到game视图,子弹周围还有黑框,shader选择 Mobile/Paticles/Additive(已经设置好了)

5,VFXremove mesh collider添加capsule collider

,为bolt添加刚体组件取消重力

6,调整方向为z-axis,半径0.03,高0.5,勾选 is trigger

7,为其添加脚本使其发射

public class Done_Mover : MonoBehaviour

{

public float speed;

 

void Start ()

{

GetComponent<Rigidbody>().velocity = transform.forward * speed;

}

}

8,回到unity,设置子弹速度为20

9.因为要有很多子弹,所以把子弹设为预制件prefab,直接将bolt拖动到下面prefab即可

10.在层级中删除bolt,点击运行,将预制件中的bolt一个个拖动到层级中,会看到子弹发射出去

 

五,1,创建gameobject命名为 Shot Spawn,将其拖到player里面,reset

2,将子弹prefab拖到Shot Spawn里,设z1.25,查看效果后将子弹删除

3,在one_PlayerController里家这样一段代码

public GameObject shot;

public Transform shotSpawn;

public float fireRate;

 

private float nextFire;

void Update ()

{

if (Input.GetButton("Fire1") && Time.time > nextFire)  

{

nextFire = Time.time + fireRate;

//GameObject clone = 

Instantiate(shot, shotSpawn.position, shotSpawn.rotation);

//as GameObject

 

}

}

 

Fire1input预设的一个按钮,即我们点击或按钮时而且当前游戏时间 下一次发射时间,那么执行: 下次发射时间增加,发射。(as GameObject 是告诉unity我们实例化了一个GameObject对象,新对象需要个参照对象才方便操作。但这里我们只让飞机发射,子弹并没有其他动作,所以用不到)

4,回到unity当中,为刚才创建的属性赋值

prefab中的bolt拖到Shot中;

Shot Spawn拖到Shot Spawn中;

Fire Rate设为0.25.1秒发射4次)。

运行。。。

5create cube ,命名为Boundaryreset,勾选 is trigger

6,设置其到中心,跟摄像机坐标一样 x0z5;调整scale使其铺满屏幕:x15z20

取消mesh render,到scene中看下效果

7,添加脚本Done_DestroyByBoundary

代码:

void OnTriggerExit (Collider other) 

{

Destroy(other.gameObject);

}

当其他碰撞器停止与该触发器接触时调用这个函数(即离开时调用),即实现子弹,障碍等碰到边界时自动消除

8remove mesh rendermesh filter,运行,会发现层级当中生成的bolt(clone )会自动消失

 

 

1,添加陨石,create gameobject ,命名为Astroidereset

2,将model中的第一个拖到Astroide中,reset 

3,为Astroide添加刚体组件,取消重力,添加capsule collider,勾选 is trigger

可以按住shift 调整 capsule collider的大小(但我的胶囊有问题。。。只有一个球,而且shift后没有出现触点)

4,为Asteroid添加脚本Done_RandomRotator 实现陨石随机角度翻滚

代码

public float tumble;   翻滚值

void Start ()

{

GetComponent<Rigidbody>().angularVelocity = Random.insideUnitSphere * tumble;

}

 

angularVelocity,旋转速率;insideUnitSphere vector3类型,会对xyz随机

回到unity,设置tumble值为5,设angular drag(角度阻力)为0

5,为Astroide添加脚本 Done_DestroyByContact

代码

void OnTriggerEnter (Collider other)

{

Destroy (other.gameObject);

Destroy (gameObject);

}

 

OnTriggerEnter OnTriggerExit不同,是第一次触碰时调用

Destroy (other.gameObject);销毁碰到的其他物体

Destroy (gameObject);销毁调用该脚本的对象即陨石

6,运行,发现陨石木有了 QAQ

7,我们来debug,在函数OnTriggerEnter中加OnTriggerEnter,再运行,发现是Boundary。。

8,为Boundary添加tagBoundary),使其免疫与陨石的碰撞。在代码中注释debug并添加代码if (other.tag == "Boundary" || other.tag == "Enemy")

{

return;

}

Enemy先不管,后面用到,这里前面判定到Boundary的时候,中断这个函数的执行,就不再执行后面销毁的代码了。

 

9添加代码

public GameObject explosion;

 

if (explosion != null)

{

Instantiate(explosion, transform.position, transform.rotation);

}

回到unity中,将预制件VFX中的explosion_asteroid拖到Asteroid对象的Explosion

和以前添加子弹一样,我们这里添加爆炸效果,使陨石被碰撞的时候释放爆炸效果

10,添加代码

public GameObject playerExplosion;

if (other.tag == "Player")

{

Instantiate(playerExplosion, other.transform.position, other.transform.rotation);

}

回到unity当中,设置playertagplayer,将explosion_player拖到AsteroidPlayer Explosion当中,实现飞机与陨石碰撞时的爆炸效果

11,为Asteroid添加Done_Mover脚本,回到unity设置speed-5使其能朝向飞机移动

12,将Asteroid拖入到prefab中,删除层级视图中的Asteroid

 

1create gameobject,命名为Game Controllerreset,添加脚本Done_GameController

添加代码实现随机产生一个陨石

public GameObject hazard;    陨石参照对象

public Vector3 spawnValues;   Vector3类型对象

void Start ()

{

SpawnWaves ();

}

void SpawnWaves()

{

Vector3 spawnPosition = new Vector3 (Random.Range (-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);

Quaternion spawnRotation = Quaternion.identity;

Instantiate (hazard, spawnPosition, spawnRotation);

}

Start中调用spawnwaves 

 

spawnPosition 为陨石产生的坐标,由spawnValues赋值,随机产生只考虑x坐标,用Random.Range确定随机范围

 

spawnRotation 为陨石产生的角度,这里用Quaternion.identity设为不变,若有角度,就不能保证陨石直直的冲向飞机

2,想让当前代码暂停执行而不暂停当前游戏需要协同程序 cooperate

StartCoroutine (SpawnWaves ()); //协同函数被调用

 

IEnumerator SpawnWaves ()    //协同函数要加IEnumerator

{

yield return new WaitForSeconds (startWait);     //开始准备时间 

//调用函数暂停要加yield return new

while (true)

{

for (int i = 0; i < hazardCount; i++)

{

GameObject hazard = hazards [Random.Range (0, hazards.Length)];

Vector3 spawnPosition = new Vector3 (Random.Range (-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);

Quaternion spawnRotation = Quaternion.identity;

Instantiate (hazard, spawnPosition, spawnRotation);

yield return new WaitForSeconds (spawnWait); //每个陨石间隔

}

yield return new WaitForSeconds (waveWait);  //每波陨石来临间隔

}

}

利用for循环一波生成多个陨石,且不会出现多个陨石同时出现导致陨石自相残杀的情况

 

3,这里有个问题,层级中爆炸对象不会自动消失,要为两个爆炸添加脚本Done_DestroyByTime

代码

public float lifetime;

 

void Start ()

{

Destroy (gameObject, lifetime);

}

在开始的一帧推延lifetime的时间执行销毁,lifetime设为2

 

 

 

八,

1unity有三个音频组件音频剪辑,音频源,音频监听器

2,将audio中的对应音效拖入prefabExplosions的对应预制件中,勾选play on awake

   这样为爆炸效果与音效建立了关联

3,添加飞机武器音效,将weapon_player拖入player中,取消play on awake,打开PlayerController脚本

4,添加GetComponent<AudioSource>().Play ();

AudioSource 作用:建立音频源于组件的关联

Play是音频源的一个函数,用于播放音频剪辑

5,运行后发现没声音,仔细一看audio里面的音频剪辑也没声音。。。如果你们出声音了麻烦请告诉我

 

九,

1,创建 3D object3D text。(Gui text什么的实在搞不出来,拿3D试出来了。。。)

Resetx旋转90度,调整字样为 Score Text,调整坐标位置移动到屏幕左上角

2,打开脚本文件

添加代码public TextMesh scoreText;

private int score; (不希望被其他调用)

Start函数内添加

score = 0;

UpdateScore ();

添加函数

void UpdateScore ()

{

scoreText.text = "Score: " + score;

}

添加共有函数

public void AddScore (int newScoreValue)

{

score += newScoreValue;

UpdateScore ();

}

回到unity中将Score Text 属性设置为Score Text对象

3,点击Game Controller,设置tagGame Controller

public int scoreValue;

private Done_GameController gameController;

 

void Start ()

{

GameObject gameControllerObject = GameObject.FindGameObjectWithTag ("GameController");

if (gameControllerObject != null)

{

gameController = gameControllerObject.GetComponent <Done_GameController>();

}

if (gameController == null)

{

Debug.Log ("Cannot find 'GameController' script");

}

}

 

在爆炸的开始为每一个爆炸clone实例找到对应的gameObject的引用,

gameController.AddScore(scoreValue);

 

在爆炸的最后执行添加分数

最后回到unity中点击prefab中的Asteroid,设置Score Value10,运行。。。

完结

1,创建gameobject,命名为Displayreset,将创建的3d text拖进去。

2,创建Restart TextGameOver Textreset,调整字样,调整位置,拖动到Display

3,打开脚本Done_GameController

添加代码

定义

public TextMesh restartText;

public TextMesh gameOverText;

private bool gameOver;

private bool restart;

start函数中初始化

gameOver = false;

restart = false;

restartText.text = "";         //使游戏开始时不显示这俩组件

gameOverText.text = "";

update函数中添加restart的实现逻辑

if (restart)

{

if (Input.GetKeyDown (KeyCode.R))

{

Application.LoadLevel (Application.loadedLevel);

}

}

建立共有函数GameOver用于设置游戏结束信息和tag

public void GameOver ()

{

gameOverText.text = "Game Over!";

gameOver = true;

}

 

IEnumerator SpawnWaves ()加入代码跳出while循环使游戏结束并显示重新开始的提示信息

 

if (gameOver)

{

restartText.text = "Press 'R' for Restart";

restart = true;

break;

}

update中添加代码实现按下R是游戏重新开始

if (restart)

{

if (Input.GetKeyDown (KeyCode.R))

{

Application.LoadLevel (Application.loadedLevel); //重新加载当前场景

}

}

4,回到unity,将Restart TextGameOver Text拖入Done_Game_Controller脚本的相关属性栏里

5,打开脚本Done_DestroyByContact

在判断触碰的函数OnTriggerEnter添加

if (other.tag == "Player")

{

Instantiate(playerExplosion, other.transform.position, other.transform.rotation);

gameController.GameOver();

}

如果陨石碰到的是飞机,播放动画,调用公有函数GameOver(),实现显示gameover的字样

待这一波陨石都消失后,会显示Press 'R' for Restart,然后按下R,会开始新一轮游戏

 

6,发布到web

Ctrl+Shift+B,选择web player,点击Add Current,将当前场景添加进去,build。选择一个你想把资源添加到的文件夹

9,发布后发现一个bug,按一下ctrl键,会一直放发射的音效,回去看了一下,发现不知道什么时候手贱把player的音频源里的loop点了

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值