gpt4 book ai didi

c# - 团结一致的 promise

转载 作者:行者123 更新时间:2023-11-30 19:59:30 25 4
gpt4 key购买 nike

我想要一个 Character 类,继承自 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# 的正确方法是什么?

最佳答案

序言

  1. 对于答案,我将使用“我想对操作进行排队”来描述您的问题。
  2. 有很多方法可以解决这个问题。而且我不会假装很全面。
  3. 即使在 JS 中,我也会考虑使用 Promises 来排队字符命令,这是错误的选择。
  4. 我从来没有编译、运行或测试过我在这里展示的代码 :D

C# 中的 Promise

some C# port of Promises在github上。我从未使用过它,但代码似乎不包含任何阻止它在 Unity 中使用的内容。不管怎样,你可以试一试。

使用Queue<>

我肯定会使用 Queue<TCommand>这个问题的一些 TCommand。唯一的问题是使用什么作为 TCommand。我会在这里给你2个例子。但是,和往常一样,还有更多选择。

一些类

像这样:

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));
}
}

IEnumerator

使用 IEnumerator 的最简单(但不是很优雅)的方法是将它与一些无限的 coroutine 一起使用。 .

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));
}
}

关于c# - 团结一致的 promise ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23844076/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com