You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 22:25:13