C# 团结一致的承诺

C# 团结一致的承诺,c#,unity3d,unityscript,C#,Unity3d,Unityscript,我想要一个角色类,从MonoBehavior继承并公开大量的方法:Walk、Attack 但是,假设两个组件同时使用这些方法,我希望对操作进行排队,并通过某种方式通知组件它们的操作已经执行 在Javascript标准中,我会这样做: var Character = function ( ) { this._deferred = new Deferred( ); }; Character.prototype.walk = function ( ) { return this._d

我想要一个角色类,从MonoBehavior继承并公开大量的方法:Walk、Attack

但是,假设两个组件同时使用这些方法,我希望对操作进行排队,并通过某种方式通知组件它们的操作已经执行

在Javascript标准中,我会这样做:

var Character = function ( ) {
    this._deferred = new Deferred( );
};

Character.prototype.walk = function ( ) {
    return this._deferred = this._deferred.then( function ( ) {
        // Do the actual walk
    } );
};

Character.prototype.attack = function ( ) {
    return this._deferred = this._deferred.then( function ( ) {
        // Do the actual attack
    } );
};

var character = new Character( );

// Component A
character.walk( ).then( function ( ) {
    // Executes when the walk is done
} );

// Component B
character.attack( ).then( function ( ) {
    // Executes when the walk AND attack is done
} );
使用Unity/C#的正确方法是什么?

序言
  • 对于答案,我将使用“我想将操作排队”作为您问题的描述
  • 有很多方法可以解决这个问题。我并不假装很全面
  • 即使在JS中,我也会考虑使用字符队列作为错误选择的承诺。
  • 我从未编译、运行或测试过我在这里展示的代码:D
  • C语言的承诺# github上有一个。我从未使用过它,但代码似乎没有包含任何阻止它在Unity中使用的内容。无论如何,你可以试试看

    使用 对于这个问题,我肯定会使用一些TCommand的
    Queue
    。唯一的问题是使用什么作为TCommand。这里我给你举两个例子。但是,像往常一样,还有更多的选择

    某类 大概是这样的:

    public enum CommandUpdateResult
    {
        Ongoing,
        Finished
    }
    
    public interface ICommand
    {
       CommandUpdateResult Update();
    }
    
    public class RunCommand: ICommand
    {
        // Bla-bla-bla
    }
    
    public class AttackCommand: ICommand
    {
        // Bla-bla-bla
    }
    
    
    public class Character: MonoBehaviour
    {
        private Queue<ICommand> commandQueue;
    
        public void Awake()
        {
            commandQueue = new Queue<ICommand>();
        }
    
        public void Update()
        {
            if (commandQueue.Count > 0 && commandQueue.Peek().Update() == CommandUpdateResult.Finished)
                commandQueue.Dequeue();
        }
    
        public void EnqueueCommand(ICommand command)
        {
            commandQueue.Enqueue(command);
        }
    }
    
    public class SomeClassThatUsesCharacter
    {
        private Character character;
        public void SomeMethodThatUsesCharacter()
        {
            character.EnqueueCommand(new RunCommand(bla-bla-bla));
            character.EnqueueCommand(new AttackCommand(bla-bla-bla));
        }
    }
    
    public enum CommandUpdateResult
    {
    不间断的
    完成了
    }
    公共接口ICommand
    {
    CommandUpdateResult Update();
    }
    公共类RunCommand:ICommand
    {
    //呜呜呜呜
    }
    公共类攻击命令:ICommand
    {
    //呜呜呜呜
    }
    公共阶级特征:单一行为
    {
    专用队列命令队列;
    公共图书馆
    {
    commandQueue=新队列();
    }
    公共无效更新()
    {
    if(commandQueue.Count>0&&commandQueue.Peek().Update()==CommandUpdateResult.Finished)
    commandQueue.Dequeue();
    }
    public void排队命令(ICommand命令)
    {
    命令队列。排队(命令);
    }
    }
    public类使用schracter的类
    {
    个性;
    使用schracter()的公共void方法
    {
    character.EnqueueCommand(newrunCommand(blablabla));
    character.EnqueueCommand(新攻击命令(blablabla));
    }
    }
    
    迭代器 使用IEnumerator最简单(但不是很优雅)的方法是将它与一些无限元素一起使用

    公共类字符:单行为
    {
    专用队列命令队列;
    私有IEnumerator命令QueueCoroutine()
    {
    while(true)
    {
    如果(commandQueue.Count>0)
    产生返回start例程(commandQueue.Peek());
    其他的
    返回新的WaitForFixedUpdate();
    }
    }
    公共图书馆
    {
    commandQueue=新队列();
    start例程(CommandQueueCoroutine());
    }
    公共无效更新()
    {
    if(commandQueue.Count>0&&commandQueue.Peek().Update()==CommandUpdateResult.Finished)
    commandQueue.Dequeue();
    }
    公共void排队(IEnumerator命令)
    {
    命令队列。排队(命令);
    }
    IEnumerator运行命令()
    {
    而(Jenny.Tells(“Run”))
    {
    transform.position.x+=1;
    返回新的WaitForFixedUpdate();
    }
    }
    IEnumerator攻击命令(恶棍恶棍)
    {
    坏人。死();
    屈服断裂;
    }
    }
    public类使用schracter的类
    {
    个性;
    使用schracter()的公共void方法
    {
    character.Enqueue(character.RunCommand());
    character.Enqueue(character.AttackCommand(someBadGuy));
    }
    }
    
    一个非常好的Unity Promise库:请参阅相关博客


    或者,我认为您也可以使用观察者对
    Walk
    Attack
    事件做出反应的接收方法。见

    不清楚。您是否希望在C#中实现承诺?或者您想要一种将角色的命令排队的方法吗?回答“两者”意味着你试图用错误的仪器来解决问题。看看行动,功能,也许delegate@SergeyKrusch我的问题是关于连锁指挥的“统一方式”。在Javascript中,我可能会使用承诺之类的东西,但在统一世界中,这可能是错误的。
    public class Character: MonoBehaviour
    {
        private Queue<IEnumerator> commandQueue;
    
        private IEnumerator CommandQueueCoroutine()
        {
            while (true)
            {
                if (commandQueue.Count > 0)
                    yield return StartCoroutine(commandQueue.Peek());
                else
                    yield return new WaitForFixedUpdate();
            }
        }
    
        public void Awake()
        {
            commandQueue = new Queue<ICommand>();
            StartCoroutine(CommandQueueCoroutine());
        }
    
        public void Update()
        {
            if (commandQueue.Count > 0 && commandQueue.Peek().Update() == CommandUpdateResult.Finished)
                commandQueue.Dequeue();
        }
    
        public void Enqueue(IEnumerator command)
        {
            commandQueue.Enqueue(command);
        }
    
        IEnumerator RunCommand()
        {
            while (Jenny.Tells("Run"))
            {
                transform.position.x += 1;
                yield return new WaitForFixedUpdate();
            }
        }
    
        IEnumerator AttackCommand(BadGuy badGuy)
        {
            badGuy.Die();
            yield break;
        }
    }
    
    public class SomeClassThatUsesCharacter
    {
        private Character character;
    
        public void SomeMethodThatUsesCharacter()
        {
            character.Enqueue(character.RunCommand());
            character.Enqueue(character.AttackCommand(someBadGuy));
        }
    }