【问题标题】:Get a type from variable and use as argument for generic method从变量中获取类型并用作泛型方法的参数
【发布时间】:2017-07-22 23:09:42
【问题描述】:

我正在为 xna 中的一个简单游戏引擎开发一些东西,我将用于未来的项目。它绝对受到 Unity 框架的启发。 我目前正在开发一个游戏对象和组件系统,并且一直在克隆游戏对象。

这就是我尝试实现它的方式,

public static GameObject CloneGameObject(GameObject obj, Vector2 position, float scale)
{
    var clone = new GameObject(); //Create a entirely new gameobject
    foreach (var comp in obj.components) //Clone all the components
    {
        Type t = comp.GetType(); 
        clone.components.Add(Component.CloneComponent<t>()); //This obviously doesn't work
    }
    clone.position = position;
    clone.scale = scale;

    AllGameObjects.Add(clone);
    return clone;
}

我遇到的问题是如何让组件类型用作通用参数。

我目前对要克隆的组件所做的只是更改克隆的所有者:

public static TComponent CloneComponent<TComponent>(Component toClone) where TComponent : Component, new()
{
    var clone = new TComponent();

    clone.gameObject = toClone.gameObject;

    return clone;
}

Component 系统很简单,所有的组件都继承自 Component 类。

例子:

class PlayerController : Component
{
    public float jumpForce = 5;
    public float walkSpeed = 2;

    RigidBody rb;
    Collider col;

    public override void Start()
    {
        base.Start();

        rb = gameObject.GetComponent<RigidBody>();
        col = gameObject.GetComponent<Collider>();
    }

    bool canJump { get { return jumps > 0; } }
    int jumps = 1;
    int maxJumps = 1;
    public override void Update(GameTime gameTime)
    {
        rb.velocity = new Vector2(Input.GetAxisInputs(Keyboard.GetState(), "Horizontal") * walkSpeed, rb.velocity.Y);
        if (Input.GetKeyOnDown(Keyboard.GetState(), Keys.Space) && canJump)
        {
            rb.velocity = new Vector2(rb.velocity.X, -jumpForce);
            jumps--;
        }

        if (!col.PlaceIsFree(new Vector2(0, 1)))
            jumps = maxJumps;
            
        base.Update(gameTime);
    }
}

(无法正确格式化代码示例,所以我只使用了 css sn-p://)

我并没有要求任何关于克隆自身的事情,只是简单地询问如何获得正确的通用参数,或者是否有其他方法可以实现这一点。

【问题讨论】:

    标签: c# visual-studio generics xna game-engine


    【解决方案1】:

    你应该改变CloneComponent函数的签名:

    public static TComponent CloneComponent<TComponent>(TComponent toClone) where TComponent : Component, new()
    

    然后你应该像这样调用这个函数:

    foreach (var comp in obj.components) //Clone all the components
    {
        clone.components.Add(Component.CloneComponent(comp));
    }
    

    您还可以使用语法糖来简化调用代码:

    public static TComponent Clone<TComponent>(this TComponent toClone) where TComponent : Component, new()
    {
        if (toClone == null)
        {
            throw new ArgumentNullException(nameof(toClone));
        }
    
        var clone = new TComponent();
    
        clone.gameObject = toClone.gameObject;
    
        return clone;
    }
    

    循环将是:

    foreach (var comp in obj.components) //Clone all the components
    {
        clone.components.Add(comp.Clone());
    }
    

    【讨论】:

      猜你喜欢
      • 2021-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多