Game Overlays (#280)

* add accuracy display

* temp BG for show

* separate overlays prefab

make proper shader for star effects

* aim shakiness display

* implement testing skill star

* fully functional skill star

* separate section display from editor

* fully separate chart section display from timeline

* add section to overlays

* fix nullreference issues

* start game layout settings

* add game settings script

* fix nonfunctioning scoring

* invert y position logic on timing bar

* add perfect challenge functionality

* fix section not showing up in editor

add perfect challenge option

* add timing display minimal mode

* Update PerfectAndPractice.png

* show gismo for minigame bounds in editor

* add ability to disable overlays in editor

* prepare medals

add new timing display graphic

* hide screen preview

* per-axis camera control

added per request

* section medals basic functionality

* add medal get animations

* fix bug with perfect icons

* visual enhancements

* adjust look of timing display minmode

address audio ducking issues(?)

* prepare overlay lyt editor

add viewport pan, rotate, scale
adjust audio setting

* add layout editor UI elements

* dynamic overlay creation

* fix default single timing disp

* set up overlay settings controls

* start UI events

* runtime uuid for component reference

* layout editor affects overlay elements

* show overlay element previews while editing

* advanced audio settings

* fix bug in drop-down creation

* fallback defaults for the new stuff

* fix textbox & overlay visibility bugs
This commit is contained in:
minenice55
2023-03-10 23:51:22 -05:00
committed by GitHub
parent 11d4abf1eb
commit d5ae99d8ba
136 changed files with 131638 additions and 1043 deletions

View File

@ -0,0 +1,54 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using HeavenStudio.Editor;
namespace HeavenStudio.Common
{
public class ChartSectionDisplay : MonoBehaviour
{
[SerializeField] private TMP_Text SectionText;
[SerializeField] private Slider SectionProgress;
// Start is called before the first frame update
void Start()
{
GameManager.instance.onSectionChange += OnSectionChange;
GameManager.instance.onBeatChanged += OnBeatChanged;
gameObject.SetActive(GameManager.instance.currentSection != null);
}
// Update is called once per frame
void Update()
{
SectionProgress.value = GameManager.instance.sectionProgress;
}
public void OnBeatChanged(float beat)
{
gameObject.SetActive(GameManager.instance.currentSection != null);
SectionProgress.value = GameManager.instance.sectionProgress;
}
public void OnSectionChange(DynamicBeatmap.ChartSection section)
{
if (section != null)
{
gameObject.SetActive(true);
SectionText.text = section.sectionName;
SectionProgress.value = GameManager.instance.sectionProgress;
if (PersistentDataManager.gameSettings.perfectChallengeType == PersistentDataManager.PerfectChallengeType.Off) return;
if (!OverlaysManager.OverlaysEnabled) return;
if (section.startPerfect && GoForAPerfect.instance != null && GoForAPerfect.instance.perfect && !GoForAPerfect.instance.gameObject.activeSelf)
{
GoForAPerfect.instance.Enable(section.beat);
}
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 52530e94ebdc2e343a3aa77a9dfd8e71
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,123 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using HeavenStudio.Util;
namespace HeavenStudio.Common
{
public class GoForAPerfect : MonoBehaviour
{
public static GoForAPerfect instance { get; set; }
[SerializeField] Animator texAnim;
[SerializeField] Animator pAnim;
private bool active = false;
private bool hiddenActive = false;
public bool perfect;
Conductor cond;
float lastReportedBeat = 0f;
float currentBeat = 0f;
long currentBlink = 0;
private void Awake()
{
instance = this;
}
private void Start()
{
perfect = true;
cond = Conductor.instance;
}
private void Update() {
gameObject.SetActive(hiddenActive);
if (!active) return;
if (!OverlaysManager.OverlaysEnabled) return;
if (cond == null || !cond.isPlaying) return;
if (cond.ReportBeat(ref lastReportedBeat))
{
currentBeat = lastReportedBeat;
if (currentBlink != 0)
{
currentBlink++;
if (currentBlink % 2 == 0)
{
texAnim.Play("GoForAPerfect_Blink", -1, 0);
}
else
{
texAnim.Play("GoForAPerfect_Blink2", -1, 0);
}
}
else
{
currentBlink++;
}
}
else if (cond.songPositionInBeats < lastReportedBeat)
{
lastReportedBeat = Mathf.Round(cond.songPositionInBeats);
}
}
public void Hit()
{
if (!active) return;
if (!OverlaysManager.OverlaysEnabled) return;
pAnim.Play("PerfectIcon_Hit", 0, 0);
}
public void Miss()
{
perfect = false;
if (!active) return;
SetInactive();
if (!OverlaysManager.OverlaysEnabled)
{
hiddenActive = false;
return;
}
GameProfiler.instance.perfect = false;
texAnim.Play("GoForAPerfect_Miss");
pAnim.Play("PerfectIcon_Miss", -1, 0);
Jukebox.PlayOneShot("perfectMiss");
}
public void Enable(double startBeat)
{
SetActive();
gameObject.SetActive(true);
pAnim.gameObject.SetActive(true);
texAnim.gameObject.SetActive(true);
texAnim.Play("GoForAPerfect_Idle");
currentBlink = 0;
}
public void Disable()
{
SetInactive();
gameObject.SetActive(false);
}
public void SetActive()
{
hiddenActive = true;
active = true;
}
public void SetInactive()
{
active = false;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9e5c7679bb002f04980d7554b101f24b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,284 @@
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.UI;
namespace HeavenStudio.Common
{
public class OverlaysManager : MonoBehaviour
{
public static OverlaysManager instance { get; private set; }
public static bool OverlaysEnabled;
const float WIDTH_SPAN = 10f;
const float HEIGHT_SPAN = 10f * (9f / 16f);
[Header("Prefabs")]
[SerializeField] GameObject TimingDisplayPrefab;
[SerializeField] GameObject SkillStarPrefab;
[SerializeField] GameObject ChartSectionPrefab;
[Header("Components")]
[SerializeField] Transform ComponentHolder;
List<OverlaysManager.OverlayOption> lytElements = new List<OverlaysManager.OverlayOption>();
// Start is called before the first frame update
void Start()
{
instance = this;
RefreshOverlaysLayout();
}
// Update is called once per frame
void Update()
{
}
public void TogleOverlaysVisibility(bool visible)
{
OverlaysEnabled = visible;
RepositionElements();
}
public void RefreshOverlaysLayout()
{
if (PersistentDataManager.gameSettings.timingDisplayComponents == null || PersistentDataManager.gameSettings.timingDisplayComponents.Count == 0)
{
PersistentDataManager.gameSettings.timingDisplayComponents = new List<TimingDisplayComponent>()
{
TimingDisplayComponent.CreateDefaultDual()
};
}
if (PersistentDataManager.gameSettings.skillStarComponents == null || PersistentDataManager.gameSettings.skillStarComponents.Count == 0)
{
PersistentDataManager.gameSettings.skillStarComponents = new List<SkillStarComponent>()
{
SkillStarComponent.CreateDefault()
};
}
if (PersistentDataManager.gameSettings.sectionComponents == null || PersistentDataManager.gameSettings.sectionComponents.Count == 0)
{
PersistentDataManager.gameSettings.sectionComponents = new List<SectionComponent>()
{
SectionComponent.CreateDefault()
};
}
lytElements = new List<OverlaysManager.OverlayOption>();
foreach (var c in PersistentDataManager.gameSettings.timingDisplayComponents) { lytElements.Add(c); }
foreach (var c in PersistentDataManager.gameSettings.skillStarComponents) { lytElements.Add(c); }
foreach (var c in PersistentDataManager.gameSettings.sectionComponents) { lytElements.Add(c); }
foreach (Transform child in ComponentHolder.transform)
{
Destroy(child.gameObject);
}
foreach (var c in lytElements)
{
if (c is TimingDisplayComponent) {
Debug.Log("TimingDisplayComponent");
c.CreateElement(TimingDisplayPrefab, ComponentHolder);
}
else if (c is SkillStarComponent) {
Debug.Log("SkillStarComponent");
c.CreateElement(SkillStarPrefab, ComponentHolder);
}
else if (c is SectionComponent) {
Debug.Log("SectionComponent");
c.CreateElement(ChartSectionPrefab, ComponentHolder);
}
c.PositionElement();
}
}
void RepositionElements()
{
lytElements = new List<OverlaysManager.OverlayOption>();
foreach (var c in PersistentDataManager.gameSettings.timingDisplayComponents) { lytElements.Add(c); }
foreach (var c in PersistentDataManager.gameSettings.skillStarComponents) { lytElements.Add(c); }
foreach (var c in PersistentDataManager.gameSettings.sectionComponents) { lytElements.Add(c); }
foreach (var c in lytElements)
{
c.PositionElement();
}
}
[Serializable]
public class TimingDisplayComponent : OverlayOption
{
public enum TimingDisplayType
{
Dual,
Single,
}
[NonSerialized] GameObject go2;
[SerializeField] public TimingDisplayType tdType;
public TimingDisplayComponent(TimingDisplayType type, bool enable, Vector2 position, float scale, float rotation)
{
tdType = type;
this.enable = enable;
this.position = position;
this.scale = scale;
this.rotation = rotation;
}
public override void CreateElement(GameObject prefab, Transform holder)
{
if (go == null) go = Instantiate(prefab, holder);
if (go2 == null) go2 = Instantiate(prefab, holder);
}
public override void PositionElement()
{
if (go != null)
{
switch (tdType)
{
case TimingDisplayType.Dual:
go.transform.localPosition = position * new Vector2(WIDTH_SPAN, HEIGHT_SPAN) * new Vector2(-1, 1);
go.transform.localScale = Vector3.one * scale;
go.transform.localRotation = Quaternion.Euler(0, 0, -rotation);
go2.transform.localPosition = position * new Vector2(WIDTH_SPAN, HEIGHT_SPAN);
go2.transform.localScale = Vector3.one * scale;
go2.transform.localRotation = Quaternion.Euler(0, 0, rotation);
go.SetActive(enable && OverlaysManager.OverlaysEnabled);
go2.SetActive(enable && OverlaysManager.OverlaysEnabled);
break;
case TimingDisplayType.Single:
go.transform.localPosition = position * new Vector2(WIDTH_SPAN, HEIGHT_SPAN);
go.transform.localScale = Vector3.one * scale;
go.transform.localRotation = Quaternion.Euler(0, 0, rotation);
go.SetActive(enable && OverlaysManager.OverlaysEnabled);
go2.SetActive(false);
break;
}
}
}
public override void EnablePreview() {}
public override void DisablePreview() {}
public static TimingDisplayComponent CreateDefaultDual()
{
return new TimingDisplayComponent(TimingDisplayType.Dual, true, new Vector2(-0.84f, 0), 1f, 0f);
}
public static TimingDisplayComponent CreateDefaultSingle()
{
return new TimingDisplayComponent(TimingDisplayType.Single, true, new Vector2(0, -0.8f), 1f, 90f);
}
}
[Serializable]
public class SkillStarComponent : OverlayOption
{
public SkillStarComponent(bool enable, Vector2 position, float scale, float rotation)
{
this.enable = enable;
this.position = position;
this.scale = scale;
this.rotation = rotation;
}
public override void PositionElement()
{
if (go != null)
{
go.transform.localPosition = position * new Vector2(WIDTH_SPAN, HEIGHT_SPAN);
go.transform.localScale = Vector3.one * scale;
go.transform.localRotation = Quaternion.Euler(0, 0, rotation);
go.SetActive(enable && OverlaysManager.OverlaysEnabled);
}
}
public override void EnablePreview() { SkillStarManager.instance?.DoStarPreview(); }
public override void DisablePreview() { SkillStarManager.instance.ResetStarPreview(); }
public static SkillStarComponent CreateDefault()
{
return new SkillStarComponent(true, new Vector2(0.75f, -0.7f), 1f, 0f);
}
}
[Serializable]
public class SectionComponent : OverlayOption
{
public SectionComponent(bool enable, Vector2 position, float scale, float rotation)
{
this.enable = enable;
this.position = position;
this.scale = scale;
this.rotation = rotation;
}
public override void PositionElement()
{
if (go != null)
{
go.transform.localPosition = position * new Vector2(WIDTH_SPAN, HEIGHT_SPAN);
go.transform.localScale = Vector3.one * scale;
go.transform.localRotation = Quaternion.Euler(0, 0, rotation);
go.SetActive(enable && OverlaysManager.OverlaysEnabled);
}
}
public override void EnablePreview()
{
if (go != null)
{
go.GetComponent<Image>().enabled = true;
}
}
public override void DisablePreview()
{
if (go != null)
{
go.GetComponent<Image>().enabled = false;
}
}
public static SectionComponent CreateDefault()
{
return new SectionComponent(true, new Vector2(0.7f, 0.765f), 1f, 0f);
}
}
[Serializable]
public abstract class OverlayOption
{
static long uuidCounter = 0;
[NonSerialized] protected GameObject go;
[NonSerialized] public long uuid = GenerateUUID();
[SerializeField] public bool enable;
[SerializeField] public Vector2 position;
[SerializeField] public float scale;
[SerializeField] public float rotation;
static long GenerateUUID()
{
return uuidCounter++;
}
public virtual void CreateElement(GameObject prefab, Transform holder)
{
if (go == null)
go = Instantiate(prefab, holder);
}
public abstract void PositionElement();
public abstract void EnablePreview();
public abstract void DisablePreview();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6c9513d62ced05840a5db89f2a529a71
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,77 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using HeavenStudio.Util;
using HeavenStudio.Games;
namespace HeavenStudio.Common
{
public class SectionMedalsManager : MonoBehaviour
{
public static SectionMedalsManager instance { get; private set; }
[SerializeField] GameObject MedalsHolder;
[SerializeField] GameObject MedalOkPrefab;
[SerializeField] GameObject MedalMissPrefab;
Conductor cond;
bool isMedalsStarted = false;
bool isMedalsEligible = true;
// Start is called before the first frame update
void Start()
{
instance = this;
cond = Conductor.instance;
GameManager.instance.onSectionChange += OnSectionChange;
}
// Update is called once per frame
void Update()
{
}
public void MakeIneligible()
{
isMedalsEligible = false;
}
public void Reset()
{
isMedalsStarted = false;
isMedalsEligible = true;
foreach (Transform child in MedalsHolder.transform)
{
Destroy(child.gameObject);
}
}
public void OnSectionChange(DynamicBeatmap.ChartSection section)
{
if (section == null) return;
Debug.Log(PersistentDataManager.gameSettings.isMedalOn);
if (PersistentDataManager.gameSettings.isMedalOn && !isMedalsStarted)
{
isMedalsStarted = true;
isMedalsEligible = true;
}
else
{
GameObject medal = Instantiate(isMedalsEligible ? MedalOkPrefab : MedalMissPrefab, MedalsHolder.transform);
medal.SetActive(true);
isMedalsEligible = true;
}
}
public void OnRemixEnd()
{
if (PersistentDataManager.gameSettings.isMedalOn && isMedalsStarted)
{
GameObject medal = Instantiate(isMedalsEligible ? MedalOkPrefab : MedalMissPrefab, MedalsHolder.transform);
medal.SetActive(true);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 93e2705ea532cf24d8c161d8762aeccc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,123 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using HeavenStudio.Util;
using HeavenStudio.Games;
namespace HeavenStudio.Common
{
public class SkillStarManager : MonoBehaviour
{
public enum StarState
{
None,
In,
Collected,
Out
}
public static SkillStarManager instance { get; private set; }
[SerializeField] private Animator starAnim;
[SerializeField] private ParticleSystem starParticle;
public float StarTargetTime { get { return starStart + starLength; } }
public bool IsEligible { get; private set; }
float starStart = float.MaxValue;
float starLength = float.MaxValue;
StarState state = StarState.None;
Conductor cond;
// Start is called before the first frame update
void Start()
{
instance = this;
cond = Conductor.instance;
}
// Update is called once per frame
void Update()
{
if (cond.songPositionInBeatsAsDouble > starStart && state == StarState.In)
{
double offset = cond.SecsToBeats(Minigame.AceStartTime()-1, cond.GetBpmAtBeat(StarTargetTime));
if (cond.songPositionInBeatsAsDouble <= starStart + starLength + offset)
starAnim.DoScaledAnimation("StarIn", starStart, starLength + (float)offset);
else
starAnim.Play("StarIn", -1, 1f);
offset = cond.SecsToBeats(Minigame.AceEndTime()-1, cond.GetBpmAtBeat(StarTargetTime));
if (cond.songPositionInBeatsAsDouble > starStart + starLength + offset)
KillStar();
}
}
public void DoStarPreview()
{
if (starAnim == null) return;
starAnim.Play("StarJust", -1, 0.5f);
starAnim.speed = 0f;
}
public void ResetStarPreview()
{
if (starAnim == null) return;
starAnim.Play("NoPose", -1, 0f);
starAnim.speed = 1f;
}
public void Reset()
{
IsEligible = false;
cond = Conductor.instance;
state = StarState.None;
starAnim.Play("NoPose", -1, 0f);
starAnim.speed = 1f;
starStart = float.MaxValue;
starLength = float.MaxValue;
}
public void DoStarIn(float beat, float length)
{
if (!OverlaysManager.OverlaysEnabled) return;
IsEligible = true;
state = StarState.In;
starStart = beat;
starLength = length;
TimingAccuracyDisplay.instance.StartStarFlash();
starAnim.DoScaledAnimation("StarIn", beat, length);
}
public bool DoStarJust()
{
if (state == StarState.In &&
cond.songPositionInBeatsAsDouble >= StarTargetTime + cond.SecsToBeats(Minigame.AceStartTime()-1, cond.GetBpmAtBeat(StarTargetTime)) &&
cond.songPositionInBeatsAsDouble <= StarTargetTime + cond.SecsToBeats(Minigame.AceEndTime()-1, cond.GetBpmAtBeat(StarTargetTime))
)
{
state = StarState.Collected;
starAnim.Play("StarJust", -1, 0f);
starParticle.Play();
Jukebox.PlayOneShot("skillStar");
TimingAccuracyDisplay.instance.StopStarFlash();
return true;
}
return false;
}
public void KillStar()
{
if (state == StarState.In && cond.songPositionInBeatsAsDouble >= starStart + starLength*0.5f || !cond.isPlaying)
{
IsEligible = false;
state = StarState.Out;
starAnim.Play("NoPose", -1, 0f);
TimingAccuracyDisplay.instance.StopStarFlash();
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0521855ace8165a44b98e3d0022da114
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,172 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using HeavenStudio.Games;
namespace HeavenStudio.Common
{
public class TimingAccuracyDisplay : MonoBehaviour
{
public enum Rating
{
NG,
OK,
Just
}
public static TimingAccuracyDisplay instance { get; private set; }
[SerializeField] GameObject NG;
[SerializeField] GameObject OK;
[SerializeField] GameObject Just;
[SerializeField] GameObject MinimalJust;
[SerializeField] GameObject MinimalOK;
[SerializeField] GameObject MinimalNG;
[SerializeField] Animator MetreAnim;
[SerializeField] Transform arrowTransform;
[SerializeField] Transform barTransform;
[SerializeField] Transform barJustTransform;
[SerializeField] Transform barOKTransform;
[SerializeField] Transform barNGTransform;
float targetArrowPos = 0f;
// Start is called before the first frame update
void Start()
{
instance = this;
}
// Update is called once per frame
void Update()
{
arrowTransform.localPosition = Vector3.Lerp(arrowTransform.localPosition, new Vector3(0, targetArrowPos, 0), 4f * Time.deltaTime);
}
public void ResetArrow()
{
targetArrowPos = 0f;
arrowTransform.localPosition = Vector3.zero;
StopStarFlash();
NG.GetComponent<ParticleSystem>().Stop();
OK.GetComponent<ParticleSystem>().Stop();
Just.GetComponent<ParticleSystem>().Stop();
MinimalNG.GetComponent<ParticleSystem>().Stop();
MinimalOK.GetComponent<ParticleSystem>().Stop();
MinimalJust.GetComponent<ParticleSystem>().Stop();
}
public void StartStarFlash()
{
MetreAnim.Play("StarWarn", -1, 0f);
}
public void StopStarFlash()
{
MetreAnim.Play("NoPose", -1, 0f);
}
public void MakeAccuracyVfx(double time, bool late = false)
{
if (!OverlaysManager.OverlaysEnabled) return;
GameObject it;
Rating type = Rating.NG;
// centre of the transfor would be "perfect ace"
// move the object up or down the bar depending on hit time
// use bar's scale Y for now, we're waiting for proper assets
// this probably doesn't work
float frac = 0f;
float y = barTransform.position.y;
// SetArrowPos(time);
// no Clamp() because double
time = System.Math.Max(Minigame.EarlyTime(), System.Math.Min(Minigame.EndTime(), time));
if (time >= Minigame.AceStartTime() && time <= Minigame.AceEndTime())
{
type = Rating.Just;
frac = (float)((time - Minigame.AceStartTime()) / (Minigame.AceEndTime() - Minigame.AceStartTime()));
y = barJustTransform.localScale.y * frac - (barJustTransform.localScale.y * 0.5f);
}
else
{
if (time > 1.0)
{
// goes "down"
if (time <= Minigame.LateTime())
{
type = Rating.OK;
frac = (float)((time - Minigame.AceEndTime()) / (Minigame.LateTime() - Minigame.AceEndTime()));
y = ((barOKTransform.localScale.y - barJustTransform.localScale.y) * frac) + barJustTransform.localScale.y;
}
else
{
type = Rating.NG;
frac = (float)((time - Minigame.LateTime()) / (Minigame.EndTime() - Minigame.LateTime()));
y = ((barNGTransform.localScale.y - barOKTransform.localScale.y) * frac) + barOKTransform.localScale.y;
}
}
else
{
// goes "up"
if (time >= Minigame.PerfectTime())
{
type = Rating.OK;
frac = (float)((time - Minigame.PerfectTime()) / (Minigame.AceStartTime() - Minigame.PerfectTime()));
y = ((barOKTransform.localScale.y - barJustTransform.localScale.y) * -frac) - barJustTransform.localScale.y;
}
else
{
type = Rating.NG;
frac = (float)((time - Minigame.EarlyTime()) / (Minigame.PerfectTime() - Minigame.EarlyTime()));
y = ((barNGTransform.localScale.y - barOKTransform.localScale.y) * -frac) - barOKTransform.localScale.y;
}
}
y *= -0.5f;
}
targetArrowPos = (targetArrowPos + y) * 0.5f;
if (PersistentDataManager.gameSettings.timingDisplayMinMode)
{
switch (type)
{
case Rating.OK:
it = MinimalOK;
break;
case Rating.Just:
it = MinimalJust;
break;
default:
it = MinimalNG;
break;
}
}
else
{
switch (type)
{
case Rating.OK:
it = OK;
break;
case Rating.Just:
it = Just;
break;
default:
it = NG;
break;
}
}
it.transform.position = barTransform.position + new Vector3(0, barTransform.localScale.y * y, 0);
it.GetComponent<ParticleSystem>().Play();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a91127b0615e4d341bcde412b3e92f93
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: