gameplay所有基本功能都装了,加入了全局警告。加入飘字等各种东西。
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
namespace Bansonic
|
||||
{
|
||||
/// <summary>
|
||||
/// 全局通知系统入口
|
||||
/// 使用方式:gNotice.message.display("内容");
|
||||
/// </summary>
|
||||
public static class gNotice
|
||||
{
|
||||
// --- 事件定义:用于通知 UI 层 ---
|
||||
/// <summary>
|
||||
/// 当任何通知被显示时触发
|
||||
/// 参数1:类型前缀(如 [Info])
|
||||
/// 参数2:消息内容
|
||||
/// </summary>
|
||||
public static event Action<string, string, float?, float?> OnNoticeDisplay;
|
||||
|
||||
/// <summary>
|
||||
/// 当任何通知被中断显示时触发
|
||||
/// </summary>
|
||||
public static event Action OnNoticeInterrupt;
|
||||
|
||||
|
||||
// --- 静态实例定义 (直接注入行为,无需枚举) ---
|
||||
|
||||
/// <summary>普通消息</summary>
|
||||
public static readonly NoticeChannel message = new NoticeChannel("[Info]", Debug.Log);
|
||||
|
||||
/// <summary>建议</summary>
|
||||
public static readonly NoticeChannel recommendation = new NoticeChannel("[Recommendation]", Debug.Log);
|
||||
|
||||
/// <summary>警告</summary>
|
||||
public static readonly NoticeChannel warning = new NoticeChannel("[Warning]", Debug.LogWarning);
|
||||
|
||||
/// <summary>错误</summary>
|
||||
public static readonly NoticeChannel error = new NoticeChannel("[Error]", Debug.LogError);
|
||||
|
||||
/// <summary>警报</summary>
|
||||
public static readonly NoticeChannel alarm = new NoticeChannel("[Alarm]", Debug.LogWarning);
|
||||
|
||||
|
||||
// --- 内部核心实现 ---
|
||||
|
||||
/// <summary>
|
||||
/// 通知通道类:封装了通用的 display 和 interrupt 逻辑
|
||||
/// </summary>
|
||||
public class NoticeChannel
|
||||
{
|
||||
private readonly string _prefix;
|
||||
private readonly Action<object> _logAction;
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="prefix">日志前缀,如 [Info]</param>
|
||||
/// <param name="logAction">具体的日志输出方法,如 Debug.Log</param>
|
||||
internal NoticeChannel(string prefix, Action<object> logAction)
|
||||
{
|
||||
_prefix = prefix;
|
||||
_logAction = logAction;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 显示消息
|
||||
/// </summary>
|
||||
public void display(object message, float? waitTime = null, float? fadeTotalTime = null)
|
||||
{
|
||||
string content = message?.ToString() ?? "null";
|
||||
_logAction($"{_prefix} {content}");
|
||||
|
||||
// 触发 UI 事件
|
||||
OnNoticeDisplay?.Invoke(_prefix, content, waitTime, fadeTotalTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 立即终止当前正在展示的全部警告prefab
|
||||
/// </summary>
|
||||
public void interrupt()
|
||||
{
|
||||
// 触发 UI 事件
|
||||
OnNoticeInterrupt?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f18837bb8147555448daa0c0b161e81a
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
@@ -0,0 +1,156 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1b1e113e4f51df34c981c4ebc66fb1b7
|
||||
TextureImporter:
|
||||
internalIDToNameTable:
|
||||
- first:
|
||||
213: 7676382691749075051
|
||||
second: TIP_0
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 985, y: 730, z: 985, w: 753}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites:
|
||||
- serializedVersion: 2
|
||||
name: TIP_0
|
||||
rect:
|
||||
serializedVersion: 2
|
||||
x: 989
|
||||
y: 736
|
||||
width: 576
|
||||
height: 64
|
||||
alignment: 0
|
||||
pivot: {x: 0.5, y: 0.5}
|
||||
border: {x: 0, y: 0, z: 0, w: 0}
|
||||
customData:
|
||||
outline: []
|
||||
physicsShape: []
|
||||
tessellationDetail: -1
|
||||
bones: []
|
||||
spriteID: b6819ad036df78a60800000000000000
|
||||
internalID: 7676382691749075051
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 1537655665
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable:
|
||||
TIP_0: 7676382691749075051
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,6 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class _globalNoticeSystem : MonoBehaviour
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0b0c42cdd2b31504ab977f0e2d0a77ae
|
||||
@@ -0,0 +1,220 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
// using TMPro;
|
||||
using System.Collections;
|
||||
using Bansonic;
|
||||
|
||||
public class _gnp : MonoBehaviour
|
||||
{
|
||||
private const float DEFAULT_DISPLAY_DURATION = 0.5f;
|
||||
private const float DEFAULT_FADE_TOTAL_TIME = 0.25f;
|
||||
private const float DEFAULT_FADE_UP_DISTANCE = 20f;
|
||||
private const float CANVAS_PLANE_DISTANCE = 10f;
|
||||
private const string PREFAB_RESOURCE_NAME = "GlobalNoticeSystem";
|
||||
private const string SCENE_INSTANCE_NAME = "GlobalNoticeSystem_SceneInstance";
|
||||
|
||||
[Header("UI Components")]
|
||||
[SerializeField] private Text _noticeText;
|
||||
[SerializeField] private Image _iconImage;
|
||||
[SerializeField] private CanvasGroup _canvasGroup;
|
||||
|
||||
[Header("Icon Colors")]
|
||||
[SerializeField] private Color _colorMessage = Color.white;
|
||||
[SerializeField] private Color _colorRecommendation = Color.white;
|
||||
[SerializeField] private Color _colorWarning = Color.yellow;
|
||||
[SerializeField] private Color _colorError = Color.red;
|
||||
[SerializeField] private Color _colorAlarm = Color.yellow;
|
||||
|
||||
[Header("Settings")]
|
||||
[SerializeField] private float _displayDuration = DEFAULT_DISPLAY_DURATION;
|
||||
[SerializeField] private float _fade_up_distance = DEFAULT_FADE_UP_DISTANCE;
|
||||
[SerializeField] private float _fadeTotalTime = DEFAULT_FADE_TOTAL_TIME;
|
||||
|
||||
private Coroutine _fadeCoroutine;
|
||||
private RectTransform _rectTransform;
|
||||
private Vector3 _initialLocalPosition;
|
||||
|
||||
private static _gnp _currentInstance;
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
|
||||
private static void InitGlobalListener()
|
||||
{
|
||||
// 确保只订阅一次,避免重复
|
||||
gNotice.OnNoticeDisplay -= StaticHandleDisplay;
|
||||
gNotice.OnNoticeInterrupt -= StaticHandleInterrupt;
|
||||
|
||||
gNotice.OnNoticeDisplay += StaticHandleDisplay;
|
||||
gNotice.OnNoticeInterrupt += StaticHandleInterrupt;
|
||||
}
|
||||
|
||||
private static void StaticHandleDisplay(string prefix, string message, float? waitTime, float? fadeTotalTime)
|
||||
{
|
||||
// 如果已有实例,先销毁(单例模式,覆盖旧消息)
|
||||
if (_currentInstance != null)
|
||||
{
|
||||
Destroy(_currentInstance.gameObject);
|
||||
}
|
||||
|
||||
GameObject prefab = Resources.Load<GameObject>(PREFAB_RESOURCE_NAME);
|
||||
if (prefab == null) return;
|
||||
|
||||
GameObject instance = Instantiate(prefab);
|
||||
instance.name = SCENE_INSTANCE_NAME;
|
||||
_currentInstance = instance.GetComponent<_gnp>();
|
||||
|
||||
if (_currentInstance != null)
|
||||
{
|
||||
_currentInstance.Display(prefix, message, waitTime, fadeTotalTime);
|
||||
}
|
||||
}
|
||||
|
||||
private static void StaticHandleInterrupt()
|
||||
{
|
||||
if (_currentInstance != null)
|
||||
{
|
||||
_currentInstance.Interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_rectTransform = transform as RectTransform;
|
||||
if (_rectTransform != null)
|
||||
{
|
||||
_initialLocalPosition = _rectTransform.localPosition;
|
||||
}
|
||||
|
||||
if (_canvasGroup == null)
|
||||
{
|
||||
_canvasGroup = GetComponent<CanvasGroup>();
|
||||
if (_canvasGroup == null)
|
||||
{
|
||||
_canvasGroup = gameObject.AddComponent<CanvasGroup>();
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化 Canvas 设置
|
||||
Canvas canvas = GetComponent<Canvas>();
|
||||
if (canvas != null && canvas.renderMode == RenderMode.ScreenSpaceCamera)
|
||||
{
|
||||
Camera mainCam = Camera.main;
|
||||
if (mainCam != null)
|
||||
{
|
||||
canvas.worldCamera = mainCam;
|
||||
canvas.planeDistance = CANVAS_PLANE_DISTANCE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Camera anyCam = FindFirstObjectByType<Camera>();
|
||||
if (anyCam != null)
|
||||
{
|
||||
canvas.worldCamera = anyCam;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SetComponentsActive(false);
|
||||
SetCanvasAlpha(0f);
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
// 实例被启用时的逻辑(如果需要)
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
// 实例被禁用时的逻辑(如果需要)
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (_currentInstance == this)
|
||||
{
|
||||
_currentInstance = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Display(string prefix, string message, float? waitTime, float? fadeTotalTime)
|
||||
{
|
||||
Color iconColor = GetColorByPrefix(prefix);
|
||||
float wait = waitTime ?? _displayDuration;
|
||||
float fade = fadeTotalTime ?? _fadeTotalTime;
|
||||
|
||||
if (_noticeText != null) _noticeText.text = message ?? "null";
|
||||
if (_iconImage != null) _iconImage.color = iconColor;
|
||||
|
||||
if (_rectTransform != null)
|
||||
{
|
||||
_rectTransform.localPosition = _initialLocalPosition;
|
||||
}
|
||||
|
||||
SetCanvasAlpha(1f);
|
||||
SetComponentsActive(true);
|
||||
transform.SetAsLastSibling();
|
||||
|
||||
if (_fadeCoroutine != null) StopCoroutine(_fadeCoroutine);
|
||||
_fadeCoroutine = StartCoroutine(FadeRoutine(wait, fade));
|
||||
}
|
||||
|
||||
public void Interrupt()
|
||||
{
|
||||
// 立即销毁
|
||||
if (gameObject != null)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator FadeRoutine(float displayDuration, float fadeTotalTime)
|
||||
{
|
||||
if (displayDuration > 0f)
|
||||
{
|
||||
yield return new WaitForSeconds(displayDuration);
|
||||
}
|
||||
|
||||
if (fadeTotalTime <= 0f)
|
||||
{
|
||||
SetCanvasAlpha(0f);
|
||||
Destroy(gameObject);
|
||||
yield break;
|
||||
}
|
||||
|
||||
float elapsed = 0f;
|
||||
while (elapsed < fadeTotalTime)
|
||||
{
|
||||
elapsed += Time.deltaTime;
|
||||
float t = Mathf.Clamp01(elapsed / fadeTotalTime);
|
||||
SetCanvasAlpha(1f - t);
|
||||
if (_rectTransform != null)
|
||||
{
|
||||
_rectTransform.localPosition = _initialLocalPosition + Vector3.up * (_fade_up_distance * t);
|
||||
}
|
||||
yield return null;
|
||||
}
|
||||
|
||||
SetCanvasAlpha(0f);
|
||||
Destroy(gameObject);
|
||||
}
|
||||
|
||||
private void SetComponentsActive(bool isActive)
|
||||
{
|
||||
if (_noticeText != null) _noticeText.gameObject.SetActive(isActive);
|
||||
if (_iconImage != null) _iconImage.gameObject.SetActive(isActive);
|
||||
}
|
||||
|
||||
private void SetCanvasAlpha(float value)
|
||||
{
|
||||
if (_canvasGroup != null) _canvasGroup.alpha = value;
|
||||
}
|
||||
|
||||
private Color GetColorByPrefix(string prefix)
|
||||
{
|
||||
if (prefix.Contains("Info")) return _colorMessage;
|
||||
if (prefix.Contains("Recommendation")) return _colorRecommendation;
|
||||
if (prefix.Contains("Warning")) return _colorWarning;
|
||||
if (prefix.Contains("Error")) return _colorError;
|
||||
if (prefix.Contains("Alarm")) return _colorAlarm;
|
||||
return _colorMessage;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fc4356408408c7a4981b59a39be930f3
|
||||
Reference in New Issue
Block a user