所以我想在Unity中使用UniRx来尝试反应式编程。我给自己一个简单的任务。为W A S D键按键流,按任意键时打印到屏幕,并在WASD序列发生时显示Combi happened
。
问题在于,如果序列在流的开头显示为完全,那么它不会被“识别”,也不会发出任何值。
这就是我的意思: 首先按下W A S D ..第一个组合未被识别,但所有后续组合都被识别。
在这里,我在开头按一个不同的字母然后做模式,一切都按预期工作。
以下是代码:
public class TestController : MonoBehaviour {
// Use this for initialization
void Start(){
var tick = this.UpdateAsObservable();
var w = tick.Where(_ => Input.GetKeyDown(KeyCode.W)).Select(_ => "W");
var s = tick.Where(_ => Input.GetKeyDown(KeyCode.S)).Select(_ => "S");
var d = tick.Where(_ => Input.GetKeyDown(KeyCode.D)).Select(_ => "D");
var a = tick.Where(_ => Input.GetKeyDown(KeyCode.A)).Select(_ => "A");
w.Subscribe(Debug.Log).AddTo(this);
s.Subscribe(Debug.Log).AddTo(this);
d.Subscribe(Debug.Log).AddTo(this);
a.Subscribe(Debug.Log).AddTo(this);
var keys = Observable.Merge(w, a, s, d);
var Combi = new[]{"W", "A", "S", "D"};
var combiFound = keys.SelectMany(keys.Take(4).Buffer(4))
.Where(list => list.SequenceEqual(Combi));
combiFound.Subscribe(_ => { Debug.LogWarning("Combi Happened!"); }, Debug.LogException).AddTo(this);
}
}
这到底发生了什么?
答案 0 :(得分:1)
我没有反应专家,但我认为解释它的是SelectMany。在那里你说只有从缓冲区中提取多个项目时,observable才会填充一个项目,因此会调用subscribe。我把它更改为这个crumby修复程序,所以至少它会从第一次尝试登录,但它并不优雅。我希望看到有人做一个声明。
var Combi = new[] { "W", "A", "S", "D" };
var buffer = keys.Take(4).Buffer(4);
var combiFound = keys.SelectMany(buffer)
.Where(list => list.SequenceEqual(Combi));
buffer.Subscribe(CombiHappend(), Debug.LogException).AddTo(this);
combiFound.Subscribe(CombiHappend(), Debug.LogException).AddTo(this);
}
private static System.Action<IList<string>> CombiHappend()
{
return (items) => { Debug.LogWarning("Combi Happened!" + string.Join(",", items.ToArray())); };
}
答案 1 :(得分:0)
我很高兴找到这个快速教程演示:Link to solution 这正是我想要实现的目标!
所以这是工作代码:
// Use this for initialization
private void Start(){
var keyCode = new[]{"W", "A", "S", "D"};
var updateTick = this.UpdateAsObservable();
// Get a stream for each key
var w = updateTick.Where(_ => Input.GetKeyDown(KeyCode.W)).Select(_ => "W");
var s = updateTick.Where(_ => Input.GetKeyDown(KeyCode.S)).Select(_ => "S");
var d = updateTick.Where(_ => Input.GetKeyDown(KeyCode.D)).Select(_ => "D");
var a = updateTick.Where(_ => Input.GetKeyDown(KeyCode.A)).Select(_ => "A");
// Display the pressed key
w.Subscribe(Debug.Log).AddTo(this);
s.Subscribe(Debug.Log).AddTo(this);
d.Subscribe(Debug.Log).AddTo(this);
a.Subscribe(Debug.Log).AddTo(this);
// Stream of all previous keys combined
var keyStream = Observable.Merge(w, a, s, d);
// Stream of events when sequence is found
var keyCodeFound = keyStream.Where(key => key == keyCode.First())
.SelectMany(key => keyStream.StartWith(key).Buffer(keyCode.Length).First())
.Where(list => list.SequenceEqual(keyCode));
// Whenever the sequence is found, a message is displayed on the screen
keyCodeFound.Subscribe(CombiHappened(), Debug.LogException)
.AddTo(this);
}
private static System.Action<IList<string>> CombiHappened() => items => {
Debug.LogWarning("Key combination happened! " + string.Join(",", items.ToArray()));
};
我很开心。现在我应该尝试寻找我指定的任何序列。希望它顺利进行!