Promises with Unity
本文关键字:Unity with Promises | 更新日期: 2023-09-27 18:05:10
我想要一个字符类,从MonoBehavior继承并暴露少量方法:行走,攻击,…
然而,假设两个组件同时使用这些方法,我希望将操作排队,并有一些方法通知组件它们的操作已经执行。
在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中,我也会考虑使用Promises来排队字符命令是错误的选择。
- 我从来没有编译,运行或测试的代码,我现在在这里:D
我肯定会使用一些TCommand的Queue<TCommand>
来解决这个问题。唯一的问题是使用什么作为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));
}
}
IEnumerator
使用IEnumerator最简单(但不是很优雅)的方法是将它与一些无限协程一起使用。
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));
}
}
标题>一个非常好的Unity Promise库:https://github.com/Real-Serious-Games/C-Sharp-Promise,参见相关博客http://www.what-could-possibly-go-wrong.com/promises-for-game-development/
或者,我认为您也可以使用对Walk
和Attack
事件作出反应的观察者进行RX方法。见https://github.com/neuecc/UniRx
现在Unity已经允许你使用:
- TaskCompletionSource作为promise;
- 任务作为未来;
但如果Promise本身更适合您的项目,请尝试使用:C-Sharp-Cancellable-Promise库
这是Real-Serious-Games Promise库的一个分支,更新到最新的。net和,支持Promise取消。