Files
Convention-Unity-Demo/Assets/Scripts/Interaction/IInteraction.cs

348 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Collections;
using System.Collections.Generic;
using Convention;
using Demo.Editor.UI;
using UnityEngine;
using UnityEngine.Events;
namespace Demo.Game
{
public interface IHookInteraction
{
}
public abstract class IInteraction : TimelineScriptObject
{
protected override void SetupTimelineItem(TimelineItem item)
{
item.SetupDuration(new(VisibleDuration.x, VisibleDuration.y), GetTimelineItemColor());
}
public enum DurationStats
{
BeforeBegin = 0,
BeforeEnd,
After,
Judgement
}
[Header(nameof(VisibleDuration))]
[Content, SerializeField] private Vector2 VisibleDuration;
[Content, SerializeField] public UnityEvent VisibleDurationBeginEvent = new(), VisibleDurationEndEvent = new();
[Content, SerializeField] private DurationStats VisibleDurationStats = default;
[Header(nameof(InteractiveDuration))]
[Content, SerializeField] private Vector2 InteractiveDuration;
[Content, SerializeField] public UnityEvent InteractiveDurationBeginEvent = new(), InteractiveDurationEndEvent = new();
[Content, SerializeField] private DurationStats InteractiveDurationStats = default;
[Header(nameof(InteractableScoreInterval))]
[Content, SerializeField] private Vector2 InteractableScoreInterval;
[Content, SerializeField] public UnityEvent InteractableScoreIntervalBeginEvent = new(), InteractableScoreIntervalEndEvent = new();
[Content, SerializeField] private DurationStats InteractableScoreIntervalStats = default;
[Header(nameof(InteractableIntervalThatCanScoreBest))]
[Content, SerializeField] private Vector2 InteractableIntervalThatCanScoreBest;
[Content, SerializeField] public UnityEvent InteractableIntervalThatCanScoreBestBeginEvent = new(), InteractableIntervalThatCanScoreBestEndEvent = new();
[Content, SerializeField] private DurationStats InteractableIntervalThatCanScoreBestStats = default;
[Header("Judgement")]
[Content, SerializeField] private float BestJudgementTimePoint = -1;
[Content, SerializeField] public UnityEvent<JudgementLevel> JudgementEvent = new();
public float GetBestJudgementTimePoint()
{
return BestJudgementTimePoint;
}
public bool IsInInteractiveDuration()
{
return InteractiveDurationStats == DurationStats.BeforeEnd;
}
public bool IsInInteractiveDuration(float time)
{
return time > InteractiveDuration.x && time < InteractiveDuration.y;
}
public const int JudgementLevelCount = 3;
public override IEnumerator LoadScript(string script)
{
yield return base.LoadScript(script);
if (BestJudgementTimePoint < 0)
{
BestJudgementTimePoint = Mathf.Lerp(InteractableIntervalThatCanScoreBest.x, InteractableIntervalThatCanScoreBest.y, 0.5f);
}
}
public override IEnumerator UnloadScript()
{
yield return base.UnloadScript();
VisibleDurationBeginEvent = new();
VisibleDurationEndEvent = new();
InteractiveDurationBeginEvent = new();
InteractiveDurationEndEvent = new();
InteractableScoreIntervalBeginEvent = new();
InteractableScoreIntervalEndEvent = new();
InteractableIntervalThatCanScoreBestBeginEvent = new();
InteractableIntervalThatCanScoreBestEndEvent = new();
BestJudgementTimePoint = -1;
}
public void InvokeJudgement(JudgementLevel level)
{
if (level == JudgementLevel.None)
return;
JudgementEvent.Invoke(level);
VisibleDurationStats = DurationStats.Judgement;
VisibleDurationEndEvent.Invoke();
InteractiveDurationStats = DurationStats.Judgement;
InteractableScoreIntervalStats = DurationStats.Judgement;
InteractableIntervalThatCanScoreBestStats = DurationStats.Judgement;
InteractiveDurationEndEvent.Invoke();
InteractableScoreIntervalEndEvent.Invoke();
InteractableIntervalThatCanScoreBestEndEvent.Invoke();
}
private static DurationStats UpdateDurationStats(float begin, UnityEvent beginEvent, float end, UnityEvent endEvent,
float current, DurationStats currentStats)
{
if (currentStats == DurationStats.After)
return DurationStats.After;
else if (current < begin)
return DurationStats.BeforeBegin;
else if (current < end)
{
if (currentStats == DurationStats.BeforeBegin)
beginEvent.Invoke();
return DurationStats.BeforeEnd;
}
else if (currentStats == DurationStats.BeforeEnd)
{
endEvent.Invoke();
}
return DurationStats.After;
}
public enum JudgementLevel
{
None = -2,//No Judge
Default = -1,
BestLevel = 0,//Level0
ScoreLevel = 1,//Level1
Bad = 128,
}
public abstract JudgementLevel JudgementBehaviour(float timePoint);
protected override void UpdateTicks(float currentTime, float deltaTime, TickType tickType)
{
if (tickType == TickType.Start || tickType == TickType.Reset)
{
VisibleDurationStats = DurationStats.BeforeBegin;
InteractiveDurationStats = DurationStats.BeforeBegin;
InteractableScoreIntervalStats = DurationStats.BeforeBegin;
InteractableIntervalThatCanScoreBestStats = DurationStats.BeforeBegin;
}
//预判断
if (VisibleDurationStats == DurationStats.Judgement)
return;
//检定
InvokeJudgement(JudgementBehaviour(currentTime));
if (tickType == TickType.Update)
{
// 可见区间
VisibleDurationStats = UpdateDurationStats(VisibleDuration.x, VisibleDurationBeginEvent, VisibleDuration.y, VisibleDurationEndEvent,
currentTime, VisibleDurationStats);
if (VisibleDurationStats != DurationStats.BeforeEnd)
return;
// 可判定区间
InteractiveDurationStats = UpdateDurationStats(InteractiveDuration.x, InteractiveDurationBeginEvent, InteractiveDuration.y, InteractiveDurationEndEvent,
currentTime, InteractiveDurationStats);
if (InteractiveDurationStats != DurationStats.BeforeEnd)
return;
// 1级判定区间
InteractableScoreIntervalStats = UpdateDurationStats(InteractableScoreInterval.x, InteractableScoreIntervalBeginEvent, InteractableScoreInterval.y, InteractableScoreIntervalEndEvent,
currentTime, InteractableScoreIntervalStats);
if (InteractableScoreIntervalStats != DurationStats.BeforeEnd)
return;
// 0级判定区间
InteractableIntervalThatCanScoreBestStats = UpdateDurationStats(InteractableIntervalThatCanScoreBest.x, InteractableIntervalThatCanScoreBestBeginEvent, InteractableIntervalThatCanScoreBest.y, InteractableIntervalThatCanScoreBestEndEvent,
currentTime, InteractableIntervalThatCanScoreBestStats);
}
}
/// <summary>
/// 通过传递对称区间进行初始化
/// </summary>
/// <param name="bestJudgementTimePoint">最佳判定点</param>
/// <param name="interactableIntervalThatCanScoreBest">区间时长,最终结果为
/// (bestJudgementTimePoint-interactableIntervalThatCanScoreBest/2,bestJudgementTimePoint+interactableIntervalThatCanScoreBest/2)</param>
/// <param name="interactableScoreInterval">区间时长,最终结果为
/// (bestJudgementTimePoint-interactableScoreInterval/2,bestJudgementTimePoint+interactableScoreInterval/2)</param>
/// <param name="interactiveDuration">区间时长,最终结果为
/// (bestJudgementTimePoint-interactiveDuration/2,bestJudgementTimePoint+interactiveDuration/2)</param>
/// <param name="visibleDuration">区间时长,最终结果为
/// (bestJudgementTimePoint-visibleDuration/2,bestJudgementTimePoint+visibleDuration/2)</param>
[ScriptableCall(@"
<summary>
通过传递对称区间进行初始化
</summary>
<param name=""bestJudgementTimePoint"">最佳判定点</param>
<param name=""interactableIntervalThatCanScoreBest"">区间时长,最终结果为
(bestJudgementTimePoint-interactableIntervalThatCanScoreBest/2,bestJudgementTimePoint+interactableIntervalThatCanScoreBest/2)</param>
<param name=""interactableScoreInterval"">区间时长,最终结果为
(bestJudgementTimePoint-interactableScoreInterval/2,bestJudgementTimePoint+interactableScoreInterval/2)</param>
<param name=""interactiveDuration"">区间时长,最终结果为
(bestJudgementTimePoint-interactiveDuration/2,bestJudgementTimePoint+interactiveDuration/2)</param>
<param name=""visibleDuration"">区间时长,最终结果为
(bestJudgementTimePoint-visibleDuration/2,bestJudgementTimePoint+visibleDuration/2)</param>
")]
public void SetupJudgementLevels(
string bestJudgementTimePoint,
string interactableIntervalThatCanScoreBest,
string interactableScoreInterval,
string interactiveDuration,
string visibleDuration)
{
var bestJudgementTimePointValue = Parse(bestJudgementTimePoint);
// InteractableIntervalThatCanScoreBest
var interactableIntervalThatCanScoreBestValue = Parse(interactableIntervalThatCanScoreBest) * 0.5f;
InteractableIntervalThatCanScoreBest = new(bestJudgementTimePointValue - interactableIntervalThatCanScoreBestValue,
bestJudgementTimePointValue + interactableIntervalThatCanScoreBestValue);
// InteractableScoreInterval
var interactableScoreIntervalValue = Parse(interactableScoreInterval) * 0.5f;
InteractableScoreInterval = new(bestJudgementTimePointValue - interactableScoreIntervalValue,
bestJudgementTimePointValue + interactableScoreIntervalValue);
// InteractiveDuration
var interactiveDurationValue = Parse(interactiveDuration) * 0.5f;
InteractiveDuration = new(bestJudgementTimePointValue - interactiveDurationValue,
bestJudgementTimePointValue + interactiveDurationValue);
// InteractableScoreInterval
var visibleDurationValue = Parse(visibleDuration) * 0.5f;
VisibleDuration = new(bestJudgementTimePointValue - visibleDurationValue,
bestJudgementTimePointValue + visibleDurationValue);
}
/// <summary>
/// 设置可见区间显现但不可判定3级判定区间开始时间
/// </summary>
/// <param name="value"></param>
[ScriptableCall(@"
<summary>
设置可见区间显现但不可判定3级判定区间开始时间
</summary>
<param name=""value""></param>
")]
public void SetVisibleDurationBegin(string value)
{
VisibleDuration.x = Parse(value);
}
/// <summary>
/// 设置可见区间显现但不可判定3级判定区间结束时间
/// </summary>
/// <param name="value"></param>
[ScriptableCall(@"
<summary>
设置可见区间显现但不可判定3级判定区间结束时间
</summary>
<param name=""value""></param>
")]
public void SetVisibleDurationEnd(string value)
{
VisibleDuration.y = Parse(value);
}
/// <summary>
/// 设置2级判定区间可判定但错误的开始时间
/// </summary>
/// <param name="value"></param>
[ScriptableCall(@"
<summary>
设置2级判定区间可判定但错误的开始时间
</summary>
<param name=""value""></param>
")]
public void SetInteractiveDurationBegin(string value)
{
InteractiveDuration.x = Parse(value);
}
/// <summary>
/// 设置2级判定区间可判定但错误的结束时间
/// </summary>
/// <param name="value"></param>
[ScriptableCall(@"
<summary>
设置2级判定区间可判定但错误的结束时间
</summary>
<param name=""value""></param>
")]
public void SetInteractiveDurationEnd(string value)
{
InteractiveDuration.y = Parse(value);
}
/// <summary>
/// 设置1级判定区间可判定的开始时间
/// </summary>
/// <param name="value"></param>
[ScriptableCall(@"
<summary>
设置1级判定区间可判定的开始时间
</summary>
<param name=""value""></param>
")]
public void SetInteractableScoreIntervalBegin(string value)
{
InteractableScoreInterval.x = Parse(value);
}
/// <summary>
/// 设置1级判定区间可判定的结束时间
/// </summary>
/// <param name="value"></param>
[ScriptableCall(@"
<summary>
设置1级判定区间可判定的结束时间
</summary>
<param name=""value""></param>
")]
public void SetInteractableScoreIntervalEnd(string value)
{
InteractableScoreInterval.y = Parse(value);
}
/// <summary>
/// 设置0级判定区间最佳判定开始时间
/// </summary>
/// <param name="value"></param>
[ScriptableCall(@"
<summary>
设置0级判定区间最佳判定开始时间
</summary>
<param name=""value""></param>
")]
public void SetInteractableIntervalThatCanScoreBestBegin(string value)
{
InteractableIntervalThatCanScoreBest.x = Parse(value);
}
/// <summary>
/// 设置0级判定区间最佳判定结束时间
/// </summary>
/// <param name="value"></param>
[ScriptableCall(@"
<summary>
设置0级判定区间最佳判定结束时间
</summary>
<param name=""value""></param>
")]
public void SetInteractableIntervalThatCanScoreBestEnd(string value)
{
InteractableIntervalThatCanScoreBest.y = Parse(value);
}
}
}