unity第三天:碰撞器与触发器
前言一、吃豆球的豆二、吃豆球三、又是豆前言
15:06…
很好,
又是一个下午开始的博客……
Code Start!
一、吃豆球的豆
在新建一个cube,命名为PickUp,transform reset,position y轴上移0.5
暂时把球隐藏起来
就像现在这样
接下来,缩小 scale里面的三边为原来的一半,rotation 都倾斜45°,效果如下
在接下来,写一个script,给它设置运动,让它旋转起来
在component里面 new 一个 script,起名Rotator,记得把它拖到script文件夹里
为了使它实时旋转起来,在update里面执行transform的Rotate()方法,参数是新建的匿名Vector3类,属性(15,30,45),为了保证旋转的速率固定,不受帧率限制,需要乘上Time.deltaTime
void Update(){transform.Rotate(new Vector3(30, 15, 45) * Time.deltaTime);}
运行一下
可以,他转起来了
下一步,该把这个方块多做几个了
把它做成一种预制件prefab,类似父类,之后以它作为模板,制作多个子类
这样既可以方便制作多个重复部件
也可以在调整的时候可以对单独的子类调整,或者对整个模板进行大修改
在Assect的根目录建一个与其他文件夹平行的prefabs文件夹
然后直接把刚才的PickUp拖到Prefabs里
接下来,建一个Empty GameObject,起名PickUps,归0
把PickUp拖进去,准备画圈
第一步,调整编辑器为俯视视角
第二步,把方块的坐标系设为global而不是local,否则它会以自身倾斜的坐标系平移,在global就是以整个世界为坐标系
用Ctrl+d可以快速复制,
在编辑页面,会选中复制之后的方块,把原来的放在当前位置
我建了10个,运行一下
很好,全都转起来了
为了方便区分,这些可收集物需要给它们新的材质,Ctrl+D之前地板的材质,把新的材质也起名叫PickUp(希望别记混了)
把它的颜色改成黄色(255,255,0)或者说是#FFFF00
视频里是把PickUp material 拖到 PickUp Prefab里……
我……
懂了,变身
现在可以拖过去了,看看效果
可以,一地金坷垃,运行一下
嗯,亮眼
下一步该设计小球触碰方块后,消除方块并增加分数系统了
二、吃豆球
我们要设计方块与小球之间的碰撞事件
即小球碰到方块后,消除方块
第一步,把小球调回来
好的,我们应该把方块的位置再调整一下……
现在看起来好多了
接下来该设计小球的脚本PlayerController了
小球的碰撞属性 Collider在官方文档中有对应的脚本方法,用来检测碰撞,并且消除
官方使用OnTriggerEnter()方法检测碰撞,
该方法会在首次碰撞中被触发,
被小球碰撞的触发器作为参数other被这个方法访问,
被碰撞者就是other.gameObject
接下来other.gameObject会等待着这个OnTriggerEnter()方法对它执行各种命令
这种行为,叫做回调
void OnTriggerEnter(Collider other){}
所以OnTriggerEnter()是一个回调方法
(C#里面应该叫回调函数来着……)
接下来,我们需要判断小球碰到的other.gameObject是不是可收集的方块,
如果是,让这个方块消失
如果不是,小球被弹开
因为other.gameObject是GameObject的对象
而在官方API中GameObject类里
判断用到的是gameObject.tag变量,一会儿把可收集方块的Tag定义为“PickUp”
消除用的是gameObject.SetActive()方法
(这个方法不会摧毁对象,只会启用或者禁用对象)
………………………………
然后b站的视频断了,我又回到了腾讯视频接着看……
………………………………
用这两个的时候记得主体是other.gameObject
所以PlayerController的代码就是
void OnTriggerEnter(Collider other){if(other.gameObject.tag == "PickUp"){other.gameObject.SetActive(false);}}
然后回头给prefabs里面的PickUp(这样以它为模板的所有物体都有tag)
打上tag
接下来就在这个页面在PickUp的Tag 列表里面添加一个名为“PickUp”的tag吧
点击这个加号
输入PickUp,save
OK
下一步运行看看
失败了!
在接着看,原来是添加完忘把tag用上了
回到PickUp的PreFab里,把tag改成PickUp
再试试,卧槽还是失败,这回再看看
……………………
这段建议看视频,简单了解一下unity的物理碰撞系统
简单来说,虽然这个方块自己花式旋转,但他在unity的碰撞判定中,是静态的
而被设置了rigidbody的物体是动态的,unity的判定是,动态撞不过静态。
……………………
而方块不消失
是因为unity只给方块设置了碰撞器collider,没有设置触发器trigger
而我们在小球的script里面设置的不是方块的collider碰到小球的方法OnColliderEnter()
而是当方块trigger碰到小球的方法OnTriggerEnter(),
那方块没有trigger,自然无法调用方法了。
没有给方块设置触发器,就给它们的prefab设置一个,把Is Trigger打上挑,这样碰撞器就变成触发器了
(我被这个变成坑了)
这 回 总 行 了 吧 !
成了(此处应打响指)
下一步该设置……
等等,视频还没有完事,再看看
三、又是豆
……………………
接下来是优化unity内存的方法。
简单来说,
为了性能优化,unity会计算所有的体积,把他们放到cash里
对于静态物体来说,他们就可以直接调用现成的体积,不用按帧计算体积了
这本来是很好的
问题在于,静态物体——可收集方块,是旋转的
它的每一次旋转都会同步刷新静态碰撞器的体积,
静态碰撞器也有体积,也是占用cash的,
每一次旋转都会使体积重新计算并上传到cash里面
重新计算,是会占用内存资源的
所以如果不想让它再次占用cash,最好的办法是把它变成动态的,
这样,它的cash就一直保持最开始的体积,直到游戏结束清空所有cash
给方块设置rigidbody,他就变成动态物体了。
在prefabs里面的PickUp添加component,选择rigidbody,运行
好样的,全掉下去了。
接着看视频……
漂亮,我把坑全踩完了。
原来,方块们掉下去的原因有两个,
1,方块在rigidbody里面会受到重力影响
2,方块的collider被改成了trigger,所以无法与地面发生碰撞,就直接穿过去了
那我们不能再把第二个原因改回来啊,方块原地打转没原来好看不说,小球“吃掉”方块的目的不就没了么。
那就只能从第一个方面入手了。
即消除重力对方块的影响。
…………
我学奸了,我先看视频再动手了。
…………
视频里的解决方案有两种,
一种是消除方块重力(把Use Gravity的勾去掉)
另一种是消除力对于方块的影响(把 IS Kinematic的勾打上)
这两种方案各有利弊
前者方块依然会受到其他的力的影响,比如风力,碰撞力(如果有的话)
后者代表,方块的移动只能通过transform操控,不能在游戏里通过玩家间接影响。
即只能用代码机械降神。
在这里视频推荐使用第二种方式取消力的影响。
测试一下
OK
那接下来终于可以把刚才的话接上了
明天该写记分制了。
四、其他
早上出去有点事,本来合计下午写代码可以接受,结果回家休息了一会,跟人论坛对线对上头了……
一晃神都干到下午3点多了……
其实还是摸鱼的心情过于严重,当时想到到点要写代码了,但还是沉迷刷论坛去了,自律有待提高啊!