Unity中如何在父物体脚本中仅用子物体hitBox碰撞器检测伤害
问题描述
我是Unity新手,正在制作一个骷髅敌人,该GameObject下至少有4个碰撞器子物体,但我只想通过名为“hitBox”的子物体碰撞器检测对玩家造成的伤害。我知道可以给hitBox添加脚本并使用OnTriggerEnter2D函数实现,但希望仅通过挂载在骷髅GameObject上的Skeleton.cs脚本来完成。请问是否有类似OnChildTriggerEnter2D的函数可以解决这个问题?
附上我的代码:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Skeleton : MonoBehaviour { #region Public Variables public float attackDistance; public float moveSpeed; public float timer; public GameObject hotZone; public GameObject triggerArea; public float hp_skel; [HideInInspector] public Transform target; [HideInInspector] public bool inRange; #endregion #region Private Variables private Animator anim; private float distance; public bool attackMode; private float intTimer; #endregion void Awake() { intTimer = timer; anim = GetComponent<Animator>(); } void Update() { if (inRange) { EnemyLogic(); } } void EnemyLogic() { distance = Vector2.Distance(transform.position, target.position); if(distance > attackDistance) { Move(); StopAttack(); } else if(attackDistance >= distance) { Attack(); } } void Move() { anim.SetInteger("Idle", 1); anim.SetBool("canWalk", true); if (!anim.GetCurrentAnimatorStateInfo(0).IsName("attack")) { Vector2 targetPosition = new Vector2(target.position.x, transform.position.y); transform.position = Vector2.MoveTowards(transform.position, targetPosition, moveSpeed * Time.deltaTime); } } void Attack() { timer = intTimer; attackMode = true; anim.SetInteger("Idle", 1); anim.SetBool("canWalk", false); anim.SetBool("Attack", true); } void StopAttack() { attackMode = false; anim.SetBool("Attack", false); } public void Flip() { Vector3 rotation = transform.eulerAngles; if(target.position.x < transform.position.x) { rotation.y = 180f; } else { rotation.y = 0f; } transform.eulerAngles = rotation; } }
解决方案
Unity没有内置的OnChildTriggerEnter2D函数,但可以通过以下两种方式实现需求:
方法1:给hitBox添加极简转发脚本(推荐)
虽然你不想给hitBox单独加脚本,但这个脚本仅负责把触发事件传递给父物体的Skeleton组件,代码非常轻量:
创建一个名为HitBoxForwarder.cs的脚本,挂载到hitBox物体上:
using UnityEngine; public class HitBoxForwarder : MonoBehaviour { private Skeleton parentSkeleton; void Awake() { // 获取父物体的Skeleton组件 parentSkeleton = GetComponentInParent<Skeleton>(); } void OnTriggerEnter2D(Collider2D other) { // 只在攻击模式下触发伤害检测 if (parentSkeleton.attackMode) { parentSkeleton.OnHitBoxTrigger(other); } } }
然后在你的Skeleton.cs中添加处理伤害的函数:
// 新增:处理hitBox的触发事件 public void OnHitBoxTrigger(Collider2D other) { // 检测碰撞对象是否是玩家(根据你的玩家标签调整) if (other.CompareTag("Player")) { // 这里写对玩家造成伤害的逻辑,比如调用玩家的受伤函数 // other.GetComponent<PlayerHealth>().TakeDamage(1); Debug.Log("玩家受到伤害"); } }
方法2:在Skeleton脚本中主动检测hitBox的碰撞(无需额外脚本)
如果不想给hitBox加任何脚本,可以在攻击动画的关键帧(比如挥砍动作命中的瞬间)调用一个检测函数,主动判断hitBox范围内是否有玩家:
首先在Skeleton.cs中添加以下代码:
// 新增:获取hitBox的碰撞器组件 private Collider2D hitBoxCollider; void Awake() { intTimer = timer; anim = GetComponent<Animator>(); // 找到hitBox子物体的碰撞器 hitBoxCollider = transform.Find("hitBox").GetComponent<Collider2D>(); } // 新增:在攻击动画的关键帧调用这个函数(需要在Animator窗口给动画添加事件) public void CheckHitBox() { if (!attackMode) return; // 检测hitBox范围内的玩家碰撞器 Collider2D[] hitColliders = Physics2D.OverlapBoxAll(hitBoxCollider.bounds.center, hitBoxCollider.bounds.size, 0f); foreach (var collider in hitColliders) { if (collider.CompareTag("Player")) { // 这里写伤害逻辑 Debug.Log("玩家受到伤害"); // 防止一次攻击多次触发伤害 break; } } }
然后在Unity的Animator窗口中,选中骷髅的攻击动画,在动画的命中关键帧位置添加一个动画事件,调用Skeleton组件的CheckHitBox函数即可。
注意:方法2需要精准控制动画事件的时间,不如方法1的触发事件准确,但完全不需要额外脚本。
内容的提问来源于stack exchange,提问作者mumber162
相关产品推荐
相关产品推荐

