update space shooter
parent
cd0a6579b8
commit
eff2f1d968
8
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniAnimation.meta
vendored
Normal file
8
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniAnimation.meta
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 22c4a6746deb208479f4b7a040eed7f3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
5
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniAnimation/README.md
vendored
Normal file
5
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniAnimation/README.md
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
# UniFramework.Animation
|
||||
|
||||
一个轻量级的高效率的动画系统。
|
||||
|
||||
支持新的动画文件格式,不再依赖Animator文件来驱动动画,使用方式非常类似于老的Animation系统。
|
7
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniAnimation/README.md.meta
vendored
Normal file
7
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniAnimation/README.md.meta
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6a7da62cb3785ef45b2dda8fa0b3c8e5
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniAnimation/Runtime.meta
vendored
Normal file
8
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniAnimation/Runtime.meta
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8664294e17a47c14c8d12545da2349a1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
106
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniAnimation/Runtime/AnimClip.cs
vendored
Normal file
106
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniAnimation/Runtime/AnimClip.cs
vendored
Normal file
|
@ -0,0 +1,106 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Playables;
|
||||
using UnityEngine.Animations;
|
||||
|
||||
namespace UniFramework.Animation
|
||||
{
|
||||
internal sealed class AnimClip : AnimNode
|
||||
{
|
||||
public readonly string Name;
|
||||
private readonly AnimationClip _clip;
|
||||
public AnimationClipPlayable _clipPlayable;
|
||||
|
||||
/// <summary>
|
||||
/// 动画层级
|
||||
/// </summary>
|
||||
public int Layer = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 动画长度
|
||||
/// </summary>
|
||||
public float ClipLength
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_clip == null)
|
||||
return 0f;
|
||||
if (Speed == 0f)
|
||||
return Mathf.Infinity;
|
||||
return _clip.length / Speed;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 归一化时间轴
|
||||
/// </summary>
|
||||
public float NormalizedTime
|
||||
{
|
||||
set
|
||||
{
|
||||
if (_clip == null)
|
||||
return;
|
||||
Time = _clip.length * value;
|
||||
}
|
||||
|
||||
get
|
||||
{
|
||||
if (_clip == null)
|
||||
return 1f;
|
||||
return Time / _clip.length;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 动画模式
|
||||
/// </summary>
|
||||
public WrapMode WrapMode
|
||||
{
|
||||
set
|
||||
{
|
||||
if (_clip != null)
|
||||
_clip.wrapMode = value;
|
||||
}
|
||||
get
|
||||
{
|
||||
if (_clip == null)
|
||||
return WrapMode.Default;
|
||||
return _clip.wrapMode;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 动画状态
|
||||
/// </summary>
|
||||
public AnimState State { private set; get; }
|
||||
|
||||
public AnimClip(PlayableGraph graph, AnimationClip clip, string name, int layer) : base(graph)
|
||||
{
|
||||
_clip = clip;
|
||||
Name = name;
|
||||
Layer = layer;
|
||||
|
||||
_clipPlayable = AnimationClipPlayable.Create(graph, clip);
|
||||
_clipPlayable.SetApplyFootIK(false);
|
||||
_clipPlayable.SetApplyPlayableIK(false);
|
||||
SetSourcePlayable(_clipPlayable);
|
||||
|
||||
if (clip.wrapMode == WrapMode.Once)
|
||||
{
|
||||
_clipPlayable.SetDuration(clip.length);
|
||||
}
|
||||
|
||||
State = new AnimState(this);
|
||||
}
|
||||
public override void PlayNode()
|
||||
{
|
||||
if (_clip.wrapMode == WrapMode.Once || _clip.wrapMode == WrapMode.ClampForever)
|
||||
{
|
||||
Time = 0;
|
||||
}
|
||||
|
||||
base.PlayNode();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 606e5729d04cc8742a38f58e595c02f9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
196
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniAnimation/Runtime/AnimMixer.cs
vendored
Normal file
196
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniAnimation/Runtime/AnimMixer.cs
vendored
Normal file
|
@ -0,0 +1,196 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Playables;
|
||||
using UnityEngine.Animations;
|
||||
|
||||
namespace UniFramework.Animation
|
||||
{
|
||||
internal sealed class AnimMixer : AnimNode
|
||||
{
|
||||
private const float HIDE_DURATION = 0.25f;
|
||||
private readonly List<AnimClip> _animClips = new List<AnimClip>(10);
|
||||
private AnimationMixerPlayable _mixer;
|
||||
private bool _isQuiting = false;
|
||||
|
||||
/// <summary>
|
||||
/// 动画层级
|
||||
/// </summary>
|
||||
public int Layer { private set; get; }
|
||||
|
||||
|
||||
public AnimMixer(PlayableGraph graph, int layer) : base(graph)
|
||||
{
|
||||
Layer = layer;
|
||||
|
||||
_mixer = AnimationMixerPlayable.Create(graph);
|
||||
SetSourcePlayable(_mixer);
|
||||
}
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
base.Update(deltaTime);
|
||||
|
||||
for (int i = 0; i < _animClips.Count; i++)
|
||||
{
|
||||
var animClip = _animClips[i];
|
||||
if (animClip != null)
|
||||
animClip.Update(deltaTime);
|
||||
}
|
||||
|
||||
bool isAllDone = true;
|
||||
for (int i = 0; i < _animClips.Count; i++)
|
||||
{
|
||||
var animClip = _animClips[i];
|
||||
if (animClip != null)
|
||||
{
|
||||
if (animClip.IsDone == false)
|
||||
isAllDone = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 当子节点都已经完成的时候断开连接
|
||||
if (isAllDone && _isQuiting == false)
|
||||
{
|
||||
_isQuiting = true;
|
||||
StartWeightFade(0, HIDE_DURATION);
|
||||
}
|
||||
if (_isQuiting)
|
||||
{
|
||||
if (Mathf.Approximately(Weight, 0f))
|
||||
DisconnectMixer();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 播放指定动画
|
||||
/// </summary>
|
||||
public void Play(AnimClip newAnimClip, float fadeDuration)
|
||||
{
|
||||
// 重新激活混合器
|
||||
_isQuiting = false;
|
||||
StartWeightFade(1f, 0);
|
||||
|
||||
if (IsContains(newAnimClip) == false)
|
||||
{
|
||||
// 优先插入到一个空位
|
||||
int index = _animClips.FindIndex(s => s == null);
|
||||
if (index == -1)
|
||||
{
|
||||
// Increase input count
|
||||
int inputCount = _mixer.GetInputCount();
|
||||
_mixer.SetInputCount(inputCount + 1);
|
||||
|
||||
newAnimClip.Connect(_mixer, inputCount);
|
||||
_animClips.Add(newAnimClip);
|
||||
}
|
||||
else
|
||||
{
|
||||
newAnimClip.Connect(_mixer, index);
|
||||
_animClips[index] = newAnimClip;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < _animClips.Count; i++)
|
||||
{
|
||||
var animClip = _animClips[i];
|
||||
if (animClip == null)
|
||||
continue;
|
||||
|
||||
if (animClip == newAnimClip)
|
||||
{
|
||||
animClip.StartWeightFade(1f, fadeDuration);
|
||||
animClip.PlayNode();
|
||||
}
|
||||
else
|
||||
{
|
||||
animClip.StartWeightFade(0f, fadeDuration);
|
||||
animClip.PauseNode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止指定动画,恢复为初始状态
|
||||
/// </summary>
|
||||
public void Stop(string name)
|
||||
{
|
||||
AnimClip animClip = FindClip(name);
|
||||
if (animClip == null)
|
||||
return;
|
||||
|
||||
animClip.PauseNode();
|
||||
animClip.ResetNode();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 暂停所有动画
|
||||
/// </summary>
|
||||
public void PauseAll()
|
||||
{
|
||||
for (int i = 0; i < _animClips.Count; i++)
|
||||
{
|
||||
var animClip = _animClips[i];
|
||||
if (animClip == null)
|
||||
continue;
|
||||
animClip.PauseNode();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否包含该动画
|
||||
/// </summary>
|
||||
public bool IsContains(AnimClip clip)
|
||||
{
|
||||
foreach (var animClip in _animClips)
|
||||
{
|
||||
if (animClip == clip)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除一个动画
|
||||
/// </summary>
|
||||
public void RemoveClip(string name)
|
||||
{
|
||||
var animClip = FindClip(name);
|
||||
if (animClip == null)
|
||||
return;
|
||||
|
||||
_animClips[animClip.InputPort] = null;
|
||||
animClip.Destroy();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定的动画
|
||||
/// </summary>
|
||||
/// <returns>如果没有返回NULL</returns>
|
||||
private AnimClip FindClip(string name)
|
||||
{
|
||||
foreach (var animClip in _animClips)
|
||||
{
|
||||
if (animClip != null && animClip.Name == name)
|
||||
return animClip;
|
||||
}
|
||||
|
||||
UniLogger.Warning($"${nameof(AnimClip)} doesn't exist : {name}");
|
||||
return null;
|
||||
}
|
||||
|
||||
private void DisconnectMixer()
|
||||
{
|
||||
for (int i = 0; i < _animClips.Count; i++)
|
||||
{
|
||||
var animClip = _animClips[i];
|
||||
if (animClip == null)
|
||||
continue;
|
||||
|
||||
animClip.Disconnect();
|
||||
_animClips[i] = null;
|
||||
}
|
||||
|
||||
Disconnect();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b33204afd07c00c4f8b425276778b8bf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
221
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniAnimation/Runtime/AnimNode.cs
vendored
Normal file
221
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniAnimation/Runtime/AnimNode.cs
vendored
Normal file
|
@ -0,0 +1,221 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Playables;
|
||||
using UnityEngine.Animations;
|
||||
|
||||
namespace UniFramework.Animation
|
||||
{
|
||||
internal abstract class AnimNode
|
||||
{
|
||||
private readonly PlayableGraph _graph;
|
||||
private Playable _source;
|
||||
private Playable _parent;
|
||||
|
||||
private float _fadeSpeed = 0f;
|
||||
private float _fadeWeight = 0f;
|
||||
private bool _isFading = false;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 是否已经连接
|
||||
/// </summary>
|
||||
public bool IsConnect { get; private set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 输入端口
|
||||
/// </summary>
|
||||
public int InputPort { private set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否已经完成
|
||||
/// If the duration of the playable is set, when the time of the playable reaches its duration during playback this flag will be set to true.
|
||||
/// </summary>
|
||||
public bool IsDone
|
||||
{
|
||||
get
|
||||
{
|
||||
return _source.IsDone();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否有效
|
||||
/// if the Playable is properly constructed by the PlayableGraph and has not been destroyed, false otherwise.
|
||||
/// </summary>
|
||||
public bool IsValid
|
||||
{
|
||||
get
|
||||
{
|
||||
return _source.IsValid();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否正在播放中
|
||||
/// </summary>
|
||||
public bool IsPlaying
|
||||
{
|
||||
get
|
||||
{
|
||||
return _source.GetPlayState() == PlayState.Playing;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 时间轴
|
||||
/// </summary>
|
||||
public float Time
|
||||
{
|
||||
set
|
||||
{
|
||||
_source.SetTime(value);
|
||||
}
|
||||
get
|
||||
{
|
||||
return (float)_source.GetTime();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 播放速度
|
||||
/// </summary>
|
||||
public float Speed
|
||||
{
|
||||
set
|
||||
{
|
||||
_source.SetSpeed(value);
|
||||
}
|
||||
get
|
||||
{
|
||||
return (float)_source.GetSpeed();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 权重值
|
||||
/// </summary>
|
||||
public float Weight
|
||||
{
|
||||
set
|
||||
{
|
||||
_parent.SetInputWeight(InputPort, value);
|
||||
}
|
||||
get
|
||||
{
|
||||
return _parent.GetInputWeight(InputPort);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public AnimNode(PlayableGraph graph)
|
||||
{
|
||||
_graph = graph;
|
||||
}
|
||||
public virtual void Update(float deltaTime)
|
||||
{
|
||||
if (_isFading)
|
||||
{
|
||||
Weight = Mathf.MoveTowards(Weight, _fadeWeight, _fadeSpeed * deltaTime);
|
||||
if (Mathf.Approximately(Weight, _fadeWeight))
|
||||
{
|
||||
_isFading = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
public virtual void Destroy()
|
||||
{
|
||||
if (IsValid)
|
||||
{
|
||||
_graph.DestroySubgraph(_source);
|
||||
}
|
||||
}
|
||||
public virtual void PlayNode()
|
||||
{
|
||||
// NOTE : When playing, the local time of this Playable will be updated during the evaluation of the PlayableGraph.
|
||||
_source.Play();
|
||||
|
||||
// NOTE : Changes a flag indicating that a playable has completed its operation.
|
||||
// Playable that reach the end of their duration are automatically marked as done.
|
||||
_source.SetDone(false);
|
||||
}
|
||||
public virtual void PauseNode()
|
||||
{
|
||||
// NOTE : When paused, the local time of this Playable will not be updated during the evaluation of the PlayableGraph.
|
||||
_source.Pause();
|
||||
|
||||
// NOTE : Changes a flag indicating that a playable has completed its operation.
|
||||
// Playable that reach the end of their duration are automatically marked as done.
|
||||
_source.SetDone(true);
|
||||
}
|
||||
public virtual void ResetNode()
|
||||
{
|
||||
_fadeSpeed = 0;
|
||||
_fadeWeight = 0;
|
||||
_isFading = false;
|
||||
|
||||
Time = 0;
|
||||
Speed = 1;
|
||||
Weight = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 连接到父节点
|
||||
/// </summary>
|
||||
/// <param name="parent">父节点对象</param>
|
||||
/// <param name="inputPort">父节点上的输入端口</param>
|
||||
public void Connect(Playable parent, int parentInputPort)
|
||||
{
|
||||
if (IsConnect)
|
||||
throw new System.Exception("AnimNode is connected.");
|
||||
|
||||
_parent = parent;
|
||||
InputPort = parentInputPort;
|
||||
|
||||
// 重置节点
|
||||
ResetNode();
|
||||
|
||||
// 连接
|
||||
_graph.Connect(_source, 0, parent, parentInputPort);
|
||||
IsConnect = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同父节点断开连接
|
||||
/// </summary>
|
||||
public void Disconnect()
|
||||
{
|
||||
if (IsConnect == false)
|
||||
throw new System.Exception("AnimNode is disconnected.");
|
||||
|
||||
// 断开
|
||||
_graph.Disconnect(_parent, InputPort);
|
||||
IsConnect = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 开始权重值过渡
|
||||
/// </summary>
|
||||
/// <param name="destWeight">目标权重值</param>
|
||||
/// <param name="fadeDuration">过渡时间</param>
|
||||
public void StartWeightFade(float destWeight, float fadeDuration)
|
||||
{
|
||||
if (fadeDuration <= 0)
|
||||
{
|
||||
Weight = destWeight;
|
||||
_isFading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
//注意:保持统一的渐变速度
|
||||
_fadeSpeed = 1f / fadeDuration;
|
||||
_fadeWeight = destWeight;
|
||||
_isFading = true;
|
||||
}
|
||||
|
||||
protected void SetSourcePlayable(Playable playable)
|
||||
{
|
||||
_source = playable;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b6928afd60ab2ed489e492e00d9ddaba
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
238
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniAnimation/Runtime/AnimPlayable.cs
vendored
Normal file
238
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniAnimation/Runtime/AnimPlayable.cs
vendored
Normal file
|
@ -0,0 +1,238 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Playables;
|
||||
using UnityEngine.Animations;
|
||||
|
||||
namespace UniFramework.Animation
|
||||
{
|
||||
internal class AnimPlayable
|
||||
{
|
||||
private readonly List<AnimClip> _animClips = new List<AnimClip>(10);
|
||||
private readonly List<AnimMixer> _animMixers = new List<AnimMixer>(10);
|
||||
|
||||
private PlayableGraph _graph;
|
||||
private AnimationPlayableOutput _output;
|
||||
private AnimationLayerMixerPlayable _mixerRoot;
|
||||
|
||||
public void Create(Animator animator)
|
||||
{
|
||||
string name = animator.gameObject.name;
|
||||
_graph = PlayableGraph.Create(name);
|
||||
_graph.SetTimeUpdateMode(DirectorUpdateMode.Manual);
|
||||
|
||||
_mixerRoot = AnimationLayerMixerPlayable.Create(_graph);
|
||||
_output = AnimationPlayableOutput.Create(_graph, name, animator);
|
||||
_output.SetSourcePlayable(_mixerRoot);
|
||||
}
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
_graph.Evaluate(deltaTime);
|
||||
|
||||
// 更新所有层级
|
||||
for (int i = 0; i < _animMixers.Count; i++)
|
||||
{
|
||||
var mixer = _animMixers[i];
|
||||
if(mixer.IsConnect)
|
||||
mixer.Update(deltaTime);
|
||||
}
|
||||
}
|
||||
public void Destroy()
|
||||
{
|
||||
_graph.Destroy();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Play the graph
|
||||
/// </summary>
|
||||
public void PlayGraph()
|
||||
{
|
||||
_graph.Play();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop the graph
|
||||
/// </summary>
|
||||
public void StopGraph()
|
||||
{
|
||||
_graph.Stop();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取动画的状态
|
||||
/// </summary>
|
||||
/// <param name="name">动画名称</param>
|
||||
/// <returns>如果动画不存在返回空</returns>
|
||||
public AnimState GetAnimState(string name)
|
||||
{
|
||||
for (int i = 0; i < _animClips.Count; i++)
|
||||
{
|
||||
if (_animClips[i].Name == name)
|
||||
return _animClips[i].State;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测动画是否正在播放
|
||||
/// </summary>
|
||||
/// <param name="name">动画名称</param>
|
||||
public bool IsPlaying(string name)
|
||||
{
|
||||
AnimClip animClip = GetAnimClip(name);
|
||||
if (animClip == null)
|
||||
return false;
|
||||
|
||||
return animClip.IsConnect && animClip.IsPlaying;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 播放一个动画
|
||||
/// </summary>
|
||||
/// <param name="name">动画名称</param>
|
||||
/// <param name="fadeLength">融合时间</param>
|
||||
public void Play(string name, float fadeLength)
|
||||
{
|
||||
var animClip = GetAnimClip(name);
|
||||
if (animClip == null)
|
||||
{
|
||||
UniLogger.Warning($"Not found animation {name}");
|
||||
return;
|
||||
}
|
||||
|
||||
int layer = animClip.Layer;
|
||||
var animMixer = GetAnimMixer(layer);
|
||||
if (animMixer == null)
|
||||
animMixer = CreateAnimMixer(layer);
|
||||
|
||||
if(animMixer.IsConnect == false)
|
||||
animMixer.Connect(_mixerRoot, animMixer.Layer);
|
||||
|
||||
animMixer.Play(animClip, fadeLength);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止一个动画
|
||||
/// </summary>
|
||||
/// <param name="name">动画名称</param>
|
||||
public void Stop(string name)
|
||||
{
|
||||
var animClip = GetAnimClip(name);
|
||||
if (animClip == null)
|
||||
{
|
||||
UniLogger.Warning($"Not found animation {name}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (animClip.IsConnect == false)
|
||||
return;
|
||||
|
||||
var animMixer = GetAnimMixer(animClip.Layer);
|
||||
if (animMixer == null)
|
||||
throw new System.Exception("Should never get here.");
|
||||
|
||||
animMixer.Stop(animClip.Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加一个动画片段
|
||||
/// </summary>
|
||||
/// <param name="name">动画名称</param>
|
||||
/// <param name="clip">动画片段</param>
|
||||
/// <param name="layer">动画层级</param>
|
||||
public bool AddAnimation(string name, AnimationClip clip, int layer = 0)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
throw new System.ArgumentException("Name is null or empty.");
|
||||
if (clip == null)
|
||||
throw new System.ArgumentNullException();
|
||||
if (layer < 0)
|
||||
throw new System.Exception("Layer must be greater than zero.");
|
||||
|
||||
if (IsContains(name))
|
||||
{
|
||||
UniLogger.Warning($"Animation already exists : {name}");
|
||||
return false;
|
||||
}
|
||||
|
||||
AnimClip animClip = new AnimClip(_graph, clip, name, layer);
|
||||
_animClips.Add(animClip);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除一个动画片段
|
||||
/// </summary>
|
||||
/// <param name="name">动画名称</param>
|
||||
public bool RemoveAnimation(string name)
|
||||
{
|
||||
if (IsContains(name) == false)
|
||||
{
|
||||
UniLogger.Warning($"Not found Animation : {name}");
|
||||
return false;
|
||||
}
|
||||
|
||||
AnimClip animClip = GetAnimClip(name);
|
||||
AnimMixer animMixer = GetAnimMixer(animClip.Layer);
|
||||
if(animMixer != null)
|
||||
animMixer.RemoveClip(animClip.Name);
|
||||
|
||||
animClip.Destroy();
|
||||
_animClips.Remove(animClip);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否包含一个动画状态
|
||||
/// </summary>
|
||||
/// <param name="name">动画名称</param>
|
||||
public bool IsContains(string name)
|
||||
{
|
||||
for (int i = 0; i < _animClips.Count; i++)
|
||||
{
|
||||
if (_animClips[i].Name == name)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private AnimClip GetAnimClip(string name)
|
||||
{
|
||||
for (int i = 0; i < _animClips.Count; i++)
|
||||
{
|
||||
if (_animClips[i].Name == name)
|
||||
return _animClips[i];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private AnimMixer GetAnimMixer(int layer)
|
||||
{
|
||||
for (int i = 0; i < _animMixers.Count; i++)
|
||||
{
|
||||
if (_animMixers[i].Layer == layer)
|
||||
return _animMixers[i];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
private AnimMixer CreateAnimMixer(int layer)
|
||||
{
|
||||
// Increase input count
|
||||
int inputCount = _mixerRoot.GetInputCount();
|
||||
if(layer == 0 && inputCount == 0)
|
||||
{
|
||||
_mixerRoot.SetInputCount(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (layer > inputCount - 1)
|
||||
{
|
||||
_mixerRoot.SetInputCount(layer + 1);
|
||||
}
|
||||
}
|
||||
|
||||
var animMixer = new AnimMixer(_graph, layer);
|
||||
_animMixers.Add(animMixer);
|
||||
return animMixer;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 772b8a9edd8466646bab12d6f5ba1084
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
126
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniAnimation/Runtime/AnimState.cs
vendored
Normal file
126
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniAnimation/Runtime/AnimState.cs
vendored
Normal file
|
@ -0,0 +1,126 @@
|
|||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Playables;
|
||||
using UnityEngine.Animations;
|
||||
|
||||
namespace UniFramework.Animation
|
||||
{
|
||||
public class AnimState
|
||||
{
|
||||
private readonly AnimClip _animClip;
|
||||
|
||||
private AnimState()
|
||||
{
|
||||
}
|
||||
internal AnimState(AnimClip animClip)
|
||||
{
|
||||
_animClip = animClip;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The name of animation.
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return _animClip.Name;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The length of the animation clip in seconds.
|
||||
/// </summary>
|
||||
public float Length
|
||||
{
|
||||
get
|
||||
{
|
||||
return _animClip.ClipLength;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The layer of animation.
|
||||
/// </summary>
|
||||
public int Layer
|
||||
{
|
||||
get
|
||||
{
|
||||
return _animClip.Layer;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapping mode of the animation.
|
||||
/// </summary>
|
||||
public WrapMode WrapMode
|
||||
{
|
||||
get
|
||||
{
|
||||
return _animClip.WrapMode;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The weight of animation.
|
||||
/// </summary>
|
||||
public float Weight
|
||||
{
|
||||
get
|
||||
{
|
||||
return _animClip.Weight;
|
||||
}
|
||||
set
|
||||
{
|
||||
_animClip.Weight = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The current time of the animation.
|
||||
/// </summary>
|
||||
public float Time
|
||||
{
|
||||
get
|
||||
{
|
||||
return _animClip.Time;
|
||||
}
|
||||
set
|
||||
{
|
||||
_animClip.Time = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The normalized time of the animation.
|
||||
/// </summary>
|
||||
public float NormalizedTime
|
||||
{
|
||||
get
|
||||
{
|
||||
return _animClip.NormalizedTime;
|
||||
}
|
||||
set
|
||||
{
|
||||
_animClip.NormalizedTime = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The playback speed of the animation. 1 is normal playback speed.
|
||||
/// </summary>
|
||||
public float Speed
|
||||
{
|
||||
get
|
||||
{
|
||||
return _animClip.Speed;
|
||||
}
|
||||
set
|
||||
{
|
||||
_animClip.Speed = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5660d9e37e5c2a44f818506c9fe76624
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
182
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniAnimation/Runtime/UniAnimation.cs
vendored
Normal file
182
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniAnimation/Runtime/UniAnimation.cs
vendored
Normal file
|
@ -0,0 +1,182 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniFramework.Animation
|
||||
{
|
||||
[RequireComponent(typeof(Animator))]
|
||||
public class UniAnimation : MonoBehaviour
|
||||
{
|
||||
[Serializable]
|
||||
public class AnimationWrapper
|
||||
{
|
||||
public int Layer;
|
||||
public WrapMode Mode;
|
||||
public AnimationClip Clip;
|
||||
}
|
||||
|
||||
private AnimPlayable _animPlayable;
|
||||
private Animator _animator;
|
||||
|
||||
[SerializeField]
|
||||
private AnimationWrapper[] _animations;
|
||||
|
||||
[SerializeField]
|
||||
private bool _playAutomatically = true;
|
||||
|
||||
[SerializeField]
|
||||
private bool _animatePhysics = false;
|
||||
|
||||
/// <summary>
|
||||
/// 自动播放动画
|
||||
/// </summary>
|
||||
public bool PlayAutomatically
|
||||
{
|
||||
get
|
||||
{
|
||||
return _playAutomatically;
|
||||
}
|
||||
set
|
||||
{
|
||||
_playAutomatically = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 物理更新模式
|
||||
/// </summary>
|
||||
public bool AnimatePhysics
|
||||
{
|
||||
get
|
||||
{
|
||||
return _animatePhysics;
|
||||
}
|
||||
set
|
||||
{
|
||||
_animatePhysics = value;
|
||||
_animator.updateMode = _animatePhysics ? AnimatorUpdateMode.AnimatePhysics : AnimatorUpdateMode.Normal;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
_animator = GetComponent<Animator>();
|
||||
_animator.updateMode = _animatePhysics ? AnimatorUpdateMode.AnimatePhysics : AnimatorUpdateMode.Normal;
|
||||
|
||||
_animPlayable = new AnimPlayable();
|
||||
_animPlayable.Create(_animator);
|
||||
|
||||
// 添加列表动作
|
||||
for (int i = 0; i < _animations.Length; i++)
|
||||
{
|
||||
var wrapper = _animations[i];
|
||||
if (wrapper == null || wrapper.Clip == null)
|
||||
continue;
|
||||
|
||||
wrapper.Clip.wrapMode = wrapper.Mode;
|
||||
_animPlayable.AddAnimation(wrapper.Clip.name, wrapper.Clip, wrapper.Layer);
|
||||
}
|
||||
}
|
||||
public void OnEnable()
|
||||
{
|
||||
_animPlayable.PlayGraph();
|
||||
|
||||
if (PlayAutomatically)
|
||||
{
|
||||
var wrapper = GetDefaultWrapper();
|
||||
if (wrapper != null)
|
||||
{
|
||||
Play(wrapper.Clip.name, 0f);
|
||||
}
|
||||
}
|
||||
|
||||
_animPlayable.Update(float.MaxValue);
|
||||
}
|
||||
public void OnDisable()
|
||||
{
|
||||
_animPlayable.StopGraph();
|
||||
}
|
||||
public void OnDestroy()
|
||||
{
|
||||
_animPlayable.Destroy();
|
||||
}
|
||||
public void Update()
|
||||
{
|
||||
_animPlayable.Update(Time.deltaTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加一个动画
|
||||
/// </summary>
|
||||
/// <param name="clip">动画片段</param>
|
||||
/// <param name="layer">动画层级</param>
|
||||
public bool AddAnimation(AnimationClip clip, int layer = 0)
|
||||
{
|
||||
return _animPlayable.AddAnimation(clip.name, clip, layer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 移除动画
|
||||
/// </summary>
|
||||
/// <param name="name">动画名称</param>
|
||||
public bool RemoveAnimation(string name)
|
||||
{
|
||||
return _animPlayable.RemoveAnimation(name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取动画状态
|
||||
/// </summary>
|
||||
public AnimState GetState(string name)
|
||||
{
|
||||
return _animPlayable.GetAnimState(name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 动画是否在播放中
|
||||
/// </summary>
|
||||
public bool IsPlaying(string name)
|
||||
{
|
||||
return _animPlayable.IsPlaying(name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否包含动画片段
|
||||
/// </summary>
|
||||
public bool IsContains(string name)
|
||||
{
|
||||
return _animPlayable.IsContains(name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 播放动画
|
||||
/// </summary>
|
||||
public void Play(string name, float fadeLength = 0.25f)
|
||||
{
|
||||
_animPlayable.Play(name, fadeLength);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止动画
|
||||
/// </summary>
|
||||
public void Stop(string name)
|
||||
{
|
||||
_animPlayable.Stop(name);
|
||||
}
|
||||
|
||||
private AnimationWrapper GetDefaultWrapper()
|
||||
{
|
||||
for (int i = 0; i < _animations.Length; i++)
|
||||
{
|
||||
var wrapper = _animations[i];
|
||||
if (wrapper == null || wrapper.Clip == null)
|
||||
continue;
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ef52174816df6104587b15c5b250201a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,12 +1,10 @@
|
|||
{
|
||||
"name": "UniWindow",
|
||||
"name": "UniFramework.Animation",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:e34a5702dd353724aa315fb8011f08c3"
|
||||
],
|
||||
"references": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": true,
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ccbd3ee89c7c8614bb89388a769680c1
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
21
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniAnimation/Runtime/UniLogger.cs
vendored
Normal file
21
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniAnimation/Runtime/UniLogger.cs
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
using System.Diagnostics;
|
||||
|
||||
namespace UniFramework.Animation
|
||||
{
|
||||
internal static class UniLogger
|
||||
{
|
||||
[Conditional("DEBUG")]
|
||||
public static void Log(string info)
|
||||
{
|
||||
UnityEngine.Debug.Log(info);
|
||||
}
|
||||
public static void Warning(string info)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning(info);
|
||||
}
|
||||
public static void Error(string info)
|
||||
{
|
||||
UnityEngine.Debug.LogError(info);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5c11371eb114ef24daad9fc81ac6e0cd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f2801816f5bf9e74eb7f2e2b340ad4cc
|
||||
guid: c1cc49e5bd383f040b0f9d481de62f04
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "UniEvent",
|
||||
"name": "UniFramework.Event",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:e34a5702dd353724aa315fb8011f08c3"
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 16d76e3e6337b0c4cae28696d4be4c7c
|
||||
guid: 72dcc846338391f44a4134c21f94723a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "UniPooling",
|
||||
"name": "UniFramework.Machine",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:e34a5702dd353724aa315fb8011f08c3"
|
8
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniNetwork.meta
vendored
Normal file
8
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniNetwork.meta
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 99ad37bbd721c834d8157bb257d4b8bb
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
89
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniNetwork/README.md
vendored
Normal file
89
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniNetwork/README.md
vendored
Normal file
|
@ -0,0 +1,89 @@
|
|||
# UniFramework.Network
|
||||
|
||||
一个高效的基于IOCP模型的网络系统。
|
||||
|
||||
```c#
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UniFramework.Network;
|
||||
|
||||
// 登录请求消息
|
||||
class LoginRequestMessage
|
||||
{
|
||||
public string Name;
|
||||
public string Password;
|
||||
}
|
||||
|
||||
// 登录反馈消息
|
||||
class LoginResponseMessage
|
||||
{
|
||||
public string Result;
|
||||
}
|
||||
|
||||
// TCP客户端
|
||||
UniFramework.Network.TcpClient _client = null;
|
||||
|
||||
// 创建TCP客户端
|
||||
void CreateClient()
|
||||
{
|
||||
// 初始化网络系统
|
||||
UniNetwork.Initalize();
|
||||
|
||||
// 创建TCP客户端
|
||||
int packageMaxSize = short.MaxValue;
|
||||
var encoder = new DefaultNetPackageEncoder();
|
||||
var decoder = new DefaultNetPackageDecoder();
|
||||
_client = UniNetwork.CreateTcpClient(packageMaxSize, encoder, decoder);
|
||||
|
||||
// 连接服务器
|
||||
var remote = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8000);
|
||||
_client.ConnectAsync(remote, OnConnectServer);
|
||||
}
|
||||
|
||||
// 关闭TCP客户端
|
||||
void CloseClient()
|
||||
{
|
||||
if(_client != null)
|
||||
{
|
||||
_client.Dispose();
|
||||
_client = null;
|
||||
}
|
||||
}
|
||||
|
||||
void OnConnectServer(SocketError error)
|
||||
{
|
||||
Debug.Log($"Server connect result : {error}");
|
||||
if (error == SocketError.Success)
|
||||
Debug.Log("服务器连接成功!");
|
||||
else
|
||||
Debug.Log("服务器连接失败!");
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
// 每帧去获取解析的网络包
|
||||
DefaultNetPackage networkPackage = client.PickPackage() as DefaultNetPackage;
|
||||
if(networkPackage != null)
|
||||
{
|
||||
string json = Encoding.UTF8.GetString(networkPackage.BodyBytes);
|
||||
LoginResponseMessage message = JsonUtility.FromJson<LoginResponseMessage>(json);
|
||||
Debug.Log(message.Result);
|
||||
}
|
||||
}
|
||||
|
||||
// 发送登录请求消息
|
||||
void SendLoginMessage()
|
||||
{
|
||||
LoginRequestMessage message = new LoginRequestMessage();
|
||||
message.Name = "hevinci";
|
||||
message.Password = "1234567";
|
||||
|
||||
DefaultNetPackage networkPackage = new DefaultNetPackage();
|
||||
networkPackage.MsgID = 10001;
|
||||
networkPackage.BodyBytes = Encoding.UTF8.GetBytes(JsonUtility.ToJson(message));
|
||||
_client.SendPackage(networkPackage);
|
||||
}
|
||||
```
|
||||
|
7
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniNetwork/README.md.meta
vendored
Normal file
7
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniNetwork/README.md.meta
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9325e3d425f106a41977ea6e672fecdb
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniNetwork/Runtime.meta
vendored
Normal file
8
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniNetwork/Runtime.meta
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: efa01143ee531b6478df4aca44367f8a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3cb02cc27ea1caf479c14cebf66a5dab
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
namespace UniFramework.Network
|
||||
{
|
||||
public class DefaultNetPackage : INetPackage
|
||||
{
|
||||
/// <summary>
|
||||
/// 消息ID
|
||||
/// </summary>
|
||||
public int MsgID { set; get; }
|
||||
|
||||
/// <summary>
|
||||
/// 包体数据
|
||||
/// </summary>
|
||||
public byte[] BodyBytes { set; get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 77bfd5d9f7d9c79478b19cf99a103c47
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,86 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UniFramework.Network
|
||||
{
|
||||
/// <summary>
|
||||
/// 网络包解码器
|
||||
/// </summary>
|
||||
public class DefaultNetPackageDecoder : INetPackageDecoder
|
||||
{
|
||||
private HandleErrorDelegate _handleErrorCallback;
|
||||
private const int PackageHeaderLengthFiledSize = 4; //int类型
|
||||
private const int PackageHeaderIDFiledSize = 4; //int类型
|
||||
|
||||
/// <summary>
|
||||
/// 获取包头的尺寸
|
||||
/// </summary>
|
||||
public int GetPackageHeaderSize()
|
||||
{
|
||||
return PackageHeaderLengthFiledSize + PackageHeaderIDFiledSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册异常错误回调方法
|
||||
/// </summary>
|
||||
/// <param name="callback"></param>
|
||||
public void RigistHandleErrorCallback(HandleErrorDelegate callback)
|
||||
{
|
||||
_handleErrorCallback = callback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 网络消息解码
|
||||
/// </summary>
|
||||
/// <param name="packageBodyMaxSize">包体的最大尺寸</param>
|
||||
/// <param name="ringBuffer">解码需要的字节缓冲区</param>
|
||||
/// <param name="outputPackages">接收的包裹列表</param>
|
||||
public void Decode(int packageBodyMaxSize, RingBuffer ringBuffer, List<INetPackage> outputPackages)
|
||||
{
|
||||
// 循环解包
|
||||
while (true)
|
||||
{
|
||||
// 如果数据不够判断消息长度
|
||||
if (ringBuffer.ReadableBytes < PackageHeaderLengthFiledSize)
|
||||
break;
|
||||
|
||||
ringBuffer.MarkReaderIndex();
|
||||
|
||||
// 读取Package长度
|
||||
int packageSize = ringBuffer.ReadInt();
|
||||
|
||||
// 如果剩余可读数据小于Package长度
|
||||
if (ringBuffer.ReadableBytes < packageSize)
|
||||
{
|
||||
ringBuffer.ResetReaderIndex();
|
||||
break; //需要退出读够数据再解包
|
||||
}
|
||||
|
||||
DefaultNetPackage package = new DefaultNetPackage();
|
||||
|
||||
// 读取包头
|
||||
{
|
||||
// 读取消息ID
|
||||
package.MsgID = ringBuffer.ReadInt();
|
||||
}
|
||||
|
||||
// 检测包体长度
|
||||
int bodySize = packageSize - PackageHeaderIDFiledSize;
|
||||
if (bodySize > packageBodyMaxSize)
|
||||
{
|
||||
_handleErrorCallback(true, $"The decode package {package.MsgID} body size is larger than {packageBodyMaxSize} !");
|
||||
break;
|
||||
}
|
||||
|
||||
// 读取包体
|
||||
{
|
||||
package.BodyBytes = ringBuffer.ReadBytes(bodySize);
|
||||
outputPackages.Add(package);
|
||||
}
|
||||
}
|
||||
|
||||
// 注意:将剩余数据移至起始
|
||||
ringBuffer.DiscardReadBytes();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6b9693105d824c8409392d251d920346
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,84 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UniFramework.Network
|
||||
{
|
||||
/// <summary>
|
||||
/// 网络包编码器
|
||||
/// </summary>
|
||||
public class DefaultNetPackageEncoder : INetPackageEncoder
|
||||
{
|
||||
private HandleErrorDelegate _handleErrorCallback;
|
||||
private const int PackageHeaderLengthFiledSize = 4; //int类型
|
||||
private const int PackageHeaderIDFiledSize = 4; //int类型
|
||||
|
||||
/// <summary>
|
||||
/// 获取包头的尺寸
|
||||
/// </summary>
|
||||
public int GetPackageHeaderSize()
|
||||
{
|
||||
return PackageHeaderLengthFiledSize + PackageHeaderIDFiledSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册异常错误回调方法
|
||||
/// </summary>
|
||||
/// <param name="callback"></param>
|
||||
public void RigistHandleErrorCallback(HandleErrorDelegate callback)
|
||||
{
|
||||
_handleErrorCallback = callback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 编码
|
||||
/// </summary>
|
||||
/// <param name="packageBodyMaxSize">包体的最大尺寸</param>
|
||||
/// <param name="ringBuffer">编码填充的字节缓冲区</param>
|
||||
/// <param name="encodePackage">发送的包裹</param>
|
||||
public void Encode(int packageBodyMaxSize, RingBuffer ringBuffer, INetPackage encodePackage)
|
||||
{
|
||||
if (encodePackage == null)
|
||||
{
|
||||
_handleErrorCallback(false, "The encode package object is null");
|
||||
return;
|
||||
}
|
||||
|
||||
DefaultNetPackage package = (DefaultNetPackage)encodePackage;
|
||||
if (package == null)
|
||||
{
|
||||
_handleErrorCallback(false, $"The encode package object is invalid : {encodePackage.GetType()}");
|
||||
return;
|
||||
}
|
||||
|
||||
// 检测逻辑是否合法
|
||||
if (package.BodyBytes == null)
|
||||
{
|
||||
_handleErrorCallback(false, $"The encode package BodyBytes field is null : {encodePackage.GetType()}");
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取包体数据
|
||||
byte[] bodyData = package.BodyBytes;
|
||||
|
||||
// 检测包体长度
|
||||
if (bodyData.Length > packageBodyMaxSize)
|
||||
{
|
||||
_handleErrorCallback(false, $"The encode package {package.MsgID} body size is larger than {packageBodyMaxSize}");
|
||||
return;
|
||||
}
|
||||
|
||||
// 写入长度
|
||||
int packetLength = PackageHeaderIDFiledSize + bodyData.Length;
|
||||
ringBuffer.WriteInt(packetLength);
|
||||
|
||||
// 写入包头
|
||||
{
|
||||
// 写入消息ID
|
||||
ringBuffer.WriteInt(package.MsgID);
|
||||
}
|
||||
|
||||
// 写入包体
|
||||
ringBuffer.WriteBytes(bodyData, 0, bodyData.Length);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a91c21858dd0d2645b67361f76d9e747
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
namespace UniFramework.Network
|
||||
{
|
||||
public delegate void HandleErrorDelegate(bool isDispose, string error);
|
||||
|
||||
public interface INetPackage
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 00149ae4ecfb570418760bc2d359e7ca
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,30 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UniFramework.Network
|
||||
{
|
||||
/// <summary>
|
||||
/// 网络包解码器
|
||||
/// </summary>
|
||||
public interface INetPackageDecoder
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取包头的尺寸
|
||||
/// </summary>
|
||||
int GetPackageHeaderSize();
|
||||
|
||||
/// <summary>
|
||||
/// 注册异常错误回调方法
|
||||
/// </summary>
|
||||
/// <param name="callback"></param>
|
||||
void RigistHandleErrorCallback(HandleErrorDelegate callback);
|
||||
|
||||
/// <summary>
|
||||
/// 网络消息解码
|
||||
/// </summary>
|
||||
/// <param name="packageBodyMaxSize">包体的最大尺寸</param>
|
||||
/// <param name="ringBuffer">解码需要的字节缓冲区</param>
|
||||
/// <param name="outputPackages">接收的包裹列表</param>
|
||||
void Decode(int packageBodyMaxSize, RingBuffer ringBuffer, List<INetPackage> outputPackages);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8c549df6ac813a74b9fd787e3991a254
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,30 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace UniFramework.Network
|
||||
{
|
||||
/// <summary>
|
||||
/// 网络包编码器
|
||||
/// </summary>
|
||||
public interface INetPackageEncoder
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取包头的尺寸
|
||||
/// </summary>
|
||||
int GetPackageHeaderSize();
|
||||
|
||||
/// <summary>
|
||||
/// 注册异常错误回调方法
|
||||
/// </summary>
|
||||
/// <param name="callback"></param>
|
||||
void RigistHandleErrorCallback(HandleErrorDelegate callback);
|
||||
|
||||
/// <summary>
|
||||
/// 编码
|
||||
/// </summary>
|
||||
/// <param name="packageBodyMaxSize">包体的最大尺寸</param>
|
||||
/// <param name="ringBuffer">编码填充的字节缓冲区</param>
|
||||
/// <param name="encodePackage">发送的包裹</param>
|
||||
void Encode(int packageBodyMaxSize, RingBuffer ringBuffer, INetPackage encodePackage);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 0c4bce3e31495bc4483ab697d895fd62
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
537
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniNetwork/Runtime/RingBuffer.cs
vendored
Normal file
537
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniNetwork/Runtime/RingBuffer.cs
vendored
Normal file
|
@ -0,0 +1,537 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniFramework.Network
|
||||
{
|
||||
/// <summary>
|
||||
/// 环形缓冲区
|
||||
/// </summary>
|
||||
public class RingBuffer
|
||||
{
|
||||
private readonly byte[] _buffer;
|
||||
private int _readerIndex = 0;
|
||||
private int _writerIndex = 0;
|
||||
private int _markedReaderIndex = 0;
|
||||
private int _markedWriterIndex = 0;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 字节缓冲区
|
||||
/// </summary>
|
||||
public RingBuffer(int capacity)
|
||||
{
|
||||
_buffer = new byte[capacity];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 字节缓冲区
|
||||
/// </summary>
|
||||
public RingBuffer(byte[] data)
|
||||
{
|
||||
_buffer = data;
|
||||
_writerIndex = data.Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取数据
|
||||
/// </summary>
|
||||
public byte[] GetBuffer()
|
||||
{
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 缓冲区容量
|
||||
/// </summary>
|
||||
public int Capacity
|
||||
{
|
||||
get { return _buffer.Length; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清空缓冲区
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
_readerIndex = 0;
|
||||
_writerIndex = 0;
|
||||
_markedReaderIndex = 0;
|
||||
_markedWriterIndex = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除已读部分,重新初始化数组
|
||||
/// </summary>
|
||||
public void DiscardReadBytes()
|
||||
{
|
||||
if (_readerIndex == 0)
|
||||
return;
|
||||
|
||||
if (_readerIndex == _writerIndex)
|
||||
{
|
||||
_readerIndex = 0;
|
||||
_writerIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0, j = _readerIndex, length = _writerIndex - _readerIndex; i < length; i++, j++)
|
||||
{
|
||||
_buffer[i] = _buffer[j];
|
||||
}
|
||||
_writerIndex -= _readerIndex;
|
||||
_readerIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#region 读取相关
|
||||
/// <summary>
|
||||
/// 读取的下标位置
|
||||
/// </summary>
|
||||
public int ReaderIndex
|
||||
{
|
||||
get { return _readerIndex; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当前可读数据量
|
||||
/// </summary>
|
||||
public int ReadableBytes
|
||||
{
|
||||
get { return _writerIndex - _readerIndex; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询是否可以读取
|
||||
/// </summary>
|
||||
/// <param name="size">读取数据量</param>
|
||||
public bool IsReadable(int size = 1)
|
||||
{
|
||||
return _writerIndex - _readerIndex >= size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 标记读取的下标位置,便于某些时候回退到该位置
|
||||
/// </summary>
|
||||
public void MarkReaderIndex()
|
||||
{
|
||||
_markedReaderIndex = _readerIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回退到标记的读取下标位置
|
||||
/// </summary>
|
||||
public void ResetReaderIndex()
|
||||
{
|
||||
_readerIndex = _markedReaderIndex;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 写入相关
|
||||
/// <summary>
|
||||
/// 写入的下标位置
|
||||
/// </summary>
|
||||
public int WriterIndex
|
||||
{
|
||||
get { return _writerIndex; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当前可写入数据量
|
||||
/// </summary>
|
||||
public int WriteableBytes
|
||||
{
|
||||
get { return Capacity - _writerIndex; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询是否可以写入
|
||||
/// </summary>
|
||||
/// <param name="size">写入数据量</param>
|
||||
public bool IsWriteable(int size = 1)
|
||||
{
|
||||
return Capacity - _writerIndex >= size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 标记写入的下标位置,便于某些时候回退到该位置。
|
||||
/// </summary>
|
||||
public void MarkWriterIndex()
|
||||
{
|
||||
_markedWriterIndex = _writerIndex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回退到标记的写入下标位置
|
||||
/// </summary>
|
||||
public void ResetWriterIndex()
|
||||
{
|
||||
_writerIndex = _markedWriterIndex;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 读取操作
|
||||
[Conditional("DEBUG")]
|
||||
private void CheckReaderIndex(int length)
|
||||
{
|
||||
if (_readerIndex + length > _writerIndex)
|
||||
{
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] ReadBytes(int count)
|
||||
{
|
||||
CheckReaderIndex(count);
|
||||
var data = new byte[count];
|
||||
Buffer.BlockCopy(_buffer, _readerIndex, data, 0, count);
|
||||
_readerIndex += count;
|
||||
return data;
|
||||
}
|
||||
public bool ReadBool()
|
||||
{
|
||||
CheckReaderIndex(1);
|
||||
return _buffer[_readerIndex++] == 1;
|
||||
}
|
||||
public byte ReadByte()
|
||||
{
|
||||
CheckReaderIndex(1);
|
||||
return _buffer[_readerIndex++];
|
||||
}
|
||||
public sbyte ReadSbyte()
|
||||
{
|
||||
return (sbyte)ReadByte();
|
||||
}
|
||||
public short ReadShort()
|
||||
{
|
||||
CheckReaderIndex(2);
|
||||
short result = BitConverter.ToInt16(_buffer, _readerIndex);
|
||||
_readerIndex += 2;
|
||||
return result;
|
||||
}
|
||||
public ushort ReadUShort()
|
||||
{
|
||||
CheckReaderIndex(2);
|
||||
ushort result = BitConverter.ToUInt16(_buffer, _readerIndex);
|
||||
_readerIndex += 2;
|
||||
return result;
|
||||
}
|
||||
public int ReadInt()
|
||||
{
|
||||
CheckReaderIndex(4);
|
||||
int result = BitConverter.ToInt32(_buffer, _readerIndex);
|
||||
_readerIndex += 4;
|
||||
return result;
|
||||
}
|
||||
public uint ReadUInt()
|
||||
{
|
||||
CheckReaderIndex(4);
|
||||
uint result = BitConverter.ToUInt32(_buffer, _readerIndex);
|
||||
_readerIndex += 4;
|
||||
return result;
|
||||
}
|
||||
public long ReadLong()
|
||||
{
|
||||
CheckReaderIndex(8);
|
||||
long result = BitConverter.ToInt64(_buffer, _readerIndex);
|
||||
_readerIndex += 8;
|
||||
return result;
|
||||
}
|
||||
public ulong ReadULong()
|
||||
{
|
||||
CheckReaderIndex(8);
|
||||
ulong result = BitConverter.ToUInt64(_buffer, _readerIndex);
|
||||
_readerIndex += 8;
|
||||
return result;
|
||||
}
|
||||
public float ReadFloat()
|
||||
{
|
||||
CheckReaderIndex(4);
|
||||
float result = BitConverter.ToSingle(_buffer, _readerIndex);
|
||||
_readerIndex += 4;
|
||||
return result;
|
||||
}
|
||||
public double ReadDouble()
|
||||
{
|
||||
CheckReaderIndex(8);
|
||||
double result = BitConverter.ToDouble(_buffer, _readerIndex);
|
||||
_readerIndex += 8;
|
||||
return result;
|
||||
}
|
||||
public string ReadUTF()
|
||||
{
|
||||
ushort count = ReadUShort();
|
||||
CheckReaderIndex(count);
|
||||
string result = Encoding.UTF8.GetString(_buffer, _readerIndex, count - 1); // 注意:读取的时候忽略字符串末尾写入结束符
|
||||
_readerIndex += count;
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<int> ReadListInt()
|
||||
{
|
||||
List<int> result = new List<int>();
|
||||
int count = ReadInt();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
result.Add(ReadInt());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public List<long> ReadListLong()
|
||||
{
|
||||
List<long> result = new List<long>();
|
||||
int count = ReadInt();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
result.Add(ReadLong());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public List<float> ReadListFloat()
|
||||
{
|
||||
List<float> result = new List<float>();
|
||||
int count = ReadInt();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
result.Add(ReadFloat());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public List<double> ReadListDouble()
|
||||
{
|
||||
List<double> result = new List<double>();
|
||||
int count = ReadInt();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
result.Add(ReadDouble());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public List<string> ReadListUTF()
|
||||
{
|
||||
List<string> result = new List<string>();
|
||||
int count = ReadInt();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
result.Add(ReadUTF());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Vector2 ReadVector2()
|
||||
{
|
||||
float x = ReadFloat();
|
||||
float y = ReadFloat();
|
||||
return new Vector2(x, y);
|
||||
}
|
||||
public Vector3 ReadVector3()
|
||||
{
|
||||
float x = ReadFloat();
|
||||
float y = ReadFloat();
|
||||
float z = ReadFloat();
|
||||
return new Vector3(x, y, z);
|
||||
}
|
||||
public Vector4 ReadVector4()
|
||||
{
|
||||
float x = ReadFloat();
|
||||
float y = ReadFloat();
|
||||
float z = ReadFloat();
|
||||
float w = ReadFloat();
|
||||
return new Vector4(x, y, z, w);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 写入操作
|
||||
[Conditional("DEBUG")]
|
||||
private void CheckWriterIndex(int length)
|
||||
{
|
||||
if (_writerIndex + length > Capacity)
|
||||
{
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteBytes(byte[] data)
|
||||
{
|
||||
WriteBytes(data, 0, data.Length);
|
||||
}
|
||||
public void WriteBytes(byte[] data, int offset, int count)
|
||||
{
|
||||
CheckWriterIndex(count);
|
||||
Buffer.BlockCopy(data, offset, _buffer, _writerIndex, count);
|
||||
_writerIndex += count;
|
||||
}
|
||||
public void WriteBool(bool value)
|
||||
{
|
||||
WriteByte((byte)(value ? 1 : 0));
|
||||
}
|
||||
public void WriteByte(byte value)
|
||||
{
|
||||
CheckWriterIndex(1);
|
||||
_buffer[_writerIndex++] = value;
|
||||
}
|
||||
public void WriteSbyte(sbyte value)
|
||||
{
|
||||
// 注意:从sbyte强转到byte不会有数据变化或丢失
|
||||
WriteByte((byte)value);
|
||||
}
|
||||
public void WriteShort(short value)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
WriteBytes(bytes);
|
||||
}
|
||||
public void WriteUShort(ushort value)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
WriteBytes(bytes);
|
||||
}
|
||||
public void WriteInt(int value)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
WriteBytes(bytes);
|
||||
}
|
||||
public void WriteUInt(uint value)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
WriteBytes(bytes);
|
||||
}
|
||||
public void WriteLong(long value)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
WriteBytes(bytes);
|
||||
}
|
||||
public void WriteULong(ulong value)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
WriteBytes(bytes);
|
||||
}
|
||||
public void WriteFloat(float value)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
WriteBytes(bytes);
|
||||
}
|
||||
public void WriteDouble(double value)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
WriteBytes(bytes);
|
||||
}
|
||||
public void WriteUTF(string value)
|
||||
{
|
||||
byte[] bytes = Encoding.UTF8.GetBytes(value);
|
||||
int num = bytes.Length + 1; // 注意:字符串末尾写入结束符
|
||||
if (num > ushort.MaxValue)
|
||||
throw new FormatException($"String length cannot be greater than {ushort.MaxValue} !");
|
||||
|
||||
WriteUShort(Convert.ToUInt16(num));
|
||||
WriteBytes(bytes);
|
||||
WriteByte((byte)'\0');
|
||||
}
|
||||
|
||||
public void WriteListInt(List<int> values)
|
||||
{
|
||||
int count = 0;
|
||||
if (values != null)
|
||||
count = values.Count;
|
||||
|
||||
WriteInt(count);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
WriteInt(values[i]);
|
||||
}
|
||||
}
|
||||
public void WriteListLong(List<long> values)
|
||||
{
|
||||
int count = 0;
|
||||
if (values != null)
|
||||
count = values.Count;
|
||||
|
||||
WriteInt(count);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
WriteLong(values[i]);
|
||||
}
|
||||
}
|
||||
public void WriteListFloat(List<float> values)
|
||||
{
|
||||
int count = 0;
|
||||
if (values != null)
|
||||
count = values.Count;
|
||||
|
||||
WriteInt(count);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
WriteFloat(values[i]);
|
||||
}
|
||||
}
|
||||
public void WriteListDouble(List<double> values)
|
||||
{
|
||||
int count = 0;
|
||||
if (values != null)
|
||||
count = values.Count;
|
||||
|
||||
WriteInt(count);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
WriteDouble(values[i]);
|
||||
}
|
||||
}
|
||||
public void WriteListUTF(List<string> values)
|
||||
{
|
||||
int count = 0;
|
||||
if (values != null)
|
||||
count = values.Count;
|
||||
|
||||
WriteInt(count);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
WriteUTF(values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteVector2(Vector2 value)
|
||||
{
|
||||
WriteFloat(value.x);
|
||||
WriteFloat(value.y);
|
||||
}
|
||||
public void WriteVector3(Vector3 value)
|
||||
{
|
||||
WriteFloat(value.x);
|
||||
WriteFloat(value.y);
|
||||
WriteFloat(value.z);
|
||||
}
|
||||
public void WriteVector4(Vector4 value)
|
||||
{
|
||||
WriteFloat(value.x);
|
||||
WriteFloat(value.y);
|
||||
WriteFloat(value.z);
|
||||
WriteFloat(value.w);
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 大小端转换
|
||||
/// </summary>
|
||||
public static void ReverseOrder(byte[] data)
|
||||
{
|
||||
ReverseOrder(data, 0, data.Length);
|
||||
}
|
||||
public static void ReverseOrder(byte[] data, int offset, int length)
|
||||
{
|
||||
if (length <= 1)
|
||||
return;
|
||||
|
||||
int end = offset + length - 1;
|
||||
int max = offset + length / 2;
|
||||
byte temp;
|
||||
for (int index = offset; index < max; index++, end--)
|
||||
{
|
||||
temp = data[end];
|
||||
data[end] = data[index];
|
||||
data[index] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: dcd2ef8207d26994497ffeb6e8f30d13
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniNetwork/Runtime/TCP.meta
vendored
Normal file
8
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniNetwork/Runtime/TCP.meta
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f491992d09ff2c1498b496c4746ff01a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
301
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniNetwork/Runtime/TCP/TcpChannel.cs
vendored
Normal file
301
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniNetwork/Runtime/TCP/TcpChannel.cs
vendored
Normal file
|
@ -0,0 +1,301 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace UniFramework.Network
|
||||
{
|
||||
internal class TcpChannel : IDisposable
|
||||
{
|
||||
private readonly SocketAsyncEventArgs _receiveArgs = new SocketAsyncEventArgs();
|
||||
private readonly SocketAsyncEventArgs _sendArgs = new SocketAsyncEventArgs();
|
||||
|
||||
private readonly Queue<INetPackage> _sendQueue = new Queue<INetPackage>(10000);
|
||||
private readonly Queue<INetPackage> _receiveQueue = new Queue<INetPackage>(10000);
|
||||
private readonly List<INetPackage> _decodeTempList = new List<INetPackage>(100);
|
||||
|
||||
private byte[] _receiveBuffer;
|
||||
private RingBuffer _encodeBuffer;
|
||||
private RingBuffer _decodeBuffer;
|
||||
private int _packageBodyMaxSize;
|
||||
private INetPackageEncoder _packageEncoder;
|
||||
private INetPackageDecoder _packageDecoder;
|
||||
private bool _isSending = false;
|
||||
private bool _isReceiving = false;
|
||||
|
||||
/// <summary>
|
||||
/// 通信Socket
|
||||
/// </summary>
|
||||
private Socket _socket;
|
||||
|
||||
/// <summary>
|
||||
/// 同步上下文
|
||||
/// </summary>
|
||||
private ThreadSyncContext _context;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化频道
|
||||
/// </summary>
|
||||
internal void InitChannel(ThreadSyncContext context, Socket socket, int packageBodyMaxSize, INetPackageEncoder encoder, INetPackageDecoder decoder)
|
||||
{
|
||||
if (packageBodyMaxSize <= 0)
|
||||
throw new System.ArgumentException($"PackageMaxSize is invalid : {packageBodyMaxSize}");
|
||||
|
||||
_context = context;
|
||||
_socket = socket;
|
||||
_socket.NoDelay = true;
|
||||
|
||||
// 创建编码解码器
|
||||
_packageBodyMaxSize = packageBodyMaxSize;
|
||||
_packageEncoder = encoder;
|
||||
_packageEncoder.RigistHandleErrorCallback(HandleError);
|
||||
_packageDecoder = decoder;
|
||||
_packageDecoder.RigistHandleErrorCallback(HandleError);
|
||||
|
||||
// 创建字节缓冲类
|
||||
// 注意:字节缓冲区长度,推荐4倍最大包体长度
|
||||
int encoderPackageMaxSize = packageBodyMaxSize + _packageEncoder.GetPackageHeaderSize();
|
||||
int decoderPakcageMaxSize = packageBodyMaxSize + _packageDecoder.GetPackageHeaderSize();
|
||||
_encodeBuffer = new RingBuffer(encoderPackageMaxSize * 4);
|
||||
_decodeBuffer = new RingBuffer(decoderPakcageMaxSize * 4);
|
||||
_receiveBuffer = new byte[decoderPakcageMaxSize];
|
||||
|
||||
// 创建IOCP接收类
|
||||
_receiveArgs.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed);
|
||||
_receiveArgs.SetBuffer(_receiveBuffer, 0, _receiveBuffer.Length);
|
||||
|
||||
// 创建IOCP发送类
|
||||
_sendArgs.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed);
|
||||
_sendArgs.SetBuffer(_encodeBuffer.GetBuffer(), 0, _encodeBuffer.Capacity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测Socket是否已连接
|
||||
/// </summary>
|
||||
public bool IsConnected()
|
||||
{
|
||||
if (_socket == null)
|
||||
return false;
|
||||
return _socket.Connected;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_socket != null)
|
||||
_socket.Shutdown(SocketShutdown.Both);
|
||||
|
||||
_receiveArgs.Dispose();
|
||||
_sendArgs.Dispose();
|
||||
|
||||
_sendQueue.Clear();
|
||||
_receiveQueue.Clear();
|
||||
_decodeTempList.Clear();
|
||||
|
||||
_encodeBuffer.Clear();
|
||||
_decodeBuffer.Clear();
|
||||
|
||||
_isSending = false;
|
||||
_isReceiving = false;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// throws if client process has already closed, so it is not necessary to catch.
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_socket != null)
|
||||
{
|
||||
_socket.Close();
|
||||
_socket = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 主线程内更新
|
||||
/// </summary>
|
||||
public void Update()
|
||||
{
|
||||
if (_socket == null || _socket.Connected == false)
|
||||
return;
|
||||
|
||||
// 接收数据
|
||||
UpdateReceiving();
|
||||
|
||||
// 发送数据
|
||||
UpdateSending();
|
||||
}
|
||||
private void UpdateReceiving()
|
||||
{
|
||||
if (_isReceiving == false)
|
||||
{
|
||||
_isReceiving = true;
|
||||
|
||||
// 请求操作
|
||||
bool willRaiseEvent = _socket.ReceiveAsync(_receiveArgs);
|
||||
if (!willRaiseEvent)
|
||||
{
|
||||
ProcessReceive(_receiveArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void UpdateSending()
|
||||
{
|
||||
if (_isSending == false && _sendQueue.Count > 0)
|
||||
{
|
||||
_isSending = true;
|
||||
|
||||
// 清空缓存
|
||||
_encodeBuffer.Clear();
|
||||
|
||||
// 合并数据一起发送
|
||||
while (_sendQueue.Count > 0)
|
||||
{
|
||||
// 如果不够写入一个最大的消息包
|
||||
int encoderPackageMaxSize = _packageBodyMaxSize + _packageEncoder.GetPackageHeaderSize();
|
||||
if (_encodeBuffer.WriteableBytes < encoderPackageMaxSize)
|
||||
break;
|
||||
|
||||
// 数据压码
|
||||
INetPackage package = _sendQueue.Dequeue();
|
||||
_packageEncoder.Encode(_packageBodyMaxSize, _encodeBuffer, package);
|
||||
}
|
||||
|
||||
// 请求操作
|
||||
_sendArgs.SetBuffer(0, _encodeBuffer.ReadableBytes);
|
||||
bool willRaiseEvent = _socket.SendAsync(_sendArgs);
|
||||
if (!willRaiseEvent)
|
||||
{
|
||||
ProcessSend(_sendArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送网络包
|
||||
/// </summary>
|
||||
public void SendPackage(INetPackage package)
|
||||
{
|
||||
lock (_sendQueue)
|
||||
{
|
||||
_sendQueue.Enqueue(package);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取网络包
|
||||
/// </summary>
|
||||
public INetPackage PickPackage()
|
||||
{
|
||||
INetPackage package = null;
|
||||
lock (_receiveQueue)
|
||||
{
|
||||
if (_receiveQueue.Count > 0)
|
||||
package = _receiveQueue.Dequeue();
|
||||
}
|
||||
return package;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// This method is called whenever a receive or send operation is completed on a socket
|
||||
/// </summary>
|
||||
private void IO_Completed(object sender, SocketAsyncEventArgs e)
|
||||
{
|
||||
// determine which type of operation just completed and call the associated handler
|
||||
switch (e.LastOperation)
|
||||
{
|
||||
case SocketAsyncOperation.Receive:
|
||||
_context.Post(ProcessReceive, e);
|
||||
break;
|
||||
case SocketAsyncOperation.Send:
|
||||
_context.Post(ProcessSend, e);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("The last operation completed on the socket was not a receive or send");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 数据接收完成时
|
||||
/// </summary>
|
||||
private void ProcessReceive(object obj)
|
||||
{
|
||||
if (_socket == null)
|
||||
return;
|
||||
|
||||
SocketAsyncEventArgs e = obj as SocketAsyncEventArgs;
|
||||
|
||||
// check if the remote host closed the connection
|
||||
if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
|
||||
{
|
||||
// 如果数据写穿
|
||||
if (_decodeBuffer.IsWriteable(e.BytesTransferred) == false)
|
||||
{
|
||||
HandleError(true, "The channel fatal error");
|
||||
return;
|
||||
}
|
||||
|
||||
// 拷贝数据
|
||||
_decodeBuffer.WriteBytes(e.Buffer, 0, e.BytesTransferred);
|
||||
|
||||
// 数据解码
|
||||
_decodeTempList.Clear();
|
||||
_packageDecoder.Decode(_packageBodyMaxSize, _decodeBuffer, _decodeTempList);
|
||||
lock (_receiveQueue)
|
||||
{
|
||||
for (int i = 0; i < _decodeTempList.Count; i++)
|
||||
{
|
||||
_receiveQueue.Enqueue(_decodeTempList[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// 为接收下一段数据,投递接收请求
|
||||
e.SetBuffer(0, _receiveBuffer.Length);
|
||||
bool willRaiseEvent = _socket.ReceiveAsync(e);
|
||||
if (!willRaiseEvent)
|
||||
{
|
||||
ProcessReceive(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HandleError(true, $"ProcessReceive error : {e.SocketError}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 数据发送完成时
|
||||
/// </summary>
|
||||
private void ProcessSend(object obj)
|
||||
{
|
||||
if (_socket == null)
|
||||
return;
|
||||
|
||||
SocketAsyncEventArgs e = obj as SocketAsyncEventArgs;
|
||||
if (e.SocketError == SocketError.Success)
|
||||
{
|
||||
_isSending = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
HandleError(true, $"ProcessSend error : {e.SocketError}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 捕获异常错误
|
||||
/// </summary>
|
||||
private void HandleError(bool isDispose, string error)
|
||||
{
|
||||
UniLogger.Error(error);
|
||||
if (isDispose) Dispose();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 841a2723c2b01744fb4bcd170411249f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
159
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniNetwork/Runtime/TCP/TcpClient.cs
vendored
Normal file
159
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniNetwork/Runtime/TCP/TcpClient.cs
vendored
Normal file
|
@ -0,0 +1,159 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace UniFramework.Network
|
||||
{
|
||||
public class TcpClient : IDisposable
|
||||
{
|
||||
private class UserToken
|
||||
{
|
||||
public System.Action<SocketError> Callback;
|
||||
}
|
||||
|
||||
private TcpChannel _channel;
|
||||
private readonly int _packageBodyMaxSize;
|
||||
private readonly INetPackageEncoder _encoder;
|
||||
private readonly INetPackageDecoder _decoder;
|
||||
private readonly ThreadSyncContext _syncContext;
|
||||
|
||||
private TcpClient()
|
||||
{
|
||||
}
|
||||
internal TcpClient(int packageBodyMaxSize, INetPackageEncoder encoder, INetPackageDecoder decoder)
|
||||
{
|
||||
_packageBodyMaxSize = packageBodyMaxSize;
|
||||
_encoder = encoder;
|
||||
_decoder = decoder;
|
||||
_syncContext = new ThreadSyncContext();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新网络
|
||||
/// </summary>
|
||||
internal void Update()
|
||||
{
|
||||
_syncContext.Update();
|
||||
|
||||
if (_channel != null)
|
||||
_channel.Update();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 销毁网络
|
||||
/// </summary>
|
||||
internal void Destroy()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (_channel != null)
|
||||
{
|
||||
_channel.Dispose();
|
||||
_channel = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 发送网络包
|
||||
/// </summary>
|
||||
public void SendPackage(INetPackage package)
|
||||
{
|
||||
if (_channel != null)
|
||||
_channel.SendPackage(package);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取网络包
|
||||
/// </summary>
|
||||
public INetPackage PickPackage()
|
||||
{
|
||||
if (_channel == null)
|
||||
return null;
|
||||
|
||||
return _channel.PickPackage();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测Socket是否已连接
|
||||
/// </summary>
|
||||
public bool IsConnected()
|
||||
{
|
||||
if (_channel == null)
|
||||
return false;
|
||||
|
||||
return _channel.IsConnected();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 异步连接
|
||||
/// </summary>
|
||||
/// <param name="remote">IP终端</param>
|
||||
/// <param name="callback">连接回调</param>
|
||||
public void ConnectAsync(IPEndPoint remote, System.Action<SocketError> callback)
|
||||
{
|
||||
UserToken token = new UserToken()
|
||||
{
|
||||
Callback = callback,
|
||||
};
|
||||
|
||||
SocketAsyncEventArgs args = new SocketAsyncEventArgs();
|
||||
args.RemoteEndPoint = remote;
|
||||
args.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptEventArg_Completed);
|
||||
args.UserToken = token;
|
||||
|
||||
Socket clientSock = new Socket(remote.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||
bool willRaiseEvent = clientSock.ConnectAsync(args);
|
||||
if (!willRaiseEvent)
|
||||
{
|
||||
ProcessConnected(args);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理连接请求
|
||||
/// </summary>
|
||||
private void ProcessConnected(object obj)
|
||||
{
|
||||
SocketAsyncEventArgs e = obj as SocketAsyncEventArgs;
|
||||
UserToken token = (UserToken)e.UserToken;
|
||||
if (e.SocketError == SocketError.Success)
|
||||
{
|
||||
if (_channel != null)
|
||||
throw new Exception("TcpClient channel is created.");
|
||||
|
||||
// 创建频道
|
||||
_channel = new TcpChannel();
|
||||
_channel.InitChannel(_syncContext, e.ConnectSocket, _packageBodyMaxSize, _encoder, _decoder);
|
||||
}
|
||||
else
|
||||
{
|
||||
UniLogger.Error($"Network connecte error : {e.SocketError}");
|
||||
}
|
||||
|
||||
// 回调函数
|
||||
if (token.Callback != null)
|
||||
token.Callback.Invoke(e.SocketError);
|
||||
}
|
||||
|
||||
private void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e)
|
||||
{
|
||||
switch (e.LastOperation)
|
||||
{
|
||||
case SocketAsyncOperation.Connect:
|
||||
_syncContext.Post(ProcessConnected, e);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("The last operation completed on the socket was not a connect");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 23ae68566c8488c4099ef4652dd317c2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading;
|
||||
|
||||
namespace UniFramework.Network
|
||||
{
|
||||
/// <summary>
|
||||
/// 同步其它线程里的回调到主线程里
|
||||
/// 注意:Unity3D中需要设置Scripting Runtime Version为.NET4.6
|
||||
/// </summary>
|
||||
internal sealed class ThreadSyncContext : SynchronizationContext
|
||||
{
|
||||
private readonly ConcurrentQueue<Action> _safeQueue = new ConcurrentQueue<Action>();
|
||||
|
||||
/// <summary>
|
||||
/// 更新同步队列
|
||||
/// </summary>
|
||||
public void Update()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (_safeQueue.TryDequeue(out Action action) == false)
|
||||
return;
|
||||
action.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 向同步队列里投递一个回调方法
|
||||
/// </summary>
|
||||
public override void Post(SendOrPostCallback callback, object state)
|
||||
{
|
||||
Action action = new Action(() => { callback(state); });
|
||||
_safeQueue.Enqueue(action);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8dc088445ce08dc4e81bfe04a381b449
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "UniFramework.Network",
|
||||
"rootNamespace": "",
|
||||
"references": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 456617c24a0e6ba4dbc9a80e49a9a021
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
21
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniNetwork/Runtime/UniLogger.cs
vendored
Normal file
21
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniNetwork/Runtime/UniLogger.cs
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
using System.Diagnostics;
|
||||
|
||||
namespace UniFramework.Network
|
||||
{
|
||||
internal static class UniLogger
|
||||
{
|
||||
[Conditional("DEBUG")]
|
||||
public static void Log(string info)
|
||||
{
|
||||
UnityEngine.Debug.Log(info);
|
||||
}
|
||||
public static void Warning(string info)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning(info);
|
||||
}
|
||||
public static void Error(string info)
|
||||
{
|
||||
UnityEngine.Debug.LogError(info);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 96bf934b4c0166c489b7b967a7c23b32
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
92
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniNetwork/Runtime/UniNetwork.cs
vendored
Normal file
92
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniNetwork/Runtime/UniNetwork.cs
vendored
Normal file
|
@ -0,0 +1,92 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniFramework.Network
|
||||
{
|
||||
public static class UniNetwork
|
||||
{
|
||||
private static bool _isInitialize = false;
|
||||
private static GameObject _driver = null;
|
||||
private readonly static List<TcpClient> _tcpClients = new List<TcpClient>();
|
||||
|
||||
/// <summary>
|
||||
/// 初始化网络系统
|
||||
/// </summary>
|
||||
public static void Initalize()
|
||||
{
|
||||
if (_isInitialize)
|
||||
throw new Exception($"{nameof(UniNetwork)} is initialized !");
|
||||
|
||||
if (_isInitialize == false)
|
||||
{
|
||||
// 创建驱动器
|
||||
_isInitialize = true;
|
||||
_driver = new GameObject($"[{nameof(UniNetwork)}]");
|
||||
_driver.AddComponent<UniNetworkDriver>();
|
||||
UnityEngine.Object.DontDestroyOnLoad(_driver);
|
||||
UniLogger.Log($"{nameof(UniNetwork)} initalize !");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 销毁网络系统
|
||||
/// </summary>
|
||||
public static void Destroy()
|
||||
{
|
||||
if (_isInitialize)
|
||||
{
|
||||
foreach (var client in _tcpClients)
|
||||
{
|
||||
client.Destroy();
|
||||
}
|
||||
_tcpClients.Clear();
|
||||
|
||||
_isInitialize = false;
|
||||
if (_driver != null)
|
||||
GameObject.Destroy(_driver);
|
||||
UniLogger.Log($"{nameof(UniNetwork)} destroy all !");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新网络系统
|
||||
/// </summary>
|
||||
internal static void Update()
|
||||
{
|
||||
if (_isInitialize)
|
||||
{
|
||||
foreach (var client in _tcpClients)
|
||||
{
|
||||
client.Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建TCP客户端
|
||||
/// </summary>
|
||||
/// <param name="packageBodyMaxSize">网络包体最大长度</param>
|
||||
public static TcpClient CreateTcpClient(int packageBodyMaxSize, INetPackageEncoder encoder, INetPackageDecoder decoder)
|
||||
{
|
||||
if (_isInitialize == false)
|
||||
throw new Exception($"{nameof(UniNetwork)} not initialized !");
|
||||
|
||||
var client = new TcpClient(packageBodyMaxSize, encoder, decoder);
|
||||
_tcpClients.Add(client);
|
||||
return client;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 销毁TCP客户端
|
||||
/// </summary>
|
||||
public static void DestroyTcpClient(TcpClient client)
|
||||
{
|
||||
if (client == null)
|
||||
return;
|
||||
|
||||
client.Dispose();
|
||||
_tcpClients.Remove(client);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6dce5e59401e1344bbd9aabf981383b5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,12 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace UniFramework.Network
|
||||
{
|
||||
internal class UniNetworkDriver : MonoBehaviour
|
||||
{
|
||||
void Update()
|
||||
{
|
||||
UniNetwork.Update();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2490b5980d0936344a4c3574bcced111
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7cfeaa68459d1cb4f96e62f6b7bd9fd7
|
||||
guid: 2348da7d2a69de841a7ad5508df0bf90
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace UniFramework.Pooling
|
|||
{
|
||||
internal class GameObjectPool
|
||||
{
|
||||
private readonly Transform _poolRoot;
|
||||
private readonly GameObject _root;
|
||||
private readonly Queue<InstantiateOperation> _cacheOperations;
|
||||
private readonly bool _dontDestroy;
|
||||
private readonly int _initCapacity;
|
||||
|
@ -48,9 +48,10 @@ namespace UniFramework.Pooling
|
|||
}
|
||||
|
||||
|
||||
public GameObjectPool(GameObject poolRoot, string location, bool dontDestroy, int initCapacity, int maxCapacity, float destroyTime)
|
||||
public GameObjectPool(GameObject poolingRoot, string location, bool dontDestroy, int initCapacity, int maxCapacity, float destroyTime)
|
||||
{
|
||||
_poolRoot = poolRoot.transform;
|
||||
_root = new GameObject(location);
|
||||
_root.transform.parent = poolingRoot.transform;
|
||||
Location = location;
|
||||
|
||||
_dontDestroy = dontDestroy;
|
||||
|
@ -73,7 +74,7 @@ namespace UniFramework.Pooling
|
|||
// 创建初始对象
|
||||
for (int i = 0; i < _initCapacity; i++)
|
||||
{
|
||||
var operation = AssetHandle.InstantiateAsync(_poolRoot);
|
||||
var operation = AssetHandle.InstantiateAsync(_root.transform);
|
||||
_cacheOperations.Enqueue(operation);
|
||||
}
|
||||
}
|
||||
|
@ -88,11 +89,7 @@ namespace UniFramework.Pooling
|
|||
AssetHandle = null;
|
||||
|
||||
// 销毁游戏对象
|
||||
foreach (var operation in _cacheOperations)
|
||||
{
|
||||
if (operation.Result != null)
|
||||
GameObject.Destroy(operation.Result);
|
||||
}
|
||||
GameObject.Destroy(_root);
|
||||
_cacheOperations.Clear();
|
||||
|
||||
SpawnCount = 0;
|
||||
|
@ -207,7 +204,7 @@ namespace UniFramework.Pooling
|
|||
if (gameObj != null)
|
||||
{
|
||||
gameObj.SetActive(false);
|
||||
gameObj.transform.SetParent(_poolRoot);
|
||||
gameObj.transform.SetParent(_root.transform);
|
||||
gameObj.transform.SetPositionAndRotation(Vector3.zero, Quaternion.identity);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "UniSingleton",
|
||||
"name": "UniFramework.Pooling",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:e34a5702dd353724aa315fb8011f08c3"
|
|
@ -1,5 +1,5 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c4d0461b6228c584dab24fbeb8dc4907
|
||||
guid: 645ad92cafefcc144b8a9811864e1d73
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"name": "UniFramework.Singleton",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:e34a5702dd353724aa315fb8011f08c3"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": true,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 13f396e17446c5545bd76be7fda54f4d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
90
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniTween/README.md
vendored
Normal file
90
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniTween/README.md
vendored
Normal file
|
@ -0,0 +1,90 @@
|
|||
# UniFramework.Tween
|
||||
|
||||
一个轻量级的补间动画系统。(扩展方便,使用灵活,功能强大)
|
||||
|
||||
初始化补间动画系统
|
||||
|
||||
```c#
|
||||
using UnityEngine;
|
||||
using UniFramework.Tween;
|
||||
|
||||
void Start()
|
||||
{
|
||||
// 初始化补间动画系统
|
||||
UniTween.Initalize();
|
||||
}
|
||||
```
|
||||
|
||||
传统编程
|
||||
|
||||
```c#
|
||||
void Start()
|
||||
{
|
||||
// 原地停留1秒,然后向上移动,停留1秒,然后同时缩小并回归原位。
|
||||
var tween = UniTween.AllocateSequence
|
||||
(
|
||||
UniTween.AllocateDelay(1f),
|
||||
this.transform.TweenMove(0.5f, new Vector3(0, 256, 0)),
|
||||
UniTween.AllocateDelay(1f),
|
||||
UniTween.AllocateParallel
|
||||
(
|
||||
this.transform.TweenScaleTo(0.5f, new Vector3(0.2f, 0.2f, 1f)),
|
||||
this.transform.TweenMove(0.5f, new Vector3(0, 0, 0))
|
||||
)
|
||||
);
|
||||
this.gameObject.PlayTween(tween);
|
||||
}
|
||||
```
|
||||
|
||||
链式编程
|
||||
|
||||
```c#
|
||||
void Start()
|
||||
{
|
||||
// 原地停留1秒,然后向上移动,停留1秒,然后同时缩小并回归原位。
|
||||
ITweenChain tween = UniTween.AllocateSequence();
|
||||
tween.Delay(1f).
|
||||
Append(this.transform.TweenMove(0.5f, new Vector3(0, 256, 0))).
|
||||
Delay(1f).
|
||||
SwitchToParallel().
|
||||
Append(this.transform.TweenScaleTo(0.5f, new Vector3(0.2f, 0.2f, 1f))).
|
||||
Append(this.transform.TweenMove(0.5f, new Vector3(0, 0, 0)));
|
||||
this.gameObject.PlayTween(tween);
|
||||
}
|
||||
```
|
||||
|
||||
默认的公共补间方法一共有30种,还可以使用AnimationCurve补充效果
|
||||
|
||||
```c#
|
||||
public AnimationCurve EaseCurve;
|
||||
|
||||
public void PlayAnim()
|
||||
{
|
||||
var tween = this.transform.TweenScaleTo(1f, Vector3.zero).SetEase(EaseCurve);
|
||||
UniTween.Play(tween);
|
||||
}
|
||||
```
|
||||
|
||||
扩展支持任意对象
|
||||
|
||||
```c#
|
||||
// 扩展支持Image对象
|
||||
public static class UnityEngine_UI_Image_Tween_Extension
|
||||
{
|
||||
public static ColorTween TweenColor(this Image obj, float duration, Color from, Color to)
|
||||
{
|
||||
ColorTween node = ColorTween.Allocate(duration, from, to);
|
||||
node.SetOnUpdate((result) => { obj.color = result; });
|
||||
return node;
|
||||
}
|
||||
public static ColorTween TweenColorTo(this Image obj, float duration, Color to)
|
||||
{
|
||||
return TweenColor(obj, duration, obj.color, to);
|
||||
}
|
||||
public static ColorTween TweenColorFrom(this Image obj, float duration, Color from)
|
||||
{
|
||||
return TweenColor(obj, duration, from, obj.color);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
7
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniTween/README.md.meta
vendored
Normal file
7
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniTween/README.md.meta
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ac85f5ddcea96cd46931986ac50d5204
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniTween/Runtime.meta
vendored
Normal file
8
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniTween/Runtime.meta
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f3cdaa08c50e0dd4c940fb957314cf2d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
24
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniTween/Runtime/ETweenLoop.cs
vendored
Normal file
24
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniTween/Runtime/ETweenLoop.cs
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
|
||||
namespace UniFramework.Tween
|
||||
{
|
||||
/// <summary>
|
||||
/// 补间循环类型
|
||||
/// </summary>
|
||||
public enum ETweenLoop
|
||||
{
|
||||
/// <summary>
|
||||
/// 只执行一次
|
||||
/// </summary>
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// 从头执行
|
||||
/// </summary>
|
||||
Restart,
|
||||
|
||||
/// <summary>
|
||||
/// 反复执行
|
||||
/// </summary>
|
||||
PingPong,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1391131ea350c9640a05910d947a38b8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
29
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniTween/Runtime/ETweenStatus.cs
vendored
Normal file
29
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniTween/Runtime/ETweenStatus.cs
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
|
||||
namespace UniFramework.Tween
|
||||
{
|
||||
/// <summary>
|
||||
/// 补间动画状态
|
||||
/// </summary>
|
||||
public enum ETweenStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// 空闲状态
|
||||
/// </summary>
|
||||
Idle,
|
||||
|
||||
/// <summary>
|
||||
/// 运行中
|
||||
/// </summary>
|
||||
Runing,
|
||||
|
||||
/// <summary>
|
||||
/// 已经完成
|
||||
/// </summary>
|
||||
Completed,
|
||||
|
||||
/// <summary>
|
||||
/// 已被终止
|
||||
/// </summary>
|
||||
Abort,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 315dd5291803c6b40a9ab70933c4d50b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
namespace UniFramework.Tween
|
||||
{
|
||||
public interface ITweenChain
|
||||
{
|
||||
ITweenChain Append(ITweenNode node);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1a69c912d23f3f446aa6dee33054bcc1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
15
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniTween/Runtime/ITweenNode.cs
vendored
Normal file
15
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniTween/Runtime/ITweenNode.cs
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
|
||||
namespace UniFramework.Tween
|
||||
{
|
||||
public interface ITweenNode
|
||||
{
|
||||
/// <summary>
|
||||
/// 节点状态
|
||||
/// </summary>
|
||||
ETweenStatus Status { get; }
|
||||
|
||||
void OnUpdate(float deltaTime);
|
||||
void OnDispose();
|
||||
void Abort();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d96ae9e29e307e44087fc62fdc6fc259
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 466dbe54c22685f48b0bc73113a7edd1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,126 @@
|
|||
|
||||
namespace UniFramework.Tween
|
||||
{
|
||||
public static partial class TweenChainExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 执行节点
|
||||
/// </summary>
|
||||
public static ITweenChain Execute(this ITweenChain chain, System.Action execute)
|
||||
{
|
||||
return chain.Append(UniTween.AllocateExecute(execute));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 条件等待节点
|
||||
/// </summary>
|
||||
public static ITweenChain Until(this ITweenChain chain, System.Func<bool> condition)
|
||||
{
|
||||
return chain.Append(UniTween.AllocateUntil(condition));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 并行执行的复合节点
|
||||
/// </summary>
|
||||
public static ITweenChain AppendParallel(this ITweenChain chain, params ITweenNode[] nodes)
|
||||
{
|
||||
var node = UniTween.AllocateParallel(nodes);
|
||||
chain.Append(node);
|
||||
return chain;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 顺序执行的复合节点
|
||||
/// </summary>
|
||||
public static ITweenChain AppendSequence(this ITweenChain chain, params ITweenNode[] nodes)
|
||||
{
|
||||
var node = UniTween.AllocateSequence(nodes);
|
||||
chain.Append(node);
|
||||
return chain;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 随机执行的复合节点
|
||||
/// </summary>
|
||||
public static ITweenChain AppendSelector(this ITweenChain chain, params ITweenNode[] nodes)
|
||||
{
|
||||
var node = UniTween.AllocateSelector(nodes);
|
||||
chain.Append(node);
|
||||
return chain;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 并行执行的复合节点
|
||||
/// </summary>
|
||||
public static ITweenChain SwitchToParallel(this ITweenChain chain, params ITweenNode[] nodes)
|
||||
{
|
||||
var node = UniTween.AllocateParallel(nodes);
|
||||
chain.Append(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 顺序执行的复合节点
|
||||
/// </summary>
|
||||
public static ITweenChain SwitchToSequence(this ITweenChain chain, params ITweenNode[] nodes)
|
||||
{
|
||||
var node = UniTween.AllocateSequence(nodes);
|
||||
chain.Append(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 随机执行的复合节点
|
||||
/// </summary>
|
||||
public static ITweenChain SwitchToSelector(this ITweenChain chain, params ITweenNode[] nodes)
|
||||
{
|
||||
var node = UniTween.AllocateSelector(nodes);
|
||||
chain.Append(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 延迟计时节点
|
||||
/// </summary>
|
||||
public static ITweenChain Delay(this ITweenChain chain, float delay, System.Action trigger = null)
|
||||
{
|
||||
return chain.Append(UniTween.AllocateDelay(delay, trigger));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重复计时节点
|
||||
/// 注意:该节点为无限时长
|
||||
/// </summary>
|
||||
public static ITweenChain Repeat(this ITweenChain chain, float delay, float interval, System.Action trigger = null)
|
||||
{
|
||||
return chain.Append(UniTween.AllocateRepeat(delay, interval, trigger));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重复计时节点
|
||||
/// </summary>
|
||||
public static ITweenChain Repeat(this ITweenChain chain, float delay, float interval, float duration, System.Action trigger = null)
|
||||
{
|
||||
return chain.Append(UniTween.AllocateRepeat(delay, interval, duration, trigger));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重复计时节点
|
||||
/// </summary>
|
||||
public static ITweenChain Repeat(this ITweenChain chain, float delay, float interval, long maxRepeatCount, System.Action trigger = null)
|
||||
{
|
||||
return chain.Append(UniTween.AllocateRepeat(delay, interval, maxRepeatCount, trigger));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 持续计时节点
|
||||
/// </summary>
|
||||
public static ITweenChain Duration(this ITweenChain chain, float delay, float duration, System.Action trigger = null)
|
||||
{
|
||||
return chain.Append(UniTween.AllocateDuration(delay, duration, trigger));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7f62323a6b951174b9a207f7e8d3971b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
228
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniTween/Runtime/TweenEase.cs
vendored
Normal file
228
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniTween/Runtime/TweenEase.cs
vendored
Normal file
|
@ -0,0 +1,228 @@
|
|||
//--------------------------------------------------
|
||||
// Author : David Ochmann
|
||||
// Website:https://easings.net/
|
||||
//--------------------------------------------------
|
||||
using System;
|
||||
|
||||
namespace UniFramework.Tween
|
||||
{
|
||||
/// <summary>
|
||||
/// 公共补间方法
|
||||
/// </summary>
|
||||
public static class TweenEase
|
||||
{
|
||||
public static class Linear
|
||||
{
|
||||
public static float Default(float t, float b, float c, float d)
|
||||
{
|
||||
return c * t / d + b;
|
||||
}
|
||||
public static float EaseIn(float t, float b, float c, float d)
|
||||
{
|
||||
return c * t / d + b;
|
||||
}
|
||||
public static float EaseOut(float t, float b, float c, float d)
|
||||
{
|
||||
return c * t / d + b;
|
||||
}
|
||||
public static float EaseInOut(float t, float b, float c, float d)
|
||||
{
|
||||
return c * t / d + b;
|
||||
}
|
||||
}
|
||||
public static class Sine
|
||||
{
|
||||
public static float EaseIn(float t, float b, float c, float d)
|
||||
{
|
||||
return -c * (float)Math.Cos(t / d * ((float)Math.PI / 2)) + c + b;
|
||||
}
|
||||
public static float EaseOut(float t, float b, float c, float d)
|
||||
{
|
||||
return c * (float)Math.Sin(t / d * ((float)Math.PI / 2)) + b;
|
||||
}
|
||||
public static float EaseInOut(float t, float b, float c, float d)
|
||||
{
|
||||
return -c / 2f * ((float)Math.Cos((float)Math.PI * t / d) - 1) + b;
|
||||
}
|
||||
}
|
||||
public static class Quad
|
||||
{
|
||||
public static float EaseIn(float t, float b, float c, float d)
|
||||
{
|
||||
return c * (t /= d) * t + b;
|
||||
}
|
||||
public static float EaseOut(float t, float b, float c, float d)
|
||||
{
|
||||
return -c * (t /= d) * (t - 2) + b;
|
||||
}
|
||||
public static float EaseInOut(float t, float b, float c, float d)
|
||||
{
|
||||
if ((t /= d / 2) < 1) return c / 2 * t * t + b;
|
||||
return -c / 2 * ((--t) * (t - 2) - 1) + b;
|
||||
}
|
||||
}
|
||||
public static class Cubic
|
||||
{
|
||||
public static float EaseIn(float t, float b, float c, float d)
|
||||
{
|
||||
return c * (t /= d) * t * t + b;
|
||||
}
|
||||
public static float EaseOut(float t, float b, float c, float d)
|
||||
{
|
||||
return c * ((t = t / d - 1) * t * t + 1) + b;
|
||||
}
|
||||
public static float EaseInOut(float t, float b, float c, float d)
|
||||
{
|
||||
if ((t /= d / 2) < 1) return c / 2 * t * t * t + b;
|
||||
return c / 2 * ((t -= 2) * t * t + 2) + b;
|
||||
}
|
||||
}
|
||||
public static class Quart
|
||||
{
|
||||
public static float EaseIn(float t, float b, float c, float d)
|
||||
{
|
||||
return c * (t /= d) * t * t * t + b;
|
||||
}
|
||||
public static float EaseOut(float t, float b, float c, float d)
|
||||
{
|
||||
return -c * ((t = t / d - 1) * t * t * t - 1) + b;
|
||||
}
|
||||
public static float EaseInOut(float t, float b, float c, float d)
|
||||
{
|
||||
if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b;
|
||||
return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
|
||||
}
|
||||
}
|
||||
public static class Quint
|
||||
{
|
||||
public static float EaseIn(float t, float b, float c, float d)
|
||||
{
|
||||
return c * (t /= d) * t * t * t * t + b;
|
||||
}
|
||||
public static float EaseOut(float t, float b, float c, float d)
|
||||
{
|
||||
return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
|
||||
}
|
||||
public static float EaseInOut(float t, float b, float c, float d)
|
||||
{
|
||||
if ((t /= d / 2) < 1) return c / 2 * t * t * t * t * t + b;
|
||||
return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
|
||||
}
|
||||
}
|
||||
public static class Expo
|
||||
{
|
||||
public static float EaseIn(float t, float b, float c, float d)
|
||||
{
|
||||
return (t == 0) ? b : c * (float)Math.Pow(2, 10 * (t / d - 1)) + b;
|
||||
}
|
||||
public static float EaseOut(float t, float b, float c, float d)
|
||||
{
|
||||
return (t == d) ? b + c : c * (-(float)Math.Pow(2, -10 * t / d) + 1) + b;
|
||||
}
|
||||
public static float EaseInOut(float t, float b, float c, float d)
|
||||
{
|
||||
if (t == 0) return b;
|
||||
if (t == d) return b + c;
|
||||
if ((t /= d / 2) < 1) return c / 2 * (float)Math.Pow(2, 10 * (t - 1)) + b;
|
||||
return c / 2 * (-(float)Math.Pow(2, -10 * --t) + 2) + b;
|
||||
}
|
||||
}
|
||||
public static class Circ
|
||||
{
|
||||
public static float EaseIn(float t, float b, float c, float d)
|
||||
{
|
||||
return -c * ((float)Math.Sqrt(1 - (t /= d) * t) - 1) + b;
|
||||
}
|
||||
public static float EaseOut(float t, float b, float c, float d)
|
||||
{
|
||||
return c * (float)Math.Sqrt(1 - (t = t / d - 1) * t) + b;
|
||||
}
|
||||
public static float EaseInOut(float t, float b, float c, float d)
|
||||
{
|
||||
if ((t /= d / 2) < 1) return -c / 2 * ((float)Math.Sqrt(1 - t * t) - 1) + b;
|
||||
return c / 2 * ((float)Math.Sqrt(1 - (t -= 2) * t) + 1) + b;
|
||||
}
|
||||
}
|
||||
public static class Back
|
||||
{
|
||||
public static float EaseIn(float t, float b, float c, float d)
|
||||
{
|
||||
float s = 1.70158f;
|
||||
return c * (t /= d) * t * ((s + 1) * t - s) + b;
|
||||
}
|
||||
public static float EaseOut(float t, float b, float c, float d)
|
||||
{
|
||||
float s = 1.70158f;
|
||||
return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
|
||||
}
|
||||
public static float EaseInOut(float t, float b, float c, float d)
|
||||
{
|
||||
float s = 1.70158f;
|
||||
if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525f)) + 1) * t - s)) + b;
|
||||
return c / 2 * ((t -= 2) * t * (((s *= (1.525f)) + 1) * t + s) + 2) + b;
|
||||
}
|
||||
}
|
||||
public static class Elastic
|
||||
{
|
||||
public static float EaseIn(float t, float b, float c, float d)
|
||||
{
|
||||
if (t == 0) return b; if ((t /= d) == 1) return b + c; float p = d * .3f;
|
||||
|
||||
float a = c;
|
||||
float s = p / 4;
|
||||
|
||||
return -(a * (float)Math.Pow(2, 10 * (t -= 1)) * (float)Math.Sin((t * d - s) * (2 * (float)Math.PI) / p)) + b;
|
||||
}
|
||||
public static float EaseOut(float t, float b, float c, float d)
|
||||
{
|
||||
if (t == 0) return b; if ((t /= d) == 1) return b + c; float p = d * .3f;
|
||||
|
||||
float a = c;
|
||||
float s = p / 4;
|
||||
|
||||
return (a * (float)Math.Pow(2, -10 * t) * (float)Math.Sin((t * d - s) * (2 * (float)Math.PI) / p) + c + b);
|
||||
}
|
||||
public static float EaseInOut(float t, float b, float c, float d)
|
||||
{
|
||||
if (t == 0) return b; if ((t /= d / 2) == 2) return b + c; float p = d * (.3f * 1.5f);
|
||||
|
||||
float a = c;
|
||||
float s = p / 4;
|
||||
|
||||
if (t < 1) return -.5f * (a * (float)Math.Pow(2, 10 * (t -= 1)) * (float)Math.Sin((t * d - s) * (2 * (float)Math.PI) / p)) + b;
|
||||
return a * (float)Math.Pow(2, -10 * (t -= 1)) * (float)Math.Sin((t * d - s) * (2 * (float)Math.PI) / p) * .5f + c + b;
|
||||
}
|
||||
}
|
||||
public static class Bounce
|
||||
{
|
||||
public static float EaseIn(float t, float b, float c, float d)
|
||||
{
|
||||
return c - Bounce.EaseOut(d - t, 0, c, d) + b;
|
||||
}
|
||||
public static float EaseOut(float t, float b, float c, float d)
|
||||
{
|
||||
if ((t /= d) < (1 / 2.75f))
|
||||
{
|
||||
return c * (7.5625f * t * t) + b;
|
||||
}
|
||||
else if (t < (2 / 2.75f))
|
||||
{
|
||||
return c * (7.5625f * (t -= (1.5f / 2.75f)) * t + .75f) + b;
|
||||
}
|
||||
else if (t < (2.5f / 2.75f))
|
||||
{
|
||||
return c * (7.5625f * (t -= (2.25f / 2.75f)) * t + .9375f) + b;
|
||||
}
|
||||
else
|
||||
{
|
||||
return c * (7.5625f * (t -= (2.625f / 2.75f)) * t + .984375f) + b;
|
||||
}
|
||||
}
|
||||
public static float EaseInOut(float t, float b, float c, float d)
|
||||
{
|
||||
if (t < d / 2) return Bounce.EaseIn(t * 2, 0, c, d) * .5f + b;
|
||||
else return Bounce.EaseOut(t * 2 - d, 0, c, d) * .5f + c * .5f + b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f73be75c1e900a64bab71022ae49d368
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 688bba5b21bb5fa40ac50ba0292aae82
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,22 @@
|
|||
using UniFramework.Tween;
|
||||
|
||||
namespace UnityEngine
|
||||
{
|
||||
public static class UnityEngine_CanvasGroup_Tween_Extension
|
||||
{
|
||||
public static FloatTween TweenAlpha(this CanvasGroup obj, float duration, float from, float to)
|
||||
{
|
||||
FloatTween node = FloatTween.Allocate(duration, from, to);
|
||||
node.SetOnUpdate((result) => { obj.alpha = result; });
|
||||
return node;
|
||||
}
|
||||
public static FloatTween TweenAlphaTo(this CanvasGroup obj, float duration, float to)
|
||||
{
|
||||
return TweenAlpha(obj, duration, obj.alpha, to);
|
||||
}
|
||||
public static FloatTween TweenAlphaFrom(this CanvasGroup obj, float duration, float from)
|
||||
{
|
||||
return TweenAlpha(obj, duration, from, obj.alpha);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8852afd144dfb644d9828c95d09536fd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,31 @@
|
|||
using UniFramework.Tween;
|
||||
|
||||
namespace UnityEngine
|
||||
{
|
||||
public static class UnityEngine_GameObject_Tween_Extension
|
||||
{
|
||||
/// <summary>
|
||||
/// 播放补间动画
|
||||
/// </summary>
|
||||
public static TweenHandle PlayTween(this GameObject go, ITweenNode tweenRoot)
|
||||
{
|
||||
return UniTween.Play(tweenRoot, go);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 播放补间动画
|
||||
/// </summary>
|
||||
public static TweenHandle PlayTween(this GameObject go, ITweenChain tweenRoot)
|
||||
{
|
||||
return UniTween.Play(tweenRoot, go);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 播放补间动画
|
||||
/// </summary>
|
||||
public static TweenHandle PlayTween(this GameObject go, ChainNode tweenRoot)
|
||||
{
|
||||
return UniTween.Play(tweenRoot, go);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 257bf3445be76d349a37454396799650
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,26 @@
|
|||
using UniFramework.Tween;
|
||||
|
||||
namespace UnityEngine
|
||||
{
|
||||
public static class UnityEngine_RectTransform_Tween_Extension
|
||||
{
|
||||
public static Vector2Tween TweenAnchoredPosition(this RectTransform obj, float duration, Vector2 from, Vector2 to)
|
||||
{
|
||||
Vector2Tween node = Vector2Tween.Allocate(duration, from, to);
|
||||
node.SetOnUpdate(
|
||||
(result) =>
|
||||
{
|
||||
obj.anchoredPosition = result;
|
||||
});
|
||||
return node;
|
||||
}
|
||||
public static Vector2Tween TweenAnchoredPositionTo(this RectTransform obj, float duration, Vector2 to)
|
||||
{
|
||||
return TweenAnchoredPosition(obj, duration, obj.anchoredPosition, to);
|
||||
}
|
||||
public static Vector2Tween TweenAnchoredPositionFrom(this RectTransform obj, float duration, Vector2 from)
|
||||
{
|
||||
return TweenAnchoredPosition(obj, duration, from, obj.anchoredPosition);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6c8bdaa0ab683904f9b5c002995e43e5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,137 @@
|
|||
using UniFramework.Tween;
|
||||
|
||||
namespace UnityEngine
|
||||
{
|
||||
public static class UnityEngine_Transform_Tween_Extension
|
||||
{
|
||||
public static Vector3Tween TweenScale(this Transform obj, float duration, Vector3 from, Vector3 to)
|
||||
{
|
||||
Vector3Tween node = Vector3Tween.Allocate(duration, from, to);
|
||||
node.SetOnUpdate((result) => { obj.localScale = result; });
|
||||
return node;
|
||||
}
|
||||
public static Vector3Tween TweenScaleTo(this Transform obj, float duration, Vector3 to)
|
||||
{
|
||||
return TweenScale(obj, duration, obj.localScale, to);
|
||||
}
|
||||
public static Vector3Tween TweenScaleFrom(this Transform obj, float duration, Vector3 from)
|
||||
{
|
||||
return TweenScale(obj, duration, from, obj.localScale);
|
||||
}
|
||||
|
||||
public static Vector3Tween ShakePosition(this Transform obj, float duration, Vector3 magnitude, bool relativeWorld = false)
|
||||
{
|
||||
Vector3 position = relativeWorld ? obj.position : obj.localPosition;
|
||||
Vector3Tween node = Vector3Tween.Allocate(duration, position, position);
|
||||
node.SetOnUpdate(
|
||||
(result) =>
|
||||
{
|
||||
if (relativeWorld)
|
||||
obj.position = result;
|
||||
else
|
||||
obj.localPosition = result;
|
||||
});
|
||||
node.SetLerp(
|
||||
(from, to, progress) =>
|
||||
{
|
||||
return TweenMath.Shake(magnitude, from, progress);
|
||||
});
|
||||
node.SetLoop(ETweenLoop.PingPong, 1);
|
||||
return node;
|
||||
}
|
||||
public static Vector3Tween TweenMove(this Transform obj, float duration, Vector3 dest, bool relativeWorld = false)
|
||||
{
|
||||
Vector3Tween node = Vector3Tween.Allocate(duration, dest, dest);
|
||||
node.SetOnUpdate(
|
||||
(result) =>
|
||||
{
|
||||
if (relativeWorld)
|
||||
obj.position = result;
|
||||
else
|
||||
obj.localPosition = result;
|
||||
});
|
||||
node.SetOnBegin(
|
||||
() =>
|
||||
{
|
||||
if (relativeWorld)
|
||||
node.SetValueFrom(obj.position);
|
||||
else
|
||||
node.SetValueFrom(obj.localPosition);
|
||||
}
|
||||
);
|
||||
return node;
|
||||
}
|
||||
public static Vector3Tween TweenPosition(this Transform obj, float duration, Vector3 from, Vector3 to, bool relativeWorld = false)
|
||||
{
|
||||
Vector3Tween node = Vector3Tween.Allocate(duration, from, to);
|
||||
node.SetOnUpdate(
|
||||
(result) =>
|
||||
{
|
||||
if (relativeWorld)
|
||||
obj.position = result;
|
||||
else
|
||||
obj.localPosition = result;
|
||||
});
|
||||
return node;
|
||||
}
|
||||
public static Vector3Tween TweenPositionTo(this Transform obj, float duration, Vector3 to, bool relativeWorld = false)
|
||||
{
|
||||
Vector3 from = relativeWorld ? obj.position : obj.localPosition;
|
||||
return TweenPosition(obj, duration, from, to, relativeWorld);
|
||||
}
|
||||
public static Vector3Tween TweenPositionFrom(this Transform obj, float duration, Vector3 from, bool relativeWorld = false)
|
||||
{
|
||||
Vector3 to = relativeWorld ? obj.position : obj.localPosition;
|
||||
return TweenPosition(obj, duration, from, to, relativeWorld);
|
||||
}
|
||||
|
||||
public static Vector3Tween TweenAngles(this Transform obj, float duration, Vector3 from, Vector3 to, bool relativeWorld = false)
|
||||
{
|
||||
Vector3Tween node = Vector3Tween.Allocate(duration, from, to);
|
||||
node.SetOnUpdate(
|
||||
(result) =>
|
||||
{
|
||||
if (relativeWorld)
|
||||
obj.eulerAngles = result;
|
||||
else
|
||||
obj.localEulerAngles = result;
|
||||
});
|
||||
node.SetLerp(TweenMath.AngleLerp);
|
||||
return node;
|
||||
}
|
||||
public static Vector3Tween TweenAnglesTo(this Transform obj, float duration, Vector3 to, bool relativeWorld = false)
|
||||
{
|
||||
Vector3 from = relativeWorld ? obj.eulerAngles : obj.localEulerAngles;
|
||||
return TweenAngles(obj, duration, from, to, relativeWorld);
|
||||
}
|
||||
public static Vector3Tween TweenAnglesFrom(this Transform obj, float duration, Vector3 from, bool relativeWorld = false)
|
||||
{
|
||||
Vector3 to = relativeWorld ? obj.eulerAngles : obj.localEulerAngles;
|
||||
return TweenAngles(obj, duration, from, to, relativeWorld);
|
||||
}
|
||||
|
||||
public static QuaternionTween TweenRotation(this Transform obj, float duration, Quaternion from, Quaternion to, bool relativeWorld = false)
|
||||
{
|
||||
QuaternionTween node = QuaternionTween.Allocate(duration, from, to);
|
||||
node.SetOnUpdate(
|
||||
(result) =>
|
||||
{
|
||||
if (relativeWorld)
|
||||
obj.rotation = result;
|
||||
else
|
||||
obj.localRotation = result;
|
||||
});
|
||||
return node;
|
||||
}
|
||||
public static QuaternionTween TweenRotationTo(this Transform obj, float duration, Quaternion to, bool relativeWorld = false)
|
||||
{
|
||||
Quaternion from = relativeWorld ? obj.rotation : obj.localRotation;
|
||||
return TweenRotation(obj, duration, from, to, relativeWorld);
|
||||
}
|
||||
public static QuaternionTween TweenRotationFrom(this Transform obj, float duration, Quaternion from, bool relativeWorld = false)
|
||||
{
|
||||
Quaternion to = relativeWorld ? obj.rotation : obj.localRotation;
|
||||
return TweenRotation(obj, duration, from, to, relativeWorld);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3848269d8b1e18e4fab08c34a729fc36
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,22 @@
|
|||
using UniFramework.Tween;
|
||||
|
||||
namespace UnityEngine.UI
|
||||
{
|
||||
public static class UnityEngine_UI_Image_Tween_Extension
|
||||
{
|
||||
public static ColorTween TweenColor(this Image obj, float duration, Color from, Color to)
|
||||
{
|
||||
ColorTween node = ColorTween.Allocate(duration, from, to);
|
||||
node.SetOnUpdate((result) => { obj.color = result; });
|
||||
return node;
|
||||
}
|
||||
public static ColorTween TweenColorTo(this Image obj, float duration, Color to)
|
||||
{
|
||||
return TweenColor(obj, duration, obj.color, to);
|
||||
}
|
||||
public static ColorTween TweenColorFrom(this Image obj, float duration, Color from)
|
||||
{
|
||||
return TweenColor(obj, duration, from, obj.color);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: dc5c855c625d63e429c5975f4c87ae20
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,22 @@
|
|||
using UniFramework.Tween;
|
||||
|
||||
namespace UnityEngine.UI
|
||||
{
|
||||
public static class UnityEngine_UI_Text_Tween_Extension
|
||||
{
|
||||
public static ColorTween TweenColor(this Text obj, float duration, Color from, Color to)
|
||||
{
|
||||
ColorTween node = ColorTween.Allocate(duration, from, to);
|
||||
node.SetOnUpdate((result) => { obj.color = result; });
|
||||
return node;
|
||||
}
|
||||
public static ColorTween TweenColorTo(this Text obj, float duration, Color to)
|
||||
{
|
||||
return TweenColor(obj, duration, obj.color, to);
|
||||
}
|
||||
public static ColorTween TweenColorFrom(this Text obj, float duration, Color from)
|
||||
{
|
||||
return TweenColor(obj, duration, from, obj.color);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 65a5efc0be7931241ba1ad7ea25398d5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
90
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniTween/Runtime/TweenHandle.cs
vendored
Normal file
90
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniTween/Runtime/TweenHandle.cs
vendored
Normal file
|
@ -0,0 +1,90 @@
|
|||
|
||||
namespace UniFramework.Tween
|
||||
{
|
||||
/// <summary>
|
||||
/// 补间动画句柄
|
||||
/// </summary>
|
||||
public class TweenHandle
|
||||
{
|
||||
private readonly ITweenNode _tweenRoot;
|
||||
private readonly UnityEngine.Object _unityObject;
|
||||
private readonly bool _safeMode;
|
||||
private bool _hasException = false;
|
||||
internal int InstanceID { private set; get; }
|
||||
|
||||
private TweenHandle()
|
||||
{
|
||||
}
|
||||
internal TweenHandle(ITweenNode tweenRoot, UnityEngine.Object unityObject)
|
||||
{
|
||||
_tweenRoot = tweenRoot;
|
||||
_unityObject = unityObject;
|
||||
|
||||
if (unityObject == null)
|
||||
{
|
||||
InstanceID = 0;
|
||||
_safeMode = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
InstanceID = unityObject.GetInstanceID();
|
||||
_safeMode = true;
|
||||
}
|
||||
}
|
||||
internal void Update(float deltaTime)
|
||||
{
|
||||
try
|
||||
{
|
||||
_tweenRoot.OnUpdate(deltaTime);
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
_hasException = true;
|
||||
UniLogger.Warning($"TweenNode has exception : {e}");
|
||||
}
|
||||
}
|
||||
internal void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
_tweenRoot.OnDispose();
|
||||
}
|
||||
catch(System.Exception e)
|
||||
{
|
||||
UniLogger.Warning($"TweenNode has exception : {e}");
|
||||
}
|
||||
}
|
||||
internal bool IsCanRemove()
|
||||
{
|
||||
// 检测游戏对象是否销毁
|
||||
if (_safeMode)
|
||||
{
|
||||
if (_unityObject == null)
|
||||
{
|
||||
_tweenRoot.Abort();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// 检测运行过程是否发生异常
|
||||
if (_hasException)
|
||||
{
|
||||
_tweenRoot.Abort();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_tweenRoot.Status == ETweenStatus.Abort || _tweenRoot.Status == ETweenStatus.Completed)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 终止补间动画
|
||||
/// </summary>
|
||||
public void Abort()
|
||||
{
|
||||
_tweenRoot.Abort();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 20d19c757b8deb54790d4fb99e8a5315
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
65
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniTween/Runtime/TweenMath.cs
vendored
Normal file
65
Assets/YooAsset/Samples~/Space Shooter/ThirdParty/UniFramework/UniTween/Runtime/TweenMath.cs
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace UniFramework.Tween
|
||||
{
|
||||
public static class TweenMath
|
||||
{
|
||||
/// <summary>
|
||||
/// 角度插值
|
||||
/// </summary>
|
||||
public static Vector3 AngleLerp(Vector3 from, Vector3 to, float progress)
|
||||
{
|
||||
float x = Mathf.LerpAngle(from.x, to.x, progress);
|
||||
float y = Mathf.LerpAngle(from.y, to.y, progress);
|
||||
float z = Mathf.LerpAngle(from.z, to.z, progress);
|
||||
Vector3 result = new Vector3(x, y, z);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 二阶贝塞尔曲线
|
||||
/// </summary>
|
||||
public static Vector3 QuadBezier(Vector3 p1, Vector3 c, Vector3 p2, float progress)
|
||||
{
|
||||
float t = progress;
|
||||
float d = 1f - t;
|
||||
return d * d * p1 + 2f * d * t * c + t * t * p2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 三阶贝塞尔曲线
|
||||
/// </summary>
|
||||
public static Vector3 CubicBezier(Vector3 p1, Vector3 c1, Vector3 c2, Vector3 p2, float progress)
|
||||
{
|
||||
float t = progress;
|
||||
float d = 1f - t;
|
||||
return d * d * d * p1 + 3f * d * d * t * c1 + 3f * d * t * t * c2 + t * t * t * p2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 样条曲线
|
||||
/// </summary>
|
||||
public static Vector3 CatmullRoom(Vector3 c1, Vector3 p1, Vector3 p2, Vector3 c2, float progress)
|
||||
{
|
||||
float t = progress;
|
||||
return .5f *
|
||||
(
|
||||
(-c1 + 3f * p1 - 3f * p2 + c2) * (t * t * t)
|
||||
+ (2f * c1 - 5f * p1 + 4f * p2 - c2) * (t * t)
|
||||
+ (-c1 + p2) * t
|
||||
+ 2f * p1
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 震动采样
|
||||
/// </summary>
|
||||
public static Vector3 Shake(Vector3 magnitude, Vector3 position, float progress)
|
||||
{
|
||||
float x = Random.Range(-magnitude.x, magnitude.x) * progress;
|
||||
float y = Random.Range(-magnitude.y, magnitude.y) * progress;
|
||||
float z = Random.Range(-magnitude.z, magnitude.z) * progress;
|
||||
return position + new Vector3(x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue