随着程序越来越复杂,一下章节不能再贴全部代码了,只贴涉及到的部分,但全部代码会在文末给出
子弹这一部分涉及多个知识点:简单归纳如下
1.给刚体施加力量让其移动
2.利用public一个对象,然后界面绑定的方法传递预制体
3.预制体实例化
十四. 子弹
1.初始化
首先,找到子弹素材,将其做成一个预制体
给他添加刚体 和 碰撞盒
创建一个脚本bullet来控制子弹
2.子弹移动
这里我们用另一种方法来让刚体移动 ==>施加力量
public void BulletMove(Vector2 moveDirection,float moveForce)
{
bulletRigid.AddForce(moveDirection*moveForce);//给子弹添加一个力,它就会受力移动
}
3.主角脚本绑定子弹预制体
由于主角是发射子弹的主体,所以,发射代码写在主角的脚本中,在主角脚本中如何获得子弹的预制体呢? 我们利用public一个对象,然后界面绑定的方法来传递预制体
首先我们public一个gameobject对象
public GameObject bulletPreb;
然后,在界面上将子弹的预制体绑定过去
![v2-caa19a061251dbaf70f4bfcddd4d1469_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/aa28149e31ecca2f48b46b344e6e4dde.png)
这种方法简单,高效!接下来就是实例化这个预制体
4.发射子弹
比如:我们按下J键,就发射一个子弹
这里用到了预制体实例化的函数Instantiate(); 实例化后调用子弹移动函数,使其移动
if (Input.GetKeyDown(KeyCode.J))
{
GameObject bullet= Instantiate(bulletPreb,rubyBody.position,Quaternion.identity);
bullet.GetComponent<bullet>().BulletMove(lookVector,300);
}
完成了!!!!
但是,效果和我们想象的完全不一样....
![v2-e48e0624f0f8e8fd9cc6039e7d556441_b.gif](https://i-blog.csdnimg.cn/blog_migrate/d8805e8d6055ab6c23b284abcdebe66d.gif)
效果不尽人意,原因有好几个,我们一个一个的解决
问题1:角色不应该和子弹有刚体碰撞,这里就要把角色和子弹分好层了(其实所有节点创建之时起就都应该分好层)
![v2-440a91380224f9bf16babd4921017c45_b.png](https://i-blog.csdnimg.cn/blog_migrate/956b0f7ab4f32da1386b5d9807745d25.png)
![v2-a77c360bdaf3f519fa109586b161baf5_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/a66593511f91bb3abd5be42784499460.png)
然后在项目设置中将player和bullet的层间碰撞取消
![v2-cd52f03778d5e89ce1c24bfa3c4624f1_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/02fbd84efd34b804014503aa603f7660.png)
![v2-60353d96f7027e063e58b4b9618bc2e5_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/7e51a1a2602ed1a25d01e20cedf1089b.jpeg)
此外,后来我将bullet之间的碰撞也取消了,这样就能保证某些极端情况下,子弹互相碰撞.
![v2-10c1b722345fc58e4f4e07def83c8356_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/c754e9a1558dd3f5f8e4e8b59e6548d6.jpeg)
问题2:
效果终于发生了变化,但是子弹怎么不动呢?
![v2-0d3cdb9553c64fa1563effab91709cfa_b.gif](https://i-blog.csdnimg.cn/blog_migrate/d082af70993e285d607088341eb0bd65.gif)
而且控制台还报错
![v2-b0bcb5727ca7a6dd821248981791472d_b.png](https://i-blog.csdnimg.cn/blog_migrate/0d9b25be4704908acd538a6b147035a6.png)
问题出在了,子弹初始化的逻辑上
我们获取子弹刚体,不应该在start里 ,而应该在awake里,
这里说一下start和awake的区别:
1.Awake()是在脚本对象实例化时被调用的,而Start()是在对象的第一帧时被调用的,而且是在Update()之前,先执行Awake方法,再执行Start方法
2.脚本的一些成员,如果想在创建之后的代码中立即使用,则必须写在Awake()里面;
3.当脚本设置为不可用时,Awake方法仍然会执行一次,而Start方法则不会执行!
所以我们可以简单理解为:实例物体创建后就awake,执行脚本开始时start,
awake是实例对象的初始化,start是脚本的初始化
这里我们想实例对象创建后立即执行所以应该将此初始化写在awake里
![v2-d8b62bfa399f54eb08f9e1f27138aede_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/7fbfb9f9bdc1ea50f6af5d15bc45389b.png)
private void Awake()
{
bulletRigid=GetComponent<Rigidbody2D>();
}
![v2-d75e875189ee767903d752d73e8bb73f_b.gif](https://i-blog.csdnimg.cn/blog_migrate/a3e80d098a90e4ea9db9e290236f5b28.gif)
终于可以了,接下来我们为子弹添加碰撞和自毁程序,在给角色添加射击动画
5. 子弹碰撞和自毁
子弹不能永远的飞行下去,当他碰到别的物体或这飞行一段时间后,应该自毁
首先我们来做飞行一段时间后自毁:
这个很简单
Destroy(gameObject,2f); //写在awake里即可 awake两秒后就会自毁
再写碰撞自毁:
private void OnCollisionEnter2D(Collision2D other)
{
Destroy(gameObject);
}
6. 给角色添加发射动画
再添加角色的射击动画:
if (Input.GetKeyDown(KeyCode.J))
{
GameObject bullet= Instantiate(bulletPreb,rubyBody.position,Quaternion.identity);
bullet.GetComponent<bullet>().BulletMove(lookVector,300);
anim.SetTrigger("launch"); //触发发射动画
}
其实这里有问题,就是没有限制角色的发射频率,因为此段代码写在update里,所以很好实现.这个功能以后完善.
7. 子弹击中敌人
子弹击中敌人,应该做以下事情,
1.子弹击中消失;
2. 敌人播放被击中的动画 //这里注意,敌人被击中时不要再继续执行移动等动作.
3.敌人播放完动画后消失
我们在敌人脚本中建立了一个布尔变量记录角色被击中的状态