Unity C#中如何让父类触发子类PrimaryInteraction提前返回
Unity C# 继承方法执行控制问题
我是一名学习Unity的学生程序员,遇到以下问题:
- 有
Weapon父类和Gun子类,父类PrimaryInteraction方法中,若武器未被玩家手持(父物体不是Hand),会打印警告并return。 - 子类
Gun重写的PrimaryInteraction调用base.PrimaryInteraction()后,即便父类return,子类仍会执行后续代码。 - 由于大量类继承自相关接口,无法修改
PrimaryInteraction的返回类型,也不想用异常处理,求优雅解决方案。
原代码
Weapon类
public override void PrimaryInteraction() { if (transform.parent == null || transform.parent.name != "Hand") { Debug.LogWarning("Weapon is not being held by a player!"); return; } }
Gun类
public override void PrimaryInteraction() { base.PrimaryInteraction(); if (!_gunModel.Automatic && Time.time >= _nextTimeToFire) { _nextTimeToFire = Time.time + 1f / _gunModel.FireRate; Shoot(); return; } _isShooting=true; }
输入处理代码
public void HandlePrimaryAction() { GameObject objectInHand = _handController.GetObjectInHand(); if (HandleObjectInHand(objectInHand)) return; if (Physics.Raycast(_playerCamera.transform.position, _playerCamera.transform.forward, out RaycastHit hit, 5f, _interactableLayer)) { HandleRaycastHit(hit); } } private bool HandleObjectInHand(GameObject obj) { if (obj == null) return false; if (obj.TryGetComponent(out IConsumableObject consumable)) { _inventoryManager.ConsumeCurrentItem(); return true; } if (obj.TryGetComponent(out Weapon weapon)) { weapon.PrimaryInteraction(); return true; } return false; } private void HandleRaycastHit(RaycastHit hit) { GameObject objectInHand = _handController.GetObjectInHand(); if (hit.collider.TryGetComponent(out IRequiredObjectInteraction requiredInteraction) && objectInHand != null) { requiredInteraction.RequiredObjectInteraction(objectInHand); } if (hit.collider.TryGetComponent(out IInteractableObject interactable)) { interactable.PrimaryInteraction(); _currentInteractableObject = interactable; } if (hit.collider.TryGetComponent(out DraggableObject draggable) && !objectInHand) { DragObject(draggable); } }
优雅解决方案
方案1:提取父类校验逻辑为独立方法
在Weapon类中新增受保护的校验方法,子类调用该方法判断是否继续执行:
修改后的Weapon类:
public override void PrimaryInteraction() { if (!IsWeaponHeld()) { Debug.LogWarning("Weapon is not being held by a player!"); return; } } protected bool IsWeaponHeld() { return transform.parent != null && transform.parent.name == "Hand"; }
修改后的Gun类:
public override void PrimaryInteraction() { base.PrimaryInteraction(); if (!IsWeaponHeld()) return; // 新增校验逻辑 if (!_gunModel.Automatic && Time.time >= _nextTimeToFire) { _nextTimeToFire = Time.time + 1f / _gunModel.FireRate; Shoot(); return; } _isShooting=true; }
方案2:父类设置受保护的状态标记
在Weapon类中添加布尔字段标记武器是否可交互,子类通过该字段判断:
修改后的Weapon类:
protected bool _canInteract = false; public override void PrimaryInteraction() { _canInteract = transform.parent != null && transform.parent.name == "Hand"; if (!_canInteract) { Debug.LogWarning("Weapon is not being held by a player!"); return; } }
修改后的Gun类:
public override void PrimaryInteraction() { base.PrimaryInteraction(); if (!_canInteract) return; // 新增状态判断 if (!_gunModel.Automatic && Time.time >= _nextTimeToFire) { _nextTimeToFire = Time.time + 1f / _gunModel.FireRate; Shoot(); return; } _isShooting=true; }
方案3:输入处理阶段提前校验
既然PrimaryInteraction仅应在武器被手持时调用,直接在输入处理阶段做校验,避免无效调用:
修改HandleObjectInHand方法:
private bool HandleObjectInHand(GameObject obj) { if (obj == null) return false; if (obj.TryGetComponent(out IConsumableObject consumable)) { _inventoryManager.ConsumeCurrentItem(); return true; } if (obj.TryGetComponent(out Weapon weapon)) { // 提前校验是否手持 if (weapon.transform.parent != null && weapon.transform.parent.name == "Hand") { weapon.PrimaryInteraction(); } else { Debug.LogWarning("Weapon is not being held by a player!"); } return true; } return false; }
此方案可选择保留或移除Weapon类PrimaryInteraction中的校验逻辑作为双重保障。
内容的提问来源于stack exchange,提问作者Oroitz Lago Ramos
相关产品推荐
相关产品推荐

