0806
视频:19 物理弹球 小球管理
- 障碍物扣血 00:03:42——00:22:20
障碍物扣血.png-
可以理解障碍物可以抗揍的次数
-
新建一个障碍物Obstacle的脚本
-
调用现有的碰撞检测的方法 注意是2D的
private void OnCollisionEnter2D(Collision2D collision) { }
-
定义一个血量也就是抗揍的能力 在碰撞里每碰撞一次 血量减1
public int Hp = 5;
-
在碰撞里每碰撞一次 血量减1
Hp -= 1;
-
此时运行时随着碰撞产生 可以看到inspector面板中的数值在下降 需要界面UI给与显示 新建一个Text设置好数字 摆好位置
-
将UI的text和障碍物的血量进行绑定 首先建立界面和代码的关联 让代码可以访问界面的东西 在代码里定义一个Text类型的公有变量
public Text TextHp;
-
记得命名空间需要引用一下
using UnityEngine.UI;
-
这是被拖过脚本的障碍物会出现TextHp的空槽 把对应的UI的Text拖进去就好了
-
此时代码已经和UI的Text进行关联了 接下来需要将障碍物的血量和text下的字符串进行关联 在start方法里初始赋值 因为障碍物血量的变量的类型是整型 而UI下text为字符串 所以强行进行转换一下
TextHp.text = Hp.ToString();
-
在update方法下再次赋值 因为每次变换需要重新赋值
- 障碍物消失
-
在Obstacle脚本中的碰撞方法中进行实现 用一个if条件语句进行判断障碍物血量值小于等于零后进行销毁 为什么是小于等于 因为后面成倍掉血会变成-1
if (Hp <= 0) { Destroy(gameObject); Destroy(TextHp); }
-
销毁的方法是Destroy(); 除了障碍物本身要消失 UI也需要消失
- 小球回收00:22:20——00:53:47
小球回收.png-
为了重置小球的位置 与其将小球位置相关数值写入代码进行控制 到不如合理有效运用collider is trigger的功能 istrigger 打勾后表示受到碰撞后触发机制的开关打开了 可以理解为即使没有显示出碰撞的状态 但仍能检测更加简单 两个物体只需要选择合适的其中一个进行勾选
-
给地面加一个有collider的sprite 重命名为ground 但其实是不需要有弹力效果的 勾选is trigger 可以让地面检测到小球有了碰撞 但不会产生弹力 记得sprite render可以将其形状隐藏掉 随时还可以打开以调整collider的大小
-
新建一个脚本 GroundChecker用来检测小球掉落地面
-
此时的碰撞就不能用oncollisinEnter2D了 需要用另一个
private void OnTriggerEnter2D(Collider2D collision) { }
-
当小球碰到地面后重置小球位置 首先需要知道小球重置的位置 可以用一个空物体代替小球的发射位置 这个空物体只有transform的组件 重命名为BallShooterPosition
-
为了直接控制小球 在Ball的脚本里写一个新的方法 可以将小球重置
public void ReSetPos() { }
-
为了获取小球的发射位置 在类里定义一个公有的Transform类型的变量用于存放小球发射的位置
public Transform BallShooterPos;
-
保存脚本后 Ball的属性会多出BallShooterPos的空槽 将BallShooterPosition的空物体拖进去
-
在ReSetPos的方法里把小球的位置重新赋值一下
transform.position = BallShooterPos.position;
-
这个方法就达到了重置位置的效果 但由于之前的物体是有运动速度和旋转的 所以在重置位置前需要把小球的速度(二维向量(0,0))和角速度都重新赋值为零
_rigidbody2D.velocity = Vector2.zero; _rigidbody2D.angularVelocity = 0; transform.position = Resetpoint.position;
-
最后特定的时候调用这个方法 在GroundChecker的代码里的OnTriggerEnter2D的方法里调用这个方法 但因为不在一个脚本里 所以首先要获取小球的自定义脚本组件 用一个变量ball接收 然后从这个变量下调取ReSetPos的方法
var ball = collision.GetComponent<Ball>(); ball.ReSetPos();
- 多个小球的管理00:53:47——01:32:01
多个小球管理.png- 多个小球需要有承接物 完善场景 模仿原游戏可以拖入图片便于调整比例和位置
- 多个小球需要重新建立脚本BallManager来控制小球的重置和发射
- 多个小球是从重置位置滑落到发射点才进行发射的 小球的起点现在变成了 重置起点ResetPoint和发射位置ShooterPoint 之前的ResetShooterPosition需要调整位置并重命名为ShooterPoint 并且新建一个ResetPointRight的空物体 暂时先做一边的
- BallManager的脚本挂在多个小球的父物体上
- 多个小球的依次发射
-
剪切Ball脚本中按下鼠标左键发射的条件代码块到新脚本ObstacleManager的update方法下 注释掉发射那句 因为现在是多个小球 需要有间隔的发射
if (Input.GetMouseButtonUp(0)) { var mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition); Vector2 _direction = mousePos - transform.position; _direction.Normalize(); //_rigidbody2D.AddForce(_direction*ForceSize,ForceMode2D.Impulse); }
-
重新写一个发射多个球的方法
void ShootBalls() { var mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition); Vector2 _direction = mousePos - transform.position; _direction.Normalize(); }
-
在按下鼠标后调用
if (Input.GetMouseButtonUp(0)) { ShootBalls(); // _rigidbody2D.AddForce(_direction * ForceSize, ForceMode2D.Impulse); }
-
在ShootBalls方法里用一个for循环 循环条件是 当变量小于子物体的总个数时 依次给这个变量加一 从而可以实现依次的效果
for (int i = 0; i < transform.childCount; i++) { }
-
这个for循环里面的语句可以执行一些操作 第一个操作就是用一个变量child接收所挂脚本的空物体下的任意一个子物体 依次访问到每个小球后
var child = transform.GetChild(i);
-
已经可以依次访问到每个子物体了 然后需要定义一个变量rg获取每个子物体的刚体组件 以便后面调用刚体组件施加力的工具AddForce达到发射的效果
var rg = child.GetComponent<Rigidbody2D>(); rg.AddForce(_direction * ForceSize, ForceMode2D.Impulse);
-
记得ForceSize需要重新定义一下 避免单纯数值 所以用变量代替 可以进行更改
public float ForceSize = 1;
-
此时多个小球可以进行发射出去了 但没有一定间隔 怎样实现延迟发射呢 引入一个概念 协程Coroutine 怎么理解呢 之前调用一个方法会全部执行完 或者执行到中间一个return语句就停止了 但有时我们会有这样一个需求 比如运行到一半想暂停一下 再次调用方法时从上面暂停的位置再执行
-
所以利用协程就可以实现在特定的地方暂停 并以协程的方式去执行相应的方法 以此实现每次发射一个小球后暂停一会儿继续执行发射的语句直到所有小球发射完成
-
怎么使用协程呢 给需要用协程的方法改变为IEnumerator
IEnumerator ShootBalls() { }
-
在需要暂停的且再次调用方法时以这个地方为开始去执行 用的的语句是yield return 需要暂停的功能后面加上 new waitforseconds();
yield return new WaitForSeconds(ShootInterval);
-
括号里是间隔的时间 为了避免字面数值 可以在类下定义一个公有浮点型ShootInterval来表示时间间隔
public float ShootInterval = 0.5f;
-
之前按下鼠标的if语句调用的就不是普通的方法了 而是带有协程的功能的方法 此时需要用特定的规则去调用这个方法
StartCoroutine(ShootBalls());
-
运行后发现小球向上发射 这是因为小球发射位置没有在代码里进行关联 在代码里定义一个发射点 并拖入空槽
public Transform ShootPoint;
-
然后再小球发射前改变小球的位置为发射点的位置
child.transform.position = ShootPoint.position;
- 多个小球的回收 重置到起点滑落至发射点
-
在每个小球自己所附带的Ball脚本里之前定义的BallShooterPos更改为ResetPoint
public Transform Resetpoint;
-
下面的重置方法里的位置也要更改
public void ReSetPos() { transform.position = Resetpoint.position; }
-
将PinBall下的子物体全部选中 把Resetpoint拖入空槽
网友评论