Unity基于响应式编程(Reactiveprogramming)⼊门
系列⽬录
背景
前有慕容⼩匹夫的⼀篇《解构C#游戏框架uFrame兼谈游戏架构设计》,引⽤⽂中内容
uFrame是提供给3D开发者使⽤的⼀个框架插件,它本⾝模仿了MVVM这种架构模式(事实上并不包含Model部分,且多出了
Controller部分)。因为⽤于Unity3D,所以它向开发者提供了⼀套基于Editor的可视化编辑⼯具,可以⽤来管理代码结构等。需要指出的是它的⼀个重要的理念,同时也是软件⼯程中的⼀个重要理念就是关注分离(Separation of concern,SoC)。uFrame 借助控制反转(IoC)/依赖注⼊(DI)实现了这种分离,从⽽进⼀步实现了MVVM这种模式。且在1.5版本之后,引⼊了UniRx
库,引进了响应式编程的思想。
读起来⾼⼤上,本⽂主要想从实际出发,着⼿最后⼀句“且在1.5版本之后,引⼊了UniRx库,引进了响应式编程的思想。”,在Unity中如何使⽤响应式编程,如何使⽤UniRx库。
当然⼀下列出这么多新概念性的东西,作为新⼿必然理解起来有困难的,当然我也希望你是天赋迥异的⼈。这⾥列出⼏点,如果你不了解,请⾃⾏去学习或者复习,回来在看也不迟。
1、Linq基础,Linq的本质及与传统命令式编程的区别和优点
2、声明式编程和命令式编程的概念和区别
3、什么是响应式编程
4、什么是观察者模式
5、软件编程中Stream的概念
好了时间过去了,让我们简单的说下什么是响应式编程。这⾥也不废话,引⽤⼀段,看的懂得⾃然明⽩,不懂得还是不明⽩
什么是反应式编程:反应式编程(Reactive programming)简称Rx,他是⼀个使⽤LINQ风格编写基于观察者模式的异步编程模型。
简单点说Rx = Observables + LINQ + Schedulers。
这⾥为什么要在游戏开发中引⼊响应式编程Rx,答案是游戏特别适合RX编程,因为在游戏中⼴泛应⽤了时间(帧)和事件(UI)的概念,时间本⾝是⼀种流,⽽事件也是基于时间的⼀种信号(并不是特别准确,意会),⽽这正是RX所擅长的。
实现
本⽂以系列⽂章中的精灵⿏标移动和序列帧动画为基础,没有基础的先参考下传统实现⽅式⼀下两篇⽂章
这⾥引⼊了UniRx库,来实现基于响应式编程及声明式编程代码重构,代码如下:
using UnityEngine;
using UniRx;
public class PlayerController : MonoBehaviour
{
public float speed;
private Vector3 moveDirection;
private int currentTexture = 0;
public Sprite[] textureArray;
// Use this for initialization
void Start()
{
//⿏标控制移动,每帧更新
Observable.EveryUpdate()
.Subscribe(_ =>
reactive声明类型{
//1、获得当前位置
Vector3 curenPosition = ansform.position;
//2、获得⽅向
if (Input.GetButton("Fire1"))
{
Vector3 moveToward = Camera.main.usePosition);
moveDirection = moveToward - curenPosition;
moveDirection.z = 0;
moveDirection.Normalize();
}
//3、插值移动
Vector3 target = moveDirection * speed + curenPosition;
transform.position = Vector3.Lerp(curenPosition, target, Time.deltaTime);
});
//帧动画
SpriteRenderer spriteRenderer = GetComponent<SpriteRenderer>();
//定时器每隔5帧
Observable.IntervalFrame(5).Subscribe(_ =>
{
currentTexture++;
if (currentTexture >= textureArray.Length)
{
currentTexture = 0;
}
spriteRenderer.sprite = textureArray[currentTexture];
});
}
}
是的没有看错,你没有发现熟悉的Update函数,如果说以上函数让你看到就是把所有代码就放在了Start⾥⾯⽽已,我们再重构⼀下代码,使⽤提取⽅法,看看效果,这就是声明式编程的魅⼒,程序可读性增强,更适合⼈类的思维⽅式
using UnityEngine;
using UniRx;
public class PlayerController : MonoBehaviour
{
public float speed;
private Vector3 moveDirection;
private int currentTexture = 0;
public Sprite[] textureArray;
// Use this for initialization
void Start()
{
//⿏标控制移动,每帧更新
PlayerMove();
//⾓⾊帧动画
PlayerAnimation();
}
/// <summary>
/// ⾓⾊帧动画控制
/// </summary>
private void PlayerAnimation()
{
SpriteRenderer spriteRenderer = GetComponent<SpriteRenderer>();
//定时器每隔5帧
Observable.IntervalFrame(5).Subscribe(_ =>
{
currentTexture++;
if (currentTexture >= textureArray.Length)
{
currentTexture = 0;
}
spriteRenderer.sprite = textureArray[currentTexture];
});
}
/// <summary>
/// ⿏标控制移动,每帧更新
/// </summary>
private void PlayerMove()
{
Observable.EveryUpdate()
.Subscribe(_ =>
{
//1、获得当前位置
Vector3 curenPosition = ansform.position;
//2、获得⽅向
if (Input.GetButton("Fire1"))
{
Vector3 moveToward = Camera.main.usePosition);
moveDirection = moveToward - curenPosition;
moveDirection.z = 0;
moveDirection.Normalize();
}
//3、插值移动
Vector3 target = moveDirection*speed + curenPosition;
transform.position = Vector3.Lerp(curenPosition, target, Time.deltaTime);
});
}
}
总结
这⾥记住UniRx两个⽅法 Observable.EveryUpdate,Observable.IntervalFrame(这⾥还记得以前⽂章
⾥提的定时器吗,这个定时器怎么样简单吧),还有ObservableWWW.GetWWW(),采⽤声明式编程的⽅式,看看函数名就知道是⼲什么的了吧,还⽤看⽂档或者解释什么吗?
⽂章内容⽐较简单,实现的功能也简单,函数也简单,希望你们喜欢。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论