UniRxの導入
以下のURLを参考にパッケージマネージャーからインストールする
UniRxの用途
UniRxはイベント処理を扱うのに長けたライブラリです。
UniRxでInputイベントを扱う
using UniRx;
using UnityEngine;
namespace Events
{
public sealed class InputEventProvider : MonoBehaviour
{
/// <summary>
/// 攻撃ボタン入力
/// </summary>
public IReadOnlyReactiveProperty<bool> Attack => _attack;
/// <summary>
/// 移動方向入力
/// </summary>
public IReadOnlyReactiveProperty<Vector3> Move => _move;
/// <summary>
/// ジャンプ入力
/// </summary>
public IReadOnlyReactiveProperty<bool> Jump => _jump;
// 実装
private ReactiveProperty<bool> _attack = new BoolReactiveProperty();
private ReactiveProperty<bool> _jump = new BoolReactiveProperty();
private ReactiveProperty<Vector3> _move = new ReactiveProperty<Vector3>();
private void Start()
{
// Destroy時にDispose()する
_attack.AddTo(this);
_jump.AddTo(this);
_move.AddTo(this);
}
private void Update()
{
// 各種入力をReactivePropertyに反映
_jump.Value = Input.GetButton("Jump");
_attack.Value = Input.GetButton("Attack");
_move.Value = new Vector3(
x:Input.GetAxis("Horizontal"),
y:0,
z:Input.GetAxis("Vertical"));
}
}
}
using System;
using UniRx;
using UnityEngine;
namespace Events
{
/// <summary>
/// 例:Inputをみて移動する
/// </summary>
public class PlayerMove : MonoBehaviour
{
[SerializeField] private float _moveSpeed = 1.0f;
[SerializeField] private InputEventProvider _inputEventProvider;
private CharacterController _characterController;
private void Start()
{
_characterController = GetComponent<CharacterController>();
// ジャンプ
// ジャンプボタン入力イベントを判定
_inputEventProvider.Jump
// ボタンが押された時に、
.Where(x => x)
// 接地中であり、
.Where(_ => _characterController.isGrounded)
// 最後にジャンプしてから1秒以上経過しているなら、
.ThrottleFirst(TimeSpan.FromSeconds(1))
.Subscribe(_ =>
{
// ジャンプ処理を実行する
_characterController.Jump();
});
// 移動処理
_inputEventProvider
.MoveDirection
// 一定値以上入力されたなら
.Where(x => x.magnitude > 0.5f)
.Subscribe(x =>
{
// そっち方向に移動する
_characterController.Move(x.normalized * _moveSpeed);
});
}
}
}
Model-View-(Reactive)Presenterパターン
using UniRx;
using UnityEngine;
namespace MVRP.Models
{
/// <summary>
/// アクションゲームにおけるプレイヤー
/// </summary>
public sealed class PlayerStatusModel : MonoBehaviour
{
/// <summary>
/// 体力
/// </summary>
public IReadOnlyReactiveProperty<int> Health => _health;
/// <summary>
/// 経験値
/// </summary>
public IReadOnlyReactiveProperty<int> Exp => _exp;
private IntReactiveProperty _health= new IntReactiveProperty(100);
private IntReactiveProperty _exp = new IntReactiveProperty(0);
/// <summary>
/// 衝突イベント
/// </summary>
private void OnCollisionEnter(Collision collision)
{
// Enemyに触れたら体力を減らす
if (collision.gameObject.TryGetComponent<Enemy>(out var _))
{
_health.Value -= 10;
}
}
private void OnDestroy()
{
_health.Dispose();
_exp.Dispose();
}
}
}
Viewの実装方法
using DG.Tweening;
using UnityEngine;
using UnityEngine.UI;
namespace MVRP.Views
{
/// <summary>
/// uGUIのSliderをアニメーションさせるコンポーネント(View)
/// </summary>
public sealed class AnimationSlider : MonoBehaviour
{
[SerializeField] private Slider _slider;
public void SetValue(float value)
{
// アニメーションしながらSliderを動かす
DOTween.To(() => _slider.value,
n => _slider.value = n,
value,
duration: 1.0f);
}
}
}
Presenterの実装方法
using MVRP.Models;
using MVRP.Views;
using UniRx;
using UnityEngine;
namespace MVRP.Presenters
{
/// <summary>
/// Playerの体力をViewに反映するPresenter
/// </summary>
public sealed class PlayerHealthPresenter : MonoBehaviour
{
// Model
[SerializeField] private PlayerStatusModel _player;
// View
[SerializeField] private AnimationSlider _animationSlider;
private void Start()
{
// PlayerのHealthを監視
_player.Health
.Subscribe(x =>
{
// Viewに反映
_animationSlider.SetValue((float)x / _player.MaxHealth);
})
.AddTo(this);
}
}
}


コメント