feat: polish game HUD scoring and results
This commit is contained in:
@@ -69,10 +69,10 @@ namespace VRBeats
|
||||
if (audioSource == null)
|
||||
return 0.0f;
|
||||
|
||||
if (hasScheduledClip)
|
||||
return (float)(AudioSettings.dspTime - scheduledDspStartTime);
|
||||
if (hasScheduledClip || scheduledDspStartTime >= 0.0)
|
||||
return Mathf.Max(0.0f, (float)(AudioSettings.dspTime - scheduledDspStartTime));
|
||||
|
||||
return audioSource.time;
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -98,8 +98,9 @@ namespace VRBeats
|
||||
TrimExpiredSamples(now);
|
||||
BuildRibbon(wideMesh, now, 0f, 1f, trailColor, 0.10f, 0.36f);
|
||||
|
||||
Color coreColor = Color.Lerp(Color.white, trailColor, 0.45f);
|
||||
BuildRibbon(coreMesh, now, 0.42f, 1f, coreColor, 0.14f, 0.48f);
|
||||
Color coreColor = Color.Lerp(Color.white, trailColor, CoreColorWeight(trailColor));
|
||||
float alphaMultiplier = VisibilityAlphaMultiplier(trailColor);
|
||||
BuildRibbon(coreMesh, now, 0.42f, 1f, coreColor, 0.14f * alphaMultiplier, 0.48f * alphaMultiplier);
|
||||
|
||||
lastBase = basePos;
|
||||
lastTip = tipPos;
|
||||
@@ -147,10 +148,11 @@ namespace VRBeats
|
||||
{
|
||||
trailColor = NormalizeColor(color);
|
||||
EnsureRenderers();
|
||||
ApplyMaterialColor(wideMaterial, trailColor, 0.34f);
|
||||
float alphaMultiplier = VisibilityAlphaMultiplier(trailColor);
|
||||
ApplyMaterialColor(wideMaterial, trailColor, 0.34f * alphaMultiplier);
|
||||
|
||||
Color coreColor = Color.Lerp(Color.white, trailColor, 0.45f);
|
||||
ApplyMaterialColor(coreMaterial, coreColor, 0.50f);
|
||||
Color coreColor = Color.Lerp(Color.white, trailColor, CoreColorWeight(trailColor));
|
||||
ApplyMaterialColor(coreMaterial, coreColor, 0.50f * alphaMultiplier);
|
||||
}
|
||||
|
||||
private void ResolveBladeAnchors()
|
||||
@@ -424,6 +426,21 @@ namespace VRBeats
|
||||
return color;
|
||||
}
|
||||
|
||||
private static float CoreColorWeight(Color color)
|
||||
{
|
||||
return IsBlueDominant(color) ? 0.78f : 0.45f;
|
||||
}
|
||||
|
||||
private static float VisibilityAlphaMultiplier(Color color)
|
||||
{
|
||||
return IsBlueDominant(color) ? 1.35f : 1f;
|
||||
}
|
||||
|
||||
private static bool IsBlueDominant(Color color)
|
||||
{
|
||||
return color.b > color.r && color.b >= color.g;
|
||||
}
|
||||
|
||||
private static Color WithAlpha(Color color, float alpha)
|
||||
{
|
||||
color.a = Mathf.Clamp01(alpha);
|
||||
|
||||
@@ -32,8 +32,9 @@ namespace VRBeats
|
||||
tangent = saberUp.sqrMagnitude > 0.001f ? saberUp.normalized : Vector3.right;
|
||||
lift = hitDir.sqrMagnitude > 0.001f ? hitDir.normalized : Vector3.up;
|
||||
|
||||
glowLine = CreateLine("Glow", 0.16f, 0.45f);
|
||||
coreLine = CreateLine("Core", 0.045f, 0.95f);
|
||||
float widthMultiplier = IsBlueDominant(effectColor) ? 1.18f : 1.0f;
|
||||
glowLine = CreateLine("Glow", 0.16f * widthMultiplier, 0.45f);
|
||||
coreLine = CreateLine("Core", 0.045f * widthMultiplier, 0.95f);
|
||||
StartCoroutine(Animate());
|
||||
}
|
||||
|
||||
@@ -67,8 +68,9 @@ namespace VRBeats
|
||||
float bend = Mathf.Lerp(0.12f, 0.34f, t);
|
||||
float alpha = 1.0f - t;
|
||||
|
||||
UpdateLine(glowLine, length, bend, alpha * 0.45f);
|
||||
UpdateLine(coreLine, length * 0.88f, bend * 0.55f, alpha * 0.95f);
|
||||
float alphaMultiplier = VisibilityAlphaMultiplier(effectColor);
|
||||
UpdateLine(glowLine, length, bend, alpha * 0.45f * alphaMultiplier);
|
||||
UpdateLine(coreLine, length * 0.88f, bend * 0.55f, alpha * 0.95f * alphaMultiplier);
|
||||
|
||||
age += Time.deltaTime;
|
||||
yield return null;
|
||||
@@ -136,5 +138,15 @@ namespace VRBeats
|
||||
color.a = 1.0f;
|
||||
return color;
|
||||
}
|
||||
|
||||
private static float VisibilityAlphaMultiplier(Color color)
|
||||
{
|
||||
return IsBlueDominant(color) ? 1.35f : 1.0f;
|
||||
}
|
||||
|
||||
private static bool IsBlueDominant(Color color)
|
||||
{
|
||||
return color.b > color.r && color.b >= color.g;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,8 +14,9 @@ namespace VRBeats
|
||||
|
||||
public void Construct(Color c)
|
||||
{
|
||||
float visibilityMultiplier = IsBlueDominant(c) ? 1.6f : 1.0f;
|
||||
materialBindings.SetUseEmmisiveIntensity(false);
|
||||
materialBindings.SetEmmisiveColor(c * glowEffect);
|
||||
materialBindings.SetEmmisiveColor(c * glowEffect * visibilityMultiplier);
|
||||
PlayAnimation();
|
||||
}
|
||||
|
||||
@@ -35,6 +36,11 @@ namespace VRBeats
|
||||
}).SetOwner(gameObject); ;
|
||||
}
|
||||
|
||||
private static bool IsBlueDominant(Color color)
|
||||
{
|
||||
return color.b > color.r && color.b >= color.g;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using UnityEngine;
|
||||
using Platinio.TweenEngine;
|
||||
using UnityEngine;
|
||||
using TMPro;
|
||||
|
||||
namespace VRBeats
|
||||
@@ -7,22 +6,25 @@ namespace VRBeats
|
||||
public class FinalScoreLabel : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private TextMeshProUGUI scoreText = null;
|
||||
[SerializeField] private float scoreFadeTime = 10.0f;
|
||||
[SerializeField] private int length = 10;
|
||||
|
||||
private string initialValue = "";
|
||||
private ScoreManager scoreManager = null;
|
||||
private GameObject resultRoot = null;
|
||||
private TextMeshProUGUI rankShadowText = null;
|
||||
private TextMeshProUGUI rankDepthText = null;
|
||||
private TextMeshProUGUI rankMainText = null;
|
||||
private TextMeshProUGUI resultScoreText = null;
|
||||
private TextMeshProUGUI resultComboText = null;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
for (int n = 0; n < length; n++)
|
||||
{
|
||||
initialValue += "0";
|
||||
}
|
||||
|
||||
scoreManager = FindFirstObjectByType<ScoreManager>();
|
||||
ApplyPopupTextStyle();
|
||||
|
||||
BuildResultLayout();
|
||||
}
|
||||
|
||||
public void ShowScore()
|
||||
@@ -30,39 +32,68 @@ namespace VRBeats
|
||||
if (scoreText == null || scoreManager == null)
|
||||
return;
|
||||
|
||||
PlatinioTween.instance.ValueTween( 0.0f , scoreManager.CurrentScore , Mathf.Min(scoreFadeTime, 0.8f)).SetOnUpdateFloat(delegate (float v)
|
||||
SetTitleActive(false);
|
||||
gameObject.CancelAllTweens();
|
||||
|
||||
if (resultRoot != null)
|
||||
{
|
||||
SetScore( (int)v );
|
||||
}).SetOnComplete(delegate
|
||||
scoreText.gameObject.SetActive(false);
|
||||
PopulateResultLayout();
|
||||
resultRoot.SetActive(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
scoreText.text = scoreManager.BuildResultSummary(length);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetValues()
|
||||
{
|
||||
gameObject.CancelAllTweens();
|
||||
|
||||
if (resultRoot != null)
|
||||
resultRoot.SetActive(false);
|
||||
if (scoreText != null)
|
||||
scoreText.gameObject.SetActive(true);
|
||||
|
||||
SetTitleActive(true);
|
||||
ApplyPopupTextStyle();
|
||||
|
||||
if (scoreText != null)
|
||||
scoreText.text = initialValue;
|
||||
}
|
||||
|
||||
|
||||
private void SetScore(int score)
|
||||
private void PopulateResultLayout()
|
||||
{
|
||||
if (this.scoreText == null)
|
||||
if (scoreManager == null ||
|
||||
rankShadowText == null ||
|
||||
rankDepthText == null ||
|
||||
rankMainText == null ||
|
||||
resultScoreText == null ||
|
||||
resultComboText == null)
|
||||
return;
|
||||
|
||||
string scoreText = score.ToString();
|
||||
int addLength = Mathf.Max( length - scoreText.Length , 0);
|
||||
string addZeros = "";
|
||||
for (int n = 0; n < addLength; n++)
|
||||
{
|
||||
addZeros += "0";
|
||||
}
|
||||
string rank = scoreManager.Rank;
|
||||
Color mainColor = HexToColor(scoreManager.RankColorHex);
|
||||
Color depthColor = HexToColor(GetRankDepthColorHex(rank));
|
||||
|
||||
this.scoreText.text = addZeros + scoreText;
|
||||
rankShadowText.text = rank;
|
||||
rankDepthText.text = rank;
|
||||
rankDepthText.color = depthColor;
|
||||
rankMainText.text = rank;
|
||||
rankMainText.color = mainColor;
|
||||
resultScoreText.text = scoreManager.CurrentScore.ToString("N0");
|
||||
resultComboText.text = $"MAX COMBO {scoreManager.MaxCombo}";
|
||||
}
|
||||
|
||||
private void SetTitleActive(bool active)
|
||||
{
|
||||
Transform titleObj = scoreText != null
|
||||
? scoreText.rectTransform.parent?.Find("Title")
|
||||
: null;
|
||||
|
||||
if (titleObj != null)
|
||||
titleObj.gameObject.SetActive(active);
|
||||
}
|
||||
|
||||
private void ApplyPopupTextStyle()
|
||||
@@ -70,15 +101,110 @@ namespace VRBeats
|
||||
if (scoreText == null)
|
||||
return;
|
||||
|
||||
scoreText.enableAutoSizing = false;
|
||||
scoreText.fontSize = 4.4f;
|
||||
scoreText.alignment = TextAlignmentOptions.Center;
|
||||
scoreText.overflowMode = TextOverflowModes.Overflow;
|
||||
RectTransform rect = scoreText.rectTransform;
|
||||
rect.anchorMin = new Vector2(0.5f, 0.5f);
|
||||
rect.anchorMax = new Vector2(0.5f, 0.5f);
|
||||
rect.anchoredPosition = new Vector2(0.0f, 0.0f);
|
||||
rect.sizeDelta = new Vector2(620.0f, 250.0f);
|
||||
|
||||
scoreText.enableAutoSizing = true;
|
||||
scoreText.fontSizeMin = 1.2f;
|
||||
scoreText.fontSizeMax = 5.5f;
|
||||
scoreText.alignment = TextAlignmentOptions.MidlineLeft;
|
||||
scoreText.overflowMode = TextOverflowModes.Truncate;
|
||||
scoreText.textWrappingMode = TextWrappingModes.NoWrap;
|
||||
scoreText.lineSpacing = -18.0f;
|
||||
scoreText.lineSpacing = -10.0f;
|
||||
scoreText.color = Color.white;
|
||||
scoreText.richText = true;
|
||||
}
|
||||
|
||||
private void BuildResultLayout()
|
||||
{
|
||||
if (scoreText == null)
|
||||
return;
|
||||
|
||||
Transform parent = scoreText.rectTransform.parent;
|
||||
if (parent == null)
|
||||
return;
|
||||
|
||||
GameObject root = new GameObject("ResultLayoutRoot");
|
||||
root.transform.SetParent(parent, false);
|
||||
RectTransform rootRect = root.AddComponent<RectTransform>();
|
||||
rootRect.anchorMin = new Vector2(0.5f, 0.5f);
|
||||
rootRect.anchorMax = new Vector2(0.5f, 0.5f);
|
||||
rootRect.anchoredPosition = Vector2.zero;
|
||||
rootRect.sizeDelta = new Vector2(620.0f, 250.0f);
|
||||
root.SetActive(false);
|
||||
resultRoot = root;
|
||||
|
||||
// Rank badge left side — hierarchy order = draw order (shadow first, main on top)
|
||||
rankShadowText = MakeTmpLabel(root.transform, "RankShadowText",
|
||||
new Vector2(-166.0f, 6.0f), new Vector2(200.0f, 200.0f), 14.0f,
|
||||
new Color(0.0f, 0.0f, 0.0f, 0.55f), TextAlignmentOptions.Midline);
|
||||
rankDepthText = MakeTmpLabel(root.transform, "RankDepthText",
|
||||
new Vector2(-168.0f, 8.0f), new Vector2(200.0f, 200.0f), 14.0f,
|
||||
Color.white, TextAlignmentOptions.Midline);
|
||||
rankMainText = MakeTmpLabel(root.transform, "RankMainText",
|
||||
new Vector2(-170.0f, 10.0f), new Vector2(200.0f, 200.0f), 14.0f,
|
||||
Color.white, TextAlignmentOptions.Midline);
|
||||
|
||||
// Score and combo right side
|
||||
resultScoreText = MakeTmpLabel(root.transform, "ResultScoreText",
|
||||
new Vector2(70.0f, 35.0f), new Vector2(260.0f, 80.0f), 5.5f,
|
||||
Color.white, TextAlignmentOptions.MidlineLeft);
|
||||
resultComboText = MakeTmpLabel(root.transform, "ResultComboText",
|
||||
new Vector2(70.0f, -35.0f), new Vector2(260.0f, 50.0f), 3.8f,
|
||||
new Color(0.84f, 0.97f, 1.0f, 1.0f), TextAlignmentOptions.MidlineLeft);
|
||||
}
|
||||
|
||||
private TextMeshProUGUI MakeTmpLabel(Transform parent, string name,
|
||||
Vector2 pos, Vector2 size, float fontSize, Color color, TextAlignmentOptions align)
|
||||
{
|
||||
GameObject go = new GameObject(name);
|
||||
go.transform.SetParent(parent, false);
|
||||
RectTransform rect = go.AddComponent<RectTransform>();
|
||||
rect.anchorMin = new Vector2(0.5f, 0.5f);
|
||||
rect.anchorMax = new Vector2(0.5f, 0.5f);
|
||||
rect.anchoredPosition = pos;
|
||||
rect.sizeDelta = size;
|
||||
|
||||
TextMeshProUGUI tmp = go.AddComponent<TextMeshProUGUI>();
|
||||
tmp.fontSize = fontSize;
|
||||
tmp.color = color;
|
||||
tmp.alignment = align;
|
||||
tmp.overflowMode = TextOverflowModes.Overflow;
|
||||
tmp.textWrappingMode = TextWrappingModes.NoWrap;
|
||||
tmp.raycastTarget = false;
|
||||
|
||||
if (scoreText != null && scoreText.font != null)
|
||||
{
|
||||
tmp.font = scoreText.font;
|
||||
tmp.fontSharedMaterial = scoreText.fontSharedMaterial;
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private static string GetRankDepthColorHex(string rank)
|
||||
{
|
||||
switch (rank)
|
||||
{
|
||||
case "M": return "#7EEBFF";
|
||||
case "S+": return "#116BFF";
|
||||
case "S": return "#B56A16";
|
||||
case "A": return "#5CAA30";
|
||||
case "B": return "#B89E20";
|
||||
case "C": return "#C05A10";
|
||||
case "D": return "#B02040";
|
||||
default: return "#606870";
|
||||
}
|
||||
}
|
||||
|
||||
private static Color HexToColor(string hex)
|
||||
{
|
||||
if (ColorUtility.TryParseHtmlString(hex, out Color color))
|
||||
return color;
|
||||
return Color.white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,12 +29,13 @@ namespace VRBeats
|
||||
[SerializeField] private bool createMissingHudLabels = true;
|
||||
[SerializeField] private bool applyHudPlacement = true;
|
||||
[SerializeField] private Vector2 hudAnchoredPosition = new Vector2(0.0f, 1.65f);
|
||||
[SerializeField] private float perfectWindow = 0.08f;
|
||||
[SerializeField] private float greatWindow = 0.15f;
|
||||
[SerializeField] private float goodWindow = 0.25f;
|
||||
[SerializeField] private float perfectWindow = 0.11f;
|
||||
[SerializeField] private float greatWindow = 0.20f;
|
||||
[SerializeField] private float goodWindow = 0.32f;
|
||||
|
||||
private int maxMultiplier = 0;
|
||||
private const int MaxCourseScore = 1000000;
|
||||
private const float ProgressBarWidth = 150.0f;
|
||||
private float currentMultiplier = 1.0f;
|
||||
private int acumulateErrors = 0;
|
||||
private int errorLimit = 0;
|
||||
@@ -54,6 +55,8 @@ namespace VRBeats
|
||||
private float judgementTimer = 0.0f;
|
||||
private Text progressLabel = null;
|
||||
private Text rankLabel = null;
|
||||
private Image progressBarBackground = null;
|
||||
private Image progressBarFill = null;
|
||||
private Vector3 comboBaseScale = Vector3.one;
|
||||
private float songCurrentTime = 0.0f;
|
||||
private float songDuration = 0.0f;
|
||||
@@ -62,8 +65,20 @@ namespace VRBeats
|
||||
|
||||
private static bool hasPendingSliceTiming = false;
|
||||
private static float pendingSliceTiming = 0.0f;
|
||||
private static Font hudFont = null;
|
||||
private Image ringBackground = null;
|
||||
|
||||
public int CurrentScore => Mathf.RoundToInt(MaxCourseScore * AccuracyPercent / 100.0f);
|
||||
public int CurrentScore
|
||||
{
|
||||
get
|
||||
{
|
||||
float accuracyRatio = AccuracyPercent / 100.0f;
|
||||
float comboRatio = totalNoteCount > 0
|
||||
? maxCombo / (float)totalNoteCount
|
||||
: 0.0f;
|
||||
return Mathf.RoundToInt(800000.0f * accuracyRatio + 200000.0f * comboRatio);
|
||||
}
|
||||
}
|
||||
public float AccuracyPercent
|
||||
{
|
||||
get
|
||||
@@ -80,6 +95,8 @@ namespace VRBeats
|
||||
{
|
||||
get
|
||||
{
|
||||
if (CurrentScore >= MaxCourseScore) return "M";
|
||||
|
||||
float accuracy = AccuracyPercent;
|
||||
if (accuracy >= 98.0f) return "S+";
|
||||
if (accuracy >= 95.0f) return "S";
|
||||
@@ -91,6 +108,9 @@ namespace VRBeats
|
||||
}
|
||||
}
|
||||
|
||||
public int MaxCombo => maxCombo;
|
||||
public string RankColorHex => GetRankColorHex();
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
maxMultiplier = VR_BeatManager.instance.GameSettings.MaxMultiplier;
|
||||
@@ -99,6 +119,7 @@ namespace VRBeats
|
||||
if (multiplierLoader != null)
|
||||
multiplierLoader.fillAmount = 0.0f;
|
||||
|
||||
canvasGroup ??= GetComponent<CanvasGroup>() ?? gameObject.AddComponent<CanvasGroup>();
|
||||
PrepareHud();
|
||||
}
|
||||
|
||||
@@ -142,15 +163,23 @@ namespace VRBeats
|
||||
|
||||
public void SetSongProgress(float currentTime, float duration)
|
||||
{
|
||||
songCurrentTime = Mathf.Max(0.0f, currentTime);
|
||||
songDuration = Mathf.Max(0.0f, duration);
|
||||
songCurrentTime = songDuration > 0.0f
|
||||
? Mathf.Clamp(currentTime, 0.0f, songDuration)
|
||||
: Mathf.Max(0.0f, currentTime);
|
||||
}
|
||||
|
||||
public void OnGameOver()
|
||||
{
|
||||
gameObject.CancelAllTweens();
|
||||
if (canvasGroup != null)
|
||||
canvasGroup.Fade(0.0f, 0.5f).SetEase(Ease.EaseOutExpo).SetOwner(gameObject);
|
||||
{
|
||||
canvasGroup.alpha = 0.0f;
|
||||
canvasGroup.interactable = false;
|
||||
canvasGroup.blocksRaycasts = false;
|
||||
}
|
||||
|
||||
SetSaberVisibility(false);
|
||||
}
|
||||
|
||||
public void OnGameRestart()
|
||||
@@ -158,7 +187,13 @@ namespace VRBeats
|
||||
ResetThisComponent();
|
||||
gameObject.CancelAllTweens();
|
||||
if (canvasGroup != null)
|
||||
canvasGroup.Fade(1.0f, 0.5f).SetEase(Ease.EaseOutExpo).SetOwner(gameObject);
|
||||
{
|
||||
canvasGroup.alpha = 1.0f;
|
||||
canvasGroup.interactable = true;
|
||||
canvasGroup.blocksRaycasts = false;
|
||||
}
|
||||
|
||||
SetSaberVisibility(true);
|
||||
}
|
||||
|
||||
public void ResetThisComponent()
|
||||
@@ -220,17 +255,11 @@ namespace VRBeats
|
||||
|
||||
public string BuildResultSummary(int minScoreLength)
|
||||
{
|
||||
string score = CurrentScore.ToString();
|
||||
score = new string('0', Mathf.Max(minScoreLength - score.Length, 0)) + score;
|
||||
string badge = missCount == 0
|
||||
? (greatCount == 0 && goodCount == 0 ? "PERFECT PLAY" : "FULL COMBO")
|
||||
: "TRY AGAIN";
|
||||
string score = CurrentScore.ToString("N0");
|
||||
|
||||
return $"<size=150%><color=#41F2FF>{Rank}</color></size>\n" +
|
||||
$"<size=118%>{score}</size>\n" +
|
||||
$"<size=56%><color=#D7F7FF>ACC {AccuracyPercent:0.0}% {badge}</color></size>\n" +
|
||||
$"<size=50%>MAX COMBO {maxCombo}</size>\n" +
|
||||
$"<size=42%><color=#A9B7C0>P {perfectCount} G {greatCount} GOOD {goodCount} MISS {missCount}</color></size>";
|
||||
return $"<line-height=76%><size=300%><color={GetRankColorHex()}>{Rank}</color></size>" +
|
||||
$"<pos=255><voffset=0.48em><size=92%>{score}</size></voffset>\n" +
|
||||
$"<pos=255><size=72%><color=#D7F7FF>MAX COMBO {maxCombo}</color></size>";
|
||||
}
|
||||
|
||||
private void CancelTweenById(int id)
|
||||
@@ -277,8 +306,8 @@ namespace VRBeats
|
||||
scoreLabel.text = $"{Mathf.CeilToInt(visualScore):N0}";
|
||||
if (comboLabel != null)
|
||||
comboLabel.text = currentCombo > 0
|
||||
? $"<size=42%><color=#E6F8FF>COMBO</color></size>\n<size=125%>{currentCombo}</size>"
|
||||
: "<size=42%><color=#E6F8FF>COMBO</color></size>\n<size=125%>0</size>";
|
||||
? $"<size=18><color=#E6F8FF>COMBO</color></size>\n<size=42>{currentCombo}</size>"
|
||||
: "<size=18><color=#E6F8FF>COMBO</color></size>\n<size=42>0</size>";
|
||||
if (accuracyLabel != null)
|
||||
accuracyLabel.text = $"{AccuracyPercent:0.0}%";
|
||||
if (rankLabel != null)
|
||||
@@ -287,6 +316,10 @@ namespace VRBeats
|
||||
progressLabel.text = songDuration > 0.0f
|
||||
? $"{FormatTime(songCurrentTime)} / {FormatTime(songDuration)}"
|
||||
: "";
|
||||
if (progressBarFill != null)
|
||||
SetProgressBarFill(songDuration > 0.0f
|
||||
? Mathf.Clamp01(songCurrentTime / songDuration)
|
||||
: 0.0f);
|
||||
|
||||
if (judgementLabel == null)
|
||||
return;
|
||||
@@ -326,13 +359,13 @@ namespace VRBeats
|
||||
else if (judgement == BeatJudgement.Great)
|
||||
{
|
||||
greatCount++;
|
||||
earnedAccuracyPoints += 700;
|
||||
earnedAccuracyPoints += 900;
|
||||
currentCombo++;
|
||||
}
|
||||
else if (judgement == BeatJudgement.Good)
|
||||
{
|
||||
goodCount++;
|
||||
earnedAccuracyPoints += 400;
|
||||
earnedAccuracyPoints += 700;
|
||||
currentCombo++;
|
||||
}
|
||||
else
|
||||
@@ -351,10 +384,10 @@ namespace VRBeats
|
||||
|
||||
private static float GetComboMultiplier(int combo)
|
||||
{
|
||||
if (combo >= 200) return 1.5f;
|
||||
if (combo >= 100) return 1.35f;
|
||||
if (combo >= 50) return 1.2f;
|
||||
if (combo >= 20) return 1.1f;
|
||||
if (combo >= 50) return 1.5f;
|
||||
if (combo >= 30) return 1.35f;
|
||||
if (combo >= 15) return 1.2f;
|
||||
if (combo >= 5) return 1.1f;
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
@@ -383,11 +416,11 @@ namespace VRBeats
|
||||
private float GetComboTierProgress()
|
||||
{
|
||||
int lower = 0;
|
||||
int upper = 20;
|
||||
if (currentCombo >= 200) return 1.0f;
|
||||
if (currentCombo >= 100) { lower = 100; upper = 200; }
|
||||
else if (currentCombo >= 50) { lower = 50; upper = 100; }
|
||||
else if (currentCombo >= 20) { lower = 20; upper = 50; }
|
||||
int upper = 5;
|
||||
if (currentCombo >= 50) return 1.0f;
|
||||
if (currentCombo >= 30) { lower = 30; upper = 50; }
|
||||
else if (currentCombo >= 15) { lower = 15; upper = 30; }
|
||||
else if (currentCombo >= 5) { lower = 5; upper = 15; }
|
||||
|
||||
return Mathf.InverseLerp(lower, upper, currentCombo);
|
||||
}
|
||||
@@ -398,22 +431,54 @@ namespace VRBeats
|
||||
if (applyHudPlacement && rect != null)
|
||||
rect.anchoredPosition = hudAnchoredPosition;
|
||||
|
||||
ConfigureText(scoreLabel, new Vector2(-255.0f, -18.0f), new Vector2(220.0f, 40.0f), 26, Color.white, TextAnchor.MiddleLeft);
|
||||
ConfigureText(multiplierLabel, new Vector2(255.0f, 36.0f), new Vector2(100.0f, 68.0f), 34, Color.white, TextAnchor.MiddleCenter);
|
||||
ConfigureImage(multiplierLoader, new Vector2(255.0f, 36.0f), new Vector2(104.0f, 104.0f));
|
||||
comboLabel = comboLabel != null ? comboLabel : FindHudText("Combo");
|
||||
accuracyLabel = accuracyLabel != null ? accuracyLabel : FindHudText("Accuracy");
|
||||
rankLabel = rankLabel != null ? rankLabel : FindHudText("Rank");
|
||||
judgementLabel = judgementLabel != null ? judgementLabel : FindHudText("Judgement");
|
||||
progressLabel = progressLabel != null ? progressLabel : FindHudText("SongProgress");
|
||||
progressBarBackground = progressBarBackground != null ? progressBarBackground : FindHudImage("SongProgressBarBackground");
|
||||
progressBarFill = progressBarFill != null ? progressBarFill : FindHudImage("SongProgressBarFill");
|
||||
|
||||
if (!createMissingHudLabels)
|
||||
return;
|
||||
|
||||
comboLabel ??= CreateHudText("Combo", new Vector2(-255.0f, 74.0f), new Vector2(220.0f, 112.0f), 36, Color.white, TextAnchor.MiddleLeft);
|
||||
accuracyLabel ??= CreateHudText("Accuracy", new Vector2(-255.0f, -58.0f), new Vector2(220.0f, 34.0f), 20, new Color(0.88f, 0.95f, 1.0f, 1.0f), TextAnchor.MiddleLeft);
|
||||
rankLabel ??= CreateHudText("Rank", new Vector2(-255.0f, -105.0f), new Vector2(220.0f, 76.0f), 48, Color.white, TextAnchor.MiddleLeft);
|
||||
judgementLabel ??= CreateHudText("Judgement", new Vector2(0.0f, 112.0f), new Vector2(260.0f, 54.0f), 28, new Color(0.25f, 0.95f, 1.0f, 1.0f), TextAnchor.MiddleCenter);
|
||||
progressLabel ??= CreateHudText("SongProgress", new Vector2(255.0f, -62.0f), new Vector2(180.0f, 34.0f), 18, Color.white, TextAnchor.MiddleCenter);
|
||||
comboLabel ??= CreateHudText("Combo");
|
||||
accuracyLabel ??= CreateHudText("Accuracy");
|
||||
rankLabel ??= CreateHudText("Rank");
|
||||
judgementLabel ??= CreateHudText("Judgement");
|
||||
progressLabel ??= CreateHudText("SongProgress");
|
||||
progressBarBackground ??= CreateHudImage("SongProgressBarBackground");
|
||||
progressBarFill ??= CreateHudImage("SongProgressBarFill");
|
||||
ringBackground = ringBackground != null ? ringBackground : FindHudImage("MultiplierRingBg");
|
||||
ringBackground ??= CreateHudImage("MultiplierRingBg");
|
||||
|
||||
ConfigureText(comboLabel, new Vector2(-335.0f, 92.0f), new Vector2(190.0f, 118.0f), 34, Color.white, TextAnchor.MiddleCenter);
|
||||
ConfigureText(scoreLabel, new Vector2(-335.0f, 10.0f), new Vector2(190.0f, 42.0f), 22, Color.white, TextAnchor.MiddleCenter);
|
||||
ConfigureText(accuracyLabel, new Vector2(-335.0f, -34.0f), new Vector2(190.0f, 32.0f), 18, new Color(0.84f, 0.94f, 1.0f, 1.0f), TextAnchor.MiddleCenter);
|
||||
ConfigureText(rankLabel, new Vector2(-335.0f, -92.0f), new Vector2(190.0f, 72.0f), 48, Color.white, TextAnchor.MiddleCenter);
|
||||
ConfigureText(judgementLabel, new Vector2(0.0f, 118.0f), new Vector2(280.0f, 56.0f), 28, new Color(0.25f, 0.95f, 1.0f, 1.0f), TextAnchor.MiddleCenter);
|
||||
ConfigureText(multiplierLabel, new Vector2(335.0f, 38.0f), new Vector2(118.0f, 76.0f), 34, Color.white, TextAnchor.MiddleCenter);
|
||||
ConfigureText(progressLabel, new Vector2(335.0f, -75.0f), new Vector2(180.0f, 30.0f), 17, Color.white, TextAnchor.MiddleCenter);
|
||||
ConfigureImage(multiplierLoader, new Vector2(335.0f, 38.0f), new Vector2(112.0f, 112.0f), new Color(1.0f, 1.0f, 1.0f, 0.78f));
|
||||
ConfigureImage(ringBackground, new Vector2(335.0f, 38.0f), new Vector2(112.0f, 112.0f), new Color(1.0f, 1.0f, 1.0f, 0.15f));
|
||||
if (ringBackground != null && multiplierLoader != null)
|
||||
{
|
||||
ringBackground.sprite = multiplierLoader.sprite;
|
||||
ringBackground.type = Image.Type.Simple;
|
||||
ringBackground.transform.SetSiblingIndex(multiplierLoader.transform.GetSiblingIndex());
|
||||
}
|
||||
ConfigureImage(progressBarBackground, new Vector2(335.0f, -48.0f), new Vector2(ProgressBarWidth, 5.0f), new Color(1.0f, 1.0f, 1.0f, 0.22f));
|
||||
ConfigureImage(progressBarFill, new Vector2(335.0f - ProgressBarWidth * 0.5f, -48.0f), new Vector2(ProgressBarWidth, 5.0f), Color.white);
|
||||
if (progressBarFill != null)
|
||||
{
|
||||
RectTransform fillRect = progressBarFill.rectTransform;
|
||||
fillRect.pivot = new Vector2(0.0f, 0.5f);
|
||||
SetProgressBarFill(0.0f);
|
||||
}
|
||||
comboBaseScale = comboLabel != null ? comboLabel.transform.localScale : Vector3.one;
|
||||
}
|
||||
|
||||
private Text CreateHudText(string name, Vector2 anchoredPosition, Vector2 size, int fontSize, Color color, TextAnchor alignment)
|
||||
private Text CreateHudText(string name)
|
||||
{
|
||||
GameObject textObject = new GameObject(name);
|
||||
textObject.layer = gameObject.layer;
|
||||
@@ -422,15 +487,27 @@ namespace VRBeats
|
||||
RectTransform rect = textObject.AddComponent<RectTransform>();
|
||||
textObject.AddComponent<CanvasRenderer>();
|
||||
Text text = textObject.AddComponent<Text>();
|
||||
ConfigureText(text, anchoredPosition, size, fontSize, color, alignment);
|
||||
return text;
|
||||
}
|
||||
|
||||
private Image CreateHudImage(string name)
|
||||
{
|
||||
GameObject imageObject = new GameObject(name);
|
||||
imageObject.layer = gameObject.layer;
|
||||
imageObject.transform.SetParent(transform, false);
|
||||
|
||||
imageObject.AddComponent<CanvasRenderer>();
|
||||
return imageObject.AddComponent<Image>();
|
||||
}
|
||||
|
||||
private static void ConfigureText(Text text, Vector2 anchoredPosition, Vector2 size, int fontSize, Color color, TextAnchor alignment)
|
||||
{
|
||||
if (text == null)
|
||||
return;
|
||||
|
||||
if (text.font == null)
|
||||
text.font = HudFont;
|
||||
|
||||
RectTransform rect = text.rectTransform;
|
||||
rect.anchorMin = new Vector2(0.5f, 0.5f);
|
||||
rect.anchorMax = new Vector2(0.5f, 0.5f);
|
||||
@@ -452,6 +529,11 @@ namespace VRBeats
|
||||
}
|
||||
|
||||
private static void ConfigureImage(Image image, Vector2 anchoredPosition, Vector2 size)
|
||||
{
|
||||
ConfigureImage(image, anchoredPosition, size, new Color(1.0f, 1.0f, 1.0f, 0.85f));
|
||||
}
|
||||
|
||||
private static void ConfigureImage(Image image, Vector2 anchoredPosition, Vector2 size, Color color)
|
||||
{
|
||||
if (image == null)
|
||||
return;
|
||||
@@ -461,16 +543,49 @@ namespace VRBeats
|
||||
rect.anchorMax = new Vector2(0.5f, 0.5f);
|
||||
rect.anchoredPosition = anchoredPosition;
|
||||
rect.sizeDelta = size;
|
||||
image.color = new Color(1.0f, 1.0f, 1.0f, 0.85f);
|
||||
image.color = color;
|
||||
image.raycastTarget = false;
|
||||
}
|
||||
|
||||
private void SetProgressBarFill(float progress)
|
||||
{
|
||||
if (progressBarFill == null)
|
||||
return;
|
||||
|
||||
RectTransform rect = progressBarFill.rectTransform;
|
||||
rect.sizeDelta = new Vector2(ProgressBarWidth * Mathf.Clamp01(progress), rect.sizeDelta.y);
|
||||
}
|
||||
|
||||
private static Font HudFont
|
||||
{
|
||||
get
|
||||
{
|
||||
if (hudFont == null)
|
||||
hudFont = Resources.GetBuiltinResource<Font>("LegacyRuntime.ttf");
|
||||
|
||||
return hudFont;
|
||||
}
|
||||
}
|
||||
|
||||
private Text FindHudText(string objectName)
|
||||
{
|
||||
Transform child = transform.Find(objectName);
|
||||
return child != null ? child.GetComponent<Text>() : null;
|
||||
}
|
||||
|
||||
private Image FindHudImage(string objectName)
|
||||
{
|
||||
Transform child = transform.Find(objectName);
|
||||
return child != null ? child.GetComponent<Image>() : null;
|
||||
}
|
||||
|
||||
private string GetRankColorHex()
|
||||
{
|
||||
switch (Rank)
|
||||
{
|
||||
case "M": return "#E8B7FF";
|
||||
case "S+": return "#41F2FF";
|
||||
case "S": return "#69FFD1";
|
||||
case "S": return "#FFD95C";
|
||||
case "A": return "#B9FF72";
|
||||
case "B": return "#FFE06A";
|
||||
case "C": return "#FFB15C";
|
||||
@@ -496,5 +611,20 @@ namespace VRBeats
|
||||
int remainingSeconds = wholeSeconds % 60;
|
||||
return $"{minutes}:{remainingSeconds:00}";
|
||||
}
|
||||
|
||||
private static void SetSaberVisibility(bool visible)
|
||||
{
|
||||
VR_Saber[] sabers = FindObjectsByType<VR_Saber>(FindObjectsSortMode.None);
|
||||
for (int i = 0; i < sabers.Length; i++)
|
||||
{
|
||||
if (sabers[i] == null)
|
||||
continue;
|
||||
|
||||
if (visible)
|
||||
sabers[i].MakeVisible();
|
||||
else
|
||||
sabers[i].MakeInvisible();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: 7aabf7bc54d695644952b5c737f1c915, type: 3}
|
||||
m_Name: Settings
|
||||
m_EditorClassIdentifier:
|
||||
rightColor: {r: 0, g: 0.6002884, b: 1, a: 1}
|
||||
rightColor: {r: 0.03, g: 0.32, b: 1, a: 1}
|
||||
leftColor: {r: 1, g: 0, b: 0, a: 1}
|
||||
glowIntensity: 40
|
||||
targetTravelDistance: 40
|
||||
|
||||
Reference in New Issue
Block a user