“噩梦射手小结”


“噩梦射手小结”_第1张图片

Unity开发'噩梦射手'的疑问与总结

1,为什么刚体这个组件无法通过enabled=false来关掉呢?

2,走路的同时播放移动动画

if (Input.GetKey("w") | Input.GetKey("s") | Input.GetKey("a") | Input.GetKey("d"))

{

GetComponent().Play("Move");

}

3,Time.timeScale=0的意思是把画面的速度变为0,同时呢,还有Time.timeScale=1是使当前画面的速度恢复正常速度,而Time.timeScale=2则是加快画面的速度。

4,这个是获取游戏结束页面的动画

GameObject.FindGameObjectWithTag("Animation").GetComponent().Play("Aniamtion");

要注意的是,这里的 Animation动画是我自定义而已经调制好了的,名字这种东西你们随便起都可以。

5,下面脚本挂载在摄像机上面,通过标题Light找到摄像机,

通过该脚本实现画面色彩从有到无的效果

GameObject.FindGameObjectWithTag("Light").GetComponent().saturation -= mChangeBalck;

6,获取摄像机这个物体上面的组件ColorCorrectionCurves().saturation

ColorCorrectionCurves这个组件是一个脚本

通过环境资源包添加的脚本。

using UnityStandardAssets.ImageEffects;

这个使用命名空间的代码是必不可少的,因为环境资源包是从外部加入的,并不是Unity本身就具备的功能,同理,当我们使用UI或AI的时候也要记得在命名空间上面用上using.UnityEngine.UI或using.UnityEngine.AI的代码

7,然哥用的是层级的方式来实现对画面物体的拾起和放下

这样就避免了其他那些无谓的接触

8,我用的不是层级,而是标题

其实从本质上来说是没有区别的

只是以后当我们想到射线的时候,最好要想到层级

因为射线检测函数 (Eg:    if (Physics.Raycast(mRay, out mInfo, 1000, 1 << 0 | 1 << 8)))

是把层级也写入了默认的重载,这样我们使用起来就了省不少代码

9,mRay = mCamera.ScreenPointToRay(Input.mousePosition);

是把摄像机mCamera画面的鼠标的点转换成射线

而我在周六的考试中我开始的时候并没有能够点出,而是输入发生了错误

是因为脚本的名字和物体的名字发生了冲突(脚本名字起camera,摄像机也是camera)

这提醒我以后在起脚本名字的时候

必须时刻注意不要与场景中已经有的物体名字冲突

10,if (Physics.Raycast(mRay, out mInfo, 1000, 1 << 0 | 1 << 8))

{

if (mInfo.collider.name== "Planks")

{

mPos = mInfo.point;//为什么要把触碰到的地面的点给到一个固定的位置

this.transform.LookAt(mPos);

}

}

用一个公开的变量mPos把当前鼠标所在的点的位置进行记录

记录后以后让怪兽看向这个点(只是时间Update更新的时间非常快,才会造成我们无法看到这一过程)然后如果能够加上位移,就与自动寻路的功能类似了

这提供了一种选择(1,一种自动寻路与2,位移,朝向的选择)

通常经常下,自动寻路还是比其他的方式省事得多

11,既然说到了自动寻路

那就来说说如果需要物体通过NavMeshAgent组件再加上 this.GetComponent().SetDestination(寻路位置)

这个代码来寻路

前提是,所需要寻路的物体必须具有NavMeshAgent组件和该代码

然后其他不需要进行寻路的物体必须变成静态,变成静态以后就bake

自动寻路和bake是紧密关联在一起的

一个组件,一条代码,n个静态,一个bake

然后新版的unity版本是每修改一次场景都需要重新进行bake

using.UnityEngine.AI的代码是自动寻路前必须使用的,

这个代码是NavMeshAgent组件能够使用的关键

12,接着说一下碰撞检测和触发检测,射线检测这三者之间的关系

碰撞检测很简单,就是需要双方都具有任意一种碰撞器,然后至少有一方有刚体

碰撞检测的代码是void OnCollisionEnter/Stay/Exit(Collision other)

在噩梦射手这个游戏里呢,碰撞只发生在玩家和三个怪物之间,显示,如果给玩家加上刚体,就可以节省不少性能,然后这个时候就会出现一种效果,就是怪物之间无限检测碰撞,出现重叠的现象,显然,这种现象在真实游戏中是不被允许的。

我会选择给三个怪物加上刚体,此时怪物之间会出现互相碰到出现到处翻滚的现象,到处翻滚是因为物体之间碰撞产生了物理上的力,而这个力是因为碰撞产生的,在这里产生碰撞的因为是因为刚体,所以我们可以通过点击刚体组件中Constraints来实现对挂载了该刚体的position和rotation在x,y,z方向上的封锁,这里我选择点击的是对旋转值x,y,z和位移y方向上的封锁,这个时候就实现了只在地面上移动和不产生翻滚效果的画面。

触发检测的代码是void  OnTriggerEnter/Stay/Exit(collider other),这里没有用到触发检测,触发检测在上一个项目飞机大战里对与子弹的射击是有所涉及的,等我下一章再写。

射线检测是一个非常有用的东西,记得刚开始做噩梦射手这个项目的时候,因为这个时候玩家的射线并不是实体,而是粒子特效,我总是死脑筋地往碰撞检测,触发检测上面想,后来是同学点醒了我(我是有多蠢~)

首先我们需要一个空射线(mRay),空的射线射到的物体(mInfo),以及射线的起点(mRay.origin),射线的方向(mRay.direaction),这四个因素是缺一不可的,接下来就是射线检测函数了

if (Physics.Raycast(mRay, out mInfo, 1000, 1 << 0 | 1 << 8)),中文翻译过来就是如果你碰到了某个物体mInfo,注意,这个的射线和mInfo是属于结构体,而结构体是值类型,需要用out把实现值类型的地址传递。然后就是射线检测是需要射线射到的物体是具有collider碰撞器的,如果你没有碰撞器,射线是无法进行检测的,这点必须注意。于是在后面我们可以看到mInfo.collider代码,这代码的意思是射线检测到的物体,接下来就可以用到minfo物体的各种功能和属性了

13,寻找组件的方法,寻找场景中物体的方式

刚开始寻找组件的时候其实非常痛苦,因为我并不知道用怎样的方式进行寻找。通过两个项目的沉淀之后,发现自己懂得了不少寻找组件,寻找场景中物理的方法。先说寻找物体:

1,标题查找是挺有效率的一种方式

2,接着就是通过组件名字来查找,这种方法相当损耗性能

寻找组件:gameObject.GetComponent().

卧槽,写着写着发现,原来自己寻找组件的方式这么少,莫名的尴尬~~

14,接下来说下自动生成怪物和怪物名字

这对于我这种初级程序员来说真的是灾难,谁知道你实例话出来的物体名字是要加上(Clone)啊?卧槽,开始的时候真的是一脸蒙蔽,以至于在Destroy(物体,时间)进行if检测判断的时候没有加上这个(Clone),直接把母体给删掉了,然后无限报错啊有木有啊卧槽

15,Animation和Animator的不同

飞机大战的时候第一次接触Animation,那时只知道Animation是一个旧版本遗留下来的组件,然后试着做居然会做了,好有成就感啊有没有,接着就想,要是以后能只有Animation不用Animator该多好,然而第二个项目就打脸了,用的是Animator;

刚开始用Animatior的时候我的内心是拒绝的,因为陌生,因为第一次把Animation和Animator混淆的痛苦经历~历史总是惊人的相似,用着用着就会用了,同时因为Animator与代码的结合使我深深爱上了Animator,也有Animator界面看起来高大上的原因,喜新厌旧没办法呀有木有

两个在使用上是有明显区别的,Animation的循环,只播放一次,调制等非常容易上手,这也是我爱不释手的原因。而Animator更多地与代码结合在一起,不仅如此Animator对整段完整动画地调节是我非常喜欢的,可以把整段动画通过可视化编程来设置开始,结束时间,还有默认播放动画等。需要关注的是,Animator动画之间是可以通过代码来实现连接的,这里的连接包括单向连接和双向连接。这就为动画之间的切换提供了无限可能,也为我以后赚外快提供了可能。。

16,实例化与欧拉角

以下是一段实例化代码,注意的是旋转值这一段,这里的旋转值用的是默认值Quaternion.identity,相当于null在数组,字符串的作用.

GameObject o1 = Instantiate(m1, transform.position, Quaternion.identity);

GameObject o1 = Instantiate(m1, 实例出现位置, 实例时出现地较母体的旋转值);

如果想要自己设置默认旋转默认值,就需要用到以下代码

transform.eulerAngles

而不是rotation,因为rotation变量在Unity里面默认重载的参数是4个,而不是3个,这里涉及到了四元素的知识,至于四元素是什么,我不知道~

17,简单UI的实现

using.UnityEngine.UI的代码是必不可少的

菜单栏GameObject>>Ui>>Canvas

Slider是用来实现血量条的,它上面有一个默认的脚本Slider,这个脚本的功能类似于环境资源包,不过是内置的UI功能,这里需要关注的变量是Min Value,MaxValue,Value,前两个值看英文就懂了,然后后面的Value是可以通过getcomponent来获取值,然后使这个值来与玩家的血量值联系在一起,我估计以后如果要做游戏,这会是一个经常使用的点。然后注意的是Value的值并不总是跟玩家血量相对应。

然后是GameOver,这是一个用Animator插件做的Animation动画,即在增加组件的时候我选择的是Animator,然后调整动画的时候用的是Animation,惭愧的是,现在的我并不知道为什么可以这样用,难道Animator所有的动画都是由Animation构造而成?因为对Animation比较熟悉了,在调整了1.5秒的动画之后(用的是简单的缩放scale调整),成功地把GameOver的效果做了出来,此外,无心插聊柳成荫,GameOver的字体还以旋转720的效果呈现,哈哈哈哈。

血条创建的流程是先创建Canvas然后再在Canvas的基础上创建一个Slider(即Slider是Canvas)的子类。接下来就是血量的调制,Slide组件上面有个Normal Color,这里的颜色是摇杆圈圈的颜色;然后是Slider的子类Back ground,他的组件Image(Script)里面有一个颜色,这是血量条内部的颜色(即扣血后原本占据血量条的那片区域,最后是Fill Area的子类Fill,虽然这位兄弟看起来是Slider的孙子(Slider的儿子是Fill Area,Fill Area的儿子是Fill),但却是最外面的那部分,就是你仅剩下的血量。 我们可以这样理解,孙子守门口(Fill),儿子守客厅(Fill Area),自己睡内室(Slider),同是因为是最大的那个,可以很轻松的“控制”儿子而孙子,这就是摇杆圈圈的由来。

最后总结一下,这款游戏与飞机大战一样,都是入门级的开发游戏,但却能教会我们很多Unity游戏开发的知识,是我们成为更好的Unity开发者的阶梯

暂时就到这里了, 以后有机会再来补充,拜~

你可能感兴趣的:(“噩梦射手小结”)