C# 找不到默认构造函数

C# 找不到默认构造函数,c#,generics,unity3d,types,createinstance,C#,Generics,Unity3d,Types,Createinstance,我正在为我的unity游戏制作一个有限状态机: using UnityEngine; using System; public class StateMachine : MonoBehaviour { private State currentState; public void ChangeState<T>() where T : State { if (currentState != null) { currentSta

我正在为我的unity游戏制作一个有限状态机:

using UnityEngine;
using System;
public class StateMachine : MonoBehaviour {

    private State currentState;

    public void ChangeState<T>() where T : State {
        if (currentState != null) {
            currentState.Exit ();
        }
        currentState = (T)Activator.CreateInstance (typeof(T), this.gameObject);
        currentState.Enter();
    }

    void Update() {
        if (currentState != null) {
            currentState.Execute ();
        }
    }

    void OnCollisionEnter2D (Collision2D col)
    {
        currentState.ResolveCollision (col);
    }
}
运行状态的简短示例:

using UnityEngine;
public class Running : State {

    public Running(GameObject parent) : base(parent) {}

    public override void Enter ()
    {
        return;
    }

    public override void Execute ()
    {
        if (Input.GetMouseButtonDown (0)) {
            parent.GetComponent<StateMachine> ().ChangeState<Jumping> ();
        }
    }

    public override void Exit ()
    {
        return;
    }

    public override void ResolveCollision (Collision2D col)
    {
        switch (col.gameObject.tag) {
        case "Obstacle":
            break;
        case "Pickupable":
            break;
        case "Enemy":
            break;
        }
        return;
    }
}
其思想是将状态机附加到任何游戏对象上,很容易更改该对象的状态

每个状态都需要父对象来操作,例如更改其位置

每个州还需要能够更改当前状态。传递父游戏对象(状态机连接到的游戏对象)将允许状态访问状态机并对游戏对象进行操作

当改变一个状态时,我总是知道要操作的游戏对象(这显然是状态机所连接的游戏对象),因此要求我不要每次改变状态时都手动传递游戏对象

为了实现这一点,我考虑使用
(T)Activator.CreateInstance(typeof(T),this.gameObject)

调用
ChangeState()时在开始方法中,我得到以下结果:

MissingMethodException:找不到方法:“未找到默认构造函数” 找到正在运行“”的…ctor()

如果我删除参数this.gameobject
(并删除state和running中的构造函数),则游戏运行时不会出错。问题是什么?我如何解决?(仍在使用activator方法)。。。欢迎任何帮助

编辑:

只是让用户创建一个类的对象,然后分配游戏对象就可以满足我的需要,但我认为这不是一个优雅的解决方案:

public void ChangeState(State state) {
    state.parent = this.gameObject;
    if (currentState != null) {
        currentState.Exit ();
    }
    //currentState = (T)Activator.CreateInstance (typeof(T), this.gameObject);
    currentState.Enter ();
}

您还可以使用反射来实例化状态,而不是使用
Activator.CreateInstance
。这有两个好处:

  • 您可以实现一些逻辑来根据参数类型找到正确的构造函数(如果把事情搞砸了,您会得到更多的描述性错误)
  • 它的性能稍微好一点
以下是您如何做到这一点:

var ctor = typeof(T).GetConstructor(new []{typeof(GameObject)})
currentState = ctor.Invoke(new object[]{this.gameObject}) as T;
或者,如果您有一组已知且有限的状态,您可以简单地创建一个工厂类来封装不同状态的实例化。您可以根据泛型类型参数重定向到正确的私有方法,并且在这些私有方法中直接调用构造函数。这表现得更好


尽管如此,如果你想要干净,使用依赖注入框架(Autofac是我的最爱之一)通常是更干净的解决方案。

我不是100%确定这些规则在统一中工作,但一般来说:这段代码可能需要一个无参数构造函数。C#仅在未提供其他构造函数的情况下提供无参数默认构造函数。如果您添加任何自定义的协构造函数,您还必须手动添加一个Parameterelss(如果您需要)。@Christopher感谢您的输入,我尝试向state和running类添加一个无参数构造函数,但我得到了相同的错误。您能发布您的跳跃类吗?@Programmer我从未达到将状态更改为跳跃的程度。当我改为运行时,我得到了错误。跳转只会在每个重写的方法中返回。为什么要麻烦使用反射呢?这就像破解你自己的代码,你仍然需要知道如何创建新的状态,并将
GameObject
作为参数传递。。。后来,这可能很容易打破。。。建议重构这个并获得反射代码。很好,你的解决方案成功了!我不是真的追求性能,而是扩展性。尽管如此,我还是很感谢您提供了其他替代方案,从未听说过autofac:)我遇到了同样的问题,因为IL2CPP正在剥离该构造函数。当我看到你的答案时,我充满了希望,但这对我来说不起作用。由于IL2CPP剥离了构造函数,因此GetConstructor返回null:(
public void ChangeState(State state) {
    state.parent = this.gameObject;
    if (currentState != null) {
        currentState.Exit ();
    }
    //currentState = (T)Activator.CreateInstance (typeof(T), this.gameObject);
    currentState.Enter ();
}
var ctor = typeof(T).GetConstructor(new []{typeof(GameObject)})
currentState = ctor.Invoke(new object[]{this.gameObject}) as T;