前段时间,把c#语法又看了一下,感觉收获还是不少的,之前只学过c,对面向对象一点感觉都没有。。。。。
现在来学习unity,感觉还是游戏什么的好!本文是写给自己的手记,不会写得很全,只写自己感觉有点意思的。
环境光
这个游戏表现的是太空环境,所以默认的环境光扔掉扔掉,环境光有点像在地球上大白天各种漫反射堆叠的效果,不适合表现太空场景。
视频里的环境光设置与我用的版本不同,我的在
windows->lighting->setting 里,给改成纯黑色。
背景贴图
这个游戏的背景使用一个quad,表面贴上图片组成的,但是默认的shader会对光线进行吸收和反射,因为图片已经调理得当,不需要进一步打光
所以使用unlit 的shader,
对比默认defuse(左),和unlit(右):
工程整体结构
玩家的设计:
元素组成
包括:
player:玩家主题部分,模型,碰撞器都在这里;
engines_player:玩家的引擎部分,是一个用粒子系统做的引擎效果。
玩家控制脚本
移动:
private void FixedUpdate(){float moveHorizontal = Input.GetAxis("Horizontal");float moveVertical = Input.GetAxis("Vertical");//用于捕捉用户的输入信息Vector3 movement=new Vector3(Speed * moveHorizontal, 0.0f, Speed * moveVertical);Rigidbody rb = (Rigidbody)this.GetComponent("Rigidbody");rb.velocity = movement;
rb.position = new Vector3(Mathf.Clamp(rb.position.x, boundary.Hm, boundary.HM),0,Mathf.Clamp(rb.position.z, boundary.Vm, boundary.VM)); //限制玩家的位置不超过屏幕具体数值微调
rb.rotation = Quaternion.Euler(0.5f*tilt* moveVertical, 0, -tilt* moveHorizontal);//移动的同时旋转}
发射子弹:
//发射子弹public GameObject shot;public Transform shotspawn; //开火的位置float nextFire = 0; //下次开火应有的时间public float fireRate=0.5f; //开火间隔private AudioSource shot_audio;//这个字段初始化在start()里private void Update(){// float nextFire = 0 ;放在这里没用,只是在每次调用的时候都被初始化了if (Input.GetButton("Fire1")&& Time.time>nextFire)//如果这一帧开始的时候,已经过了预定开火时间{nextFire = Time.time + fireRate;Instantiate(shot, shotspawn.position,new Quaternion() ); //新实例化一个Quaternion 作为rotation,避免子弹发射角度不对shot_audio.Play(); //开火音效}}
子弹:
注意:考虑到子弹一出现,就应该飞走,所以为其添加移动的
public float speed;void Start () {Rigidbody rb =(Rigidbody) GetComponent("Rigidbody");//rb.velocity = new Vector3(0, 0, 4.0f);rb.velocity = transform.forward* speed;}
场景、环境的设计:
背景:
由quad ,贴上图片组成,shader用unlit,
边界:
作为backgroud的子物体,是一个使用用render的cube,添加一个box_collider脚本:private void OnTriggerExit(Collider other){Destroy(other.gameObject);}//所有物体离开碰撞器都会被销毁
灯光:
没什么好说的,喜欢怎么打都行,不过教程中打的3个光挺有意思的,主光源,填充光源,轮廓光源。。。。轮廓光源以前没听说过。
UI: (ps如何获取子物体)
很简单,就是在一个canvas里放了3个Text:
然后关键来了:如何获取Canvas下的Text子物体????
作为一个以前只知道c 的萌新,又去各种百度....然后结果如下:UI = GameObject.Find("Canvas"); //先找到CanvaUI = UI.transform.Find("Text").gameObject;//获得Text 子物体// 原来藏在transform下面。。。。Transform和Tomponent,GameObject是什么关系啊。。。。text = UI.GetComponent("Text") as Text;//获得Text.Text组件CurrentScore += scoreValue;text.text = "Score:"+ CurrentScore;
gameController:游戏流程控制
实际上是一个空的gameObject,顺便带上流程控制脚本,大多数难度不大关键:
延时的实现,协程Coroutine,具体我也不懂,我随便说说,不要参考代码:
IEnumerator SpawnWaves() / /IEnumerator 关键字{yield return new WaitForSeconds(startWait); //协程 延时标记while (true){for (int b = 0; b < 20; b++)//生成一波陨石{Vector3 spawnPosition = new Vector3(Random.Range(-spawnValues_xRandom.x, spawnValues_xRandom.x), spawnValues_xRandom.y, spawnValues_xRandom.z);Quaternion spawnRotation = Quaternion.identity;Instantiate(Hazard, spawnPosition, spawnRotation);yield return new WaitForSeconds(spawnWait); //协程 延时标记}
spawnWait *= 0.8f;Mathf.Clamp(spawnWait, 0.1f, 100);yield return new WaitForSeconds(3.0f);//协程 延时标记
if (isGameOvered){isRestart = true;break;}}}
void Start(){UI = GameObject.Find("Canvas");StartCoroutine(SpawnWaves());// 启动协程}
其他 :
rigidbody的直接使用与引用:
视频中经常出现类似this.rigidbody.xxxxxx 之类的直接写法。。。。但是貌似unity5以后不能这么用应该写成:Rigidbody rb = (Rigidbody)this.GetComponent("Rigidbody");rb.xxxxxxxx ;
也就是说,要先建立好引用(?),再做操作。 //引用是什么。。。。
其他的组件也一样,先做好引用再做操作。
场景加载:SceneManager.LoadScene("Main");// Application.LoadLevel(Application.loadedLevel);
两种写法都可以,不过后者已经属于“传统型写法”了。
总结 :
大概花了三个 半天,把教程看完了,也做完了,感觉收获还是比较大的,
其中主要的收获在于:熟悉了unity的整体开发流程,打代码不至于东张西望了。细节部分:一、关于协程,延时的理解二、面向对象概念的熟悉,什么实例化,继承,引用,云云、、、三、如何通过transform获取子对象四、获取用户输入,计算移动偏移量
ps:有点乱。。。还是不熟悉这个编辑工具。。。算了,反正是给自己看的,有兴趣的看看吧
ps:csdn这个编辑工具有毒。。。。。。。