欢迎回到第20天Unity开发的又一个激动人心的一天! 你相信吗? 我们是100天的1/5! 我希望这种势头能使我继续前进,直到我发货为止!
现在回首第19天,我们创建了一个可以使用的医疗系统,但是遇到了问题。
由于某种原因,即使我们经过攻击动画,对撞机也只会击中敌人一次。
今天,我们将解决这个问题。 所以,让我们开始吧!
问题在于我们在第12天为骑士创建的Mesh Collider。还记得吗?
那个站立的网状对撞机,实际上就是每次骑士攻击我们时我们都会与之碰撞的东西。
问题是网格碰撞器无法跟随模型的动画,因此当骑士第一次触摸我们时,网格物体可能会触摸我们,但是之后,我们(玩家)就不会被碰撞器向后推,网永远不会再碰我们。
这是说明问题的图片:
尽管骑士模型本身可能正在触碰我们,但我们的Mesh Collider却是静态的,不会移动。
这不好! 当骑士的拳头接触到玩家时,我们想伤害我们的玩家! 不是这个静态的网格对撞机!
要解决此问题,需要进行一些更改。
- 我们仍然需要我们的Mesh碰撞机。 这阻止了我们穿越敌人。 现在,我们遇到了一个问题,我们可以在骑士上行走,但是现在我们将解决此问题。
- 我们将在骑士手中增加一个Box Collider。 这样,我们就可以确定我们的玩家何时受到重击。
目前,我们无法移动网格,因为它位于父实体中。 根据这篇关于网格定位不正确的文章,我们将制作一个新的空对象并在其中添加网格碰撞器。
这对我们有用,因为我们只需要网格即可进行碰撞检测和光线投射以进行拍摄。
我们开始做吧!
最初,我们将Mesh Collider放置在我们的KnightPrefab游戏对象中。 让我们现在将其删除。
选择knightprefab ,单击鼠标右键,然后选择创建空 ,以制作一个新的游戏对象。 让我们将该对象重命名为Collider 。
选择Collider并向其中添加一个新的Mesh Collider组件。 对于“ 网格” ,选择“ 主体”以恢复我们的“骑士”模型。
您可能必须在自己周围移动对撞机 ,以使对撞机与我们的骑士相匹配,但是,最后您应该具有以下内容:
现在有了这个,我们不能只是走过骑士。
既然我们已经解决了网格对撞机问题,那么我们将解决最初的问题,即当敌人攻击我们时对他们造成伤害。
为此,我们将在骑士的拳头上增加盒子对撞机。 具体来说,在knightprefab中->臀部->脊柱->胸部-> L_shoulder / R_shoulder->一直到L_Wrist / R_Wrist。
对于每个盒子对撞机 ,我将盒子的比例设置为0.25以适合手的大小。
现在我们有了这个,我们需要将脚本附加到每个可以检测到碰撞的手模型上。 父对象的脚本无法为其子级检测到冲突。
同样重要的是,原始脚本EnemyAttack保持原样 ,因为我们需要访问位于父级中的动画师组件。
为了解决我们的问题,我们将代码的冲突部分从EnemyAttack移到名为FistCollider的新脚本中。
FistCollider将处理骑士拳头的碰撞,我们将在EnemyAttack脚本中获得结果。
这是我们的FistCollider脚本:
使用UnityEngine;公共类FistCollider:MonoBehaviour { 私人GameObject _player; 私人布尔_collidedWithPlayer; 无效Start() { _player = GameObject.FindGameObjectWithTag(“ Player”); _collidedWithPlayer = false; } void OnCollisionEnter(Collision other) { 如果(other.gameObject == _player) { _collidedWithPlayer = true; } 打印(“输入与_player相撞”); } void OnCollisionExit(Collision other) { 如果(other.gameObject == _player) { _collidedWithPlayer = false; } print(“退出与_player相撞”); 公共布尔IsCollidingWithPlayer() { return _collidedWithPlayer; } }
这是代码流:
- 像我们的EnemyAttack脚本一样,我们要访问我们的玩家游戏对象,并且要检查是否与敌人相撞。
- 在Start()中 ,确保实例化两个变量。
- 在OnCollisionEnter()和OnCollisionExit()中,如果与我们发生冲突的是玩家,那么我们将设置布尔标志。 再一次,这与
- 在IsCollidingWithPlayer()中,我们会将布尔值_collidedWithPlayer交给任何调用它的人。 请注意,此功能是公共的,因此其他脚本可以访问此功能。 我们稍后将使用它。
让我们将脚本附加到L_Wrist和R_Wrist。
现在,我们将部分碰撞代码从EnemyAttack移到了FistCollider ,让我们在EnemyAttack中使用FistCollider 。 这是代码:
使用UnityEngine; 公共课程EnemyAttack:MonoBehaviour { 公共FistCollider LeftFist; 公共FistCollider RightFist; 私人Animator _animator; 私人GameObject _player; 无效Awake() { _player = GameObject.FindGameObjectWithTag(“ Player”); _animator = GetComponent (); } void OnTriggerEnter(对撞机其他) { 如果(other.gameObject == _player) { _animator.SetBool(“ IsNearPlayer”,true); } print(“使用_player输入触发器”); } void OnTriggerExit(Collider other) { 如果(other.gameObject == _player) { _animator.SetBool(“ IsNearPlayer”,false); } print(“使用_player退出触发器”); } private void Attack() { 如果(LeftFist.IsCollidingWithPlayer()|| RightFist.IsCollidingWithPlayer()) { _player.GetComponent ()。TakeDamage(10); } } }
这是我们代码中的更改:
- 首先,我们创建新的公共变量: LeftArm和RightArm ,它们是我们刚刚创建的FistCollider脚本。
- 我们清理了很多代码,特别是Collision部分以及与之相关的所有内容。
- 在Attack()中,我们使用新的FistCollider与玩家发生碰撞,然后在触发动画中的攻击事件时,检查玩家是否被击中。 如果他们这样做(意味着骑士的拳头与玩家相撞),玩家将受到伤害。
完成脚本后,我们需要做的最后一件事就是确保将FirstCollider对象附加到播放器上。
我们可以将我们的游戏对象直接附加到该地点,脚本将被自动选择。
完成后,我们应该有以下内容:
ew,这是很多工作!
在过去的两天中,我们创建了健康系统,然后重新探视了敌方骑士的网状对撞机存在的一些问题,例如在它们上方行走而无法与玩家精确碰撞的情况。
我们还分离了具有攻击冲突功能的代码,同时仍使我们原来的冲突脚本正常运行。
既然我们终于可以为玩家带来健康,那么明天,我们要做的下一件事就是在玩家的生命值达到0时开始最终游戏状态。
在那之前,度过一个愉快的夜晚,我要睡觉了!
资料来源:第20天
访问Unity VR开发的100天主页。
访问我们的主页