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

Unity中如何通过ObstacleController父类引用调用子类UpdateData方法?

解决方案:统一敌人生成系统的Controller数据更新

针对父类无法统一调用子类UpdateData、嵌套泛型导致代码冗余的问题,以下是几种适配Unity安卓游戏场景的实用方案:

1. 抽象统一的ControllerData基类+非泛型入口方法

核心思路是将所有敌人的数据类抽象到一个基类,给父类控制器添加非泛型的UpdateData入口,内部完成类型校验与转换,既保留子类的强类型数据处理,又支持父类统一调用。

步骤代码:

1.1 定义统一的数据基类

public abstract class BaseObstacleData
{
    // 所有敌人共有的基础字段,比如生成权重、ID等
    public int ObstacleId;
    public float SpawnPriority;
}

// EnemyA专属数据
public class EnemyAData : BaseObstacleData
{
    public int AttackDamage;
    public float MoveSpeed;
}

// EnemyB专属数据
public class EnemyBData : BaseObstacleData
{
    public float ExplosionRadius;
    public int MaxHealth;
}

1.2 重构控制器抽象层

调整接口与抽象父类,添加非泛型统一调用入口:

// 非泛型接口,用于父类统一调用
public interface IObstacleController
{
    void UpdateData(BaseObstacleData data);
}

// 泛型抽象父类,保留子类强类型处理
public abstract class ObstacleController<TData> : IObstacleController 
    where TData : BaseObstacleData
{
    // 子类实现强类型数据更新
    public abstract void UpdateData(TData data);

    // 非泛型入口,内部完成类型转换
    public void UpdateData(BaseObstacleData data)
    {
        if (data is TData typedData)
        {
            UpdateData(typedData);
        }
        else
        {
            Debug.LogError($"数据类型不匹配:{GetType().Name} 无法处理 {data.GetType().Name}");
        }
    }
}

// EnemyA控制器子类
public class EnemyAController : ObstacleController<EnemyAData>
{
    public override void UpdateData(EnemyAData data)
    {
        // 强类型处理EnemyA数据更新
        Debug.Log($"更新EnemyA:伤害={data.AttackDamage},移速={data.MoveSpeed}");
    }
}

1.3 统一调用示例

// 用非泛型接口存储所有控制器
List<IObstacleController> _allControllers = new List<IObstacleController>();

_allControllers.Add(new EnemyAController());
_allControllers.Add(new EnemyBController());

// 遍历统一执行数据更新
foreach (var controller in _allControllers)
{
    BaseObstacleData enemyData = GetRandomEnemyData(); // 自定义获取随机敌人数据的方法
    controller.UpdateData(enemyData);
}

2. 工厂模式优化控制器创建与数据绑定

如果需要批量生成控制器并绑定数据,用工厂模式封装类型映射逻辑,避免手动处理类型匹配的重复代码:

public static class ObstacleControllerFactory
{
    // 缓存数据类型与控制器创建器的映射
    private static readonly Dictionary<Type, Func<IObstacleController>> _controllerMap = new();

    static ObstacleControllerFactory()
    {
        // 注册所有敌人数据与对应控制器的创建逻辑
        _controllerMap.Add(typeof(EnemyAData), () => new EnemyAController());
        _controllerMap.Add(typeof(EnemyBData), () => new EnemyBController());
    }

    // 根据数据实例创建并初始化控制器
    public static IObstacleController CreateAndInitController(BaseObstacleData data)
    {
        if (_controllerMap.TryGetValue(data.GetType(), out var creator))
        {
            var controller = creator();
            controller.UpdateData(data);
            return controller;
        }
        
        Debug.LogError($"未找到对应的数据类型:{data.GetType().Name}");
        return null;
    }
}

使用示例:

var enemyAData = new EnemyAData { AttackDamage = 10, MoveSpeed = 3f };
var enemyAController = ObstacleControllerFactory.CreateAndInitController(enemyAData);

3. 简化泛型接口(可选)

如果原有的IObstacleController带5个泛型参数过于复杂,考虑将部分泛型参数合并到BaseObstacleData中,或者用组合类代替多层泛型,减少嵌套复杂度。比如将敌人的行为配置、资源引用等合并到数据基类的子类中,避免接口泛型参数过多导致的维护问题。


内容的提问来源于stack exchange,提问作者Džoni

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 01:50:29